# Every warehouse needs history. Almost none have it.

My first engagement as an independent consultant started with a week of manually recovering failed warehouse loads, and a CFO whose numbers moved between Monday and Thursday. The root cause was a warehouse with no history, which is far more common than it should be.

I'd just become a father for the second time and started a new business. My first engagement was as interim data and analytics manager at a large national wholesaler, and the job started on January 2nd, right after the holiday season. Everyone, especially the senior leadership team, was anxious to review sales performance over the critical year-end period.

I had barely stepped into my new office when someone from the team mentioned the ETL jobs had failed. Those are the nightly loads that feed the data warehouse, and we couldn't simply restart them. Two data engineers spent the entire first week manually recovering the broken runs, while the leadership team waited for numbers I couldn't give them yet. Day one and I already had a P1 on my hands: a priority-one incident, the kind where everything else stops.

---

After that first intense week we delivered the financial insights the leadership team had been waiting for, and I sat down with the team to understand how the warehouse was actually built.

It was built around financial transactions. The primary ERP system was so heavily dated that it had simply run out of available customer numbers. IT's solution was to rotate them: once a customer was considered done, their number went back into the pool for the next one. The warehouse manually combined each customer number with an effective date to pinpoint the exact customer. A customer could also be an employee, given how the ERP data model was designed, which made the whole construct even harder to reason about.

Beyond that workaround, the warehouse worked with actuals only. No snapshots, no history. Backdating and corrections propagated straight into the financial dashboards, so the numbers drifted depending on the moment you refreshed. The same report, run on Monday and again on Thursday, could show different figures for the same period. The business itself hadn't changed; someone had corrected a transaction, or rotated a customer number. I was the one who got to explain that to a CFO reviewing quarterly performance.

---

This isn't an unusual situation. Historization (slowly changing dimensions, point-in-time tables, temporal tracking) is one of the oldest concepts in data warehousing. Kimball wrote about it decades ago, and every data architecture course covers it. In practice it's also one of the most commonly skipped steps.

The reasons are predictable. Done by hand, historization usually means slowly changing dimensions of type 2: you keep every version of a record, stamped with the dates it was valid. That calls for surrogate keys, artificial IDs that survive changes in the source, plus effective and expiry dates, a current-row indicator, and merge logic that handles inserts, updates, and deletes correctly. Deletes are the nasty case; get the merge wrong and you either lose records or quietly resurrect them. All of this, for every table. Multiply that by dozens or hundreds of source tables and the effort becomes significant. Teams look at the backlog, weigh it against delivery pressure, and decide to add history later. Later never comes, and when someone eventually asks what the numbers looked like six months ago, the answer is a three-day scramble through transaction logs. Or worse, an honest "we don't know."

Tools like dbt have improved this considerably. Its snapshots give you a declarative way to track changes: you declare what to watch, and dbt records a new version of a record whenever it changes, instead of you hand-rolling merge logic. That's a real step forward, and I mean that. But you still decide, table by table, which ones deserve tracking. Each snapshot wants a strategy, a unique key, and someone who notices when a source column changes type. You configure each of them, and you keep those configurations alive as schemas evolve. With hundreds of source tables, the effort still scales linearly with the count.

---

The next step is to remove that linear scaling entirely. If your metadata already describes each source table (its schema, its role, how it changes over time), a model can read that metadata and recommend the right pattern per table: a straightforward upsert here, append-only tracking there, full versioned history where the meaning of a record genuinely changes over time. Combine that recommendation with the right templates, and historization can be generated for every table at once. A person can review each recommendation, and any the model is unsure of wait for one, instead of building each table from scratch.

That's the difference between declarative and automated. Snapshots still ask you to decide which tables to track and how. A metadata-driven platform can recommend a pattern and generate the historization layer as part of the pipeline.

The belief I'd leave you with is that history should be something a warehouse simply has, the way it has tables. When it is, a dashboard stops drifting because someone backdated a correction, and the CFO's numbers on Thursday are the ones you showed on Monday.

If any of this resonates, we're building Amfelt for exactly this problem. We're opening it to a small group of teams first. [Join the waitlist](/waitlist/).
