---
title: A Practical Guide to Generating a Time Spline in dbt
description: Learn how to optimize your dbt workflows by converting a dim_dates CSV seed into a macro, saving time and compute resources on every build.
---

[Recce | Blog](https://blog.reccehq.com)

# [A Practical Guide to Generating a Time Spline in dbt](https://blog.reccehq.com/practical-guide-to-dim-dates-dbt)

 Written by [Dori Wilson](https://blog.reccehq.com/author/dori-wilson) | Jun 23, 2025 4:00:00 PM

## From Seed to Macro

In an [earlier post](https://medium.com/inthepipeline/building-in-the-open-recces-internal-dbt-repo-refactor-53f7860d6a1a) about refactoring our own dbt repo, we mentioned a `dim_dates` table was added for building the semantic layer. My colleague already covered why we moved from a CSV seed to a macro. This post picks up from there and walks through *how* we did it, so your team can apply the same approach.

If you’re still using a `dim_dates.csv` seed file, this one’s for you.

### The Problem: Seeds Are Loaded Every Time

Our original setup was simple, e.g. a CSV seed. We liked that as it is version-controlled and easy to modify. But in practice, this seed with 55152 rows added **~3 minutes** to every `dbt build`.

```
 14:25:43  1 of 2 OK loaded seed file PR_103.dim_dates .................................... [INSERT 55152 in 165.21s]
```

This slowed us down reviewing PRs since we build for every PR and compare with the production environment using [Recce](https://github.com/DataRecce/recce) to ensure it won’t break the production environment.

Plus, 55152 rows is too large as a seed and we cannot skip unchanged seeds with dbt selector.

We needed something better.

### The Principle: Version-Control the Logic, Not the Data

The `dim_dates` table is basically static. We don’t need to recalculate and reload it on every build. But we still want to version control the table in the dbt project, which means keeping the logic and generate the table only when needed.

### The Solution: Use a dbt Macro + `run-operation`

Here’s what we did:

### 1. Convert Your SQL into a Macro

Here is our macro to generate the `dim_dates` table in Snowflake.

### 2. Create the Table Manually When Needed

To generate or update the `dim_dates` table, run the this.

```
dbt run-operation generate_dim_dates --args '{schema_name: <your_schema>}'
```

This executes the macro and materializes the table once in your warehouse.

You can also parameterize `start_date` and `end_date` if you want tighter control or shorter test versions.

### Final Thoughts

`dim_dates` is foundational, but rebuilding it on every run is a waste of time and compute. This simple shift—from seed to macro—saves minutes on every build and gives you full control over how the table evolves.

If your team is using dbt at any meaningful scale, this change pays for itself almost instantly.

Want to implement it yourself? Just grab your existing seed SQL and wrap it in a macro like the one above.

Happy building! 🚀

[View full post](https://blog.reccehq.com/practical-guide-to-dim-dates-dbt)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Dori Wilson"
  },
  "dateModified" : "2026-02-17T20:49:38.009Z",
  "datePublished" : "2025-06-23T16:00:00Z",
  "headline" : "A Practical Guide to Generating a Time Spline (dim_dates) in dbt",
  "image" : {
    "@type" : "ImageObject",
    "height" : 1165,
    "url" : "https://242432742.fs1.hubspotusercontent-na2.net/hubfs/242432742/Blog/a-practical-guide/Screenshot%202025-07-11%20at%2014.39.01.png",
    "width" : 800
  },
  "mainEntityOfPage" : "https://blog.reccehq.com/practical-guide-to-dim-dates-dbt",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 0.0,
      "url" : "https://242432742.fs1.hubspotusercontent-na2.net/hubfs/242432742/recce-og-image.avif",
      "width" : 0.0
    },
    "name" : "blog"
  }
}
```