Part 14. Silver layer: customers, accounts, cards, payments
The Silver layer builds resilient intermediate entities. These are not final data marts for consumers, but they are no longer raw sources either. Silver must be reusable: Customer 360, the risk mart, and the credit mart should be able to read the same intermediate models without duplicating logic.
What belongs in silver
In the tutorial example, silver is represented by intermediate models:
int_customer_balances;int_customer_card_activity.
They aggregate accounts and card transactions into customer-level signals that mart_customer_360 then uses.
Silver rules
- do not expose direct PII further than necessary;
- keep a clear grain;
- do not mix unrelated domains;
- do not make product decisions if the model is reusable;
- use
ref()so that lineage is readable in dbt.
If int_customer_card_activity computes risk_event_count_7d, the specification must explain what 7 days means and where the risk flag comes from. If it doesn't, the model looks like SQL but is not a durable data asset.
Acceptance facts
For silver:
- input models are read only through
ref();
- customer-level models have one row per
customer_id; - amounts do not become null without an explanation;
- risk counters have a clear window;
- PII does not leak into the reusable layer without a policy.
Qwen prompt
Compare intermediate models against mart specifications and requirements.
Show the grain of each intermediate model, input `ref()` calls, reusable fields,
and validation gaps.
Do not modify files.
Minimal output
Build a table:
| Model | Grain | Inputs | Used in | Validation gap |
|---|---|---|---|---|
| int_customer_balances | customer_id | stg_accounts | mart_customer_360 | |
| int_customer_card_activity | customer_id | stg_card_transactions | mart_customer_360 |
An empty validation gap means the model is sufficiently described and verifiable.
Walkthrough for the reader
The Silver layer is often the place where a project either matures or drowns in ad-hoc transformations. Sources here have already been cast to understandable types but have not yet become products. That creates the temptation to "improve" the data just a little: join customers with accounts, drop odd rows, rename risk, compute a convenient feature. If these decisions are not written down, silver turns into a hidden business layer.
A good silver layer builds durable entities: customer, account, transaction, loan, consents. It removes technical noise but does not claim the right to change the product's promise. For example, it is fine to standardize customer_id to a single name and prepare balances for further aggregation. It is not acceptable, without a specification, to decide that a customer is active only when the balance is positive if that affects consumers.
Silver is also useful as a layer of reuse. If every gold mart cleans up customers and accounts on its own, discrepancies will inevitably appear. One mart will handle nulls differently, another will filter closed accounts differently, a third will compute delinquency differently. A shared silver layer makes these decisions visible and reduces duplication — but only if it itself stays understandable and verifiable.
The reader should not judge silver by the number of models. Sometimes one careful intermediate model is better than three layers with pretty names. The criterion is simple: does the layer help express a repeatable entity and prove its quality? If the answer is no, the model was probably built for architectural symmetry rather than for the reader or the data consumer.
Practice
Build a grain / inputs / used in table for the two intermediate models in the example. If a model has more than one purpose, separate the purposes in words before changing the SQL.
Common mistake
Turning silver into a "dump of convenient CTEs". If a model cannot be described by a single grain and a single purpose, it is too broad.
Review questions
- Why should silver not be tied to a single product?
- Which fields from staging must not be carried downstream without a policy?
- How does
ref()help a reviewer?