I treat reference data as product data because small lookup values can quietly control big business behavior. I recommend versioning, approvals, cached lookup paths, and snapshots for analytics.
Small lists with large consequences
Reference data looks small until one code changes product behavior, tax reporting, and integration contracts.
How shared codes keep rules aligned
Reference data looks small until one code changes product behavior, tax reporting, and integration contracts.
Typical systems of record
When I talk about "Typical systems of record", I am checking whether Reference Data Architecture can be traced back, trusted, and used by someone making a decision.
PostgreSQL, SQL Server, DynamoDB, Cosmos DB, Redis, object storage with versioned files, warehouses for snapshots.
Provider options in practice
| Provider | Typical services |
|---|---|
| AWS | S3 versioning, RDS, DynamoDB, AppConfig, Glue Data Catalog. |
| Azure | App Configuration, Azure SQL, Cosmos DB, Purview, Synapse. |
| Google Cloud | Cloud SQL, Firestore, Cloud Storage versioning, Dataplex, BigQuery. |
Real company pattern
My recommendation in this reference data pattern is to keep approvals and effective dates visible, because small code changes can quietly change business behavior.
Stripe country and currency style API data is a practical public example: payment platforms expose controlled reference values so integrations do not invent their own country, currency, and capability rules.
Real world operating example
I use "Real world operating example" to keep Reference Data Architecture grounded in a real system, because abstract patterns are too easy to agree with and too hard to operate.
A tax service owns tax category reference data. Checkout validates every item category against the current approved version, while finance reports can still reproduce last quarter using the old version.
Small implementation example
I use "Small implementation example" to keep Reference Data Architecture grounded in a real system, because abstract patterns are too easy to agree with and too hard to operate.
with active_rate as (
select tax_rate
from reference.tax_rates
where country_code = :country_code
and region_code = :region_code
and active = true
and effective_from <= :checkout_time
and (effective_to is null or effective_to > :checkout_time)
)
select max(tax_rate) as tax_rate,
case when count(*) = 1 then 'ALLOW_CHECKOUT' else 'BLOCK_CHECKOUT' end as decision
from active_rate;
The query permits checkout only when exactly one active tax rate matches the place and time. Missing or duplicate reference data blocks the transaction.
Operational traps
- Version reference values and effective dates.
- Make invalid values fail fast at the boundary.
- Keep retired codes for historical reporting.