system-design-data-architecture · git:20260830.00e03f4 · 2026-08-30 · sha256 fd5551c23036060f
system-design-data-architecture git:20260830.00e03f4A
Immutable. This exact content is served forever at /api/v1/blob/fd5551c23036060f.
---
name: system-design-data-architecture
description: "Choose and scale the data layer: SQL versus NoSQL per access pattern, single data ownership, replication and read scaling, partition key choice, hot partition and celebrity key mitigation. Use when selecting a store, planning sharding, or fixing a data-tier bottleneck."
metadata:
triggers:
keywords:
- sql vs nosql
- sharding
- replication
- partition key
- denormalization
- hot partition
- data store choice
- read replica
- polyglot persistence
---
# Data Architecture
## **Priority: P1 (HIGH)**
Access patterns choose the store. Ownership precedes schema. Shard last, not first.
## Store Selection
1. List every read and write access pattern with its QPS, latency target, and consistency need.
2. Default to a relational store. It wins until a specific pattern proves it cannot serve.
3. Move a pattern to a specialized store only when the relational store fails that named pattern:
key-value for hot lookups, wide-column for massive ordered writes, document for schema-variant
aggregates, graph for multi-hop traversal, search index for text and facets, object store for blobs.
4. Every additional store adds sync lag, dual-write risk, and one more operational surface. Justify it.
5. Blobs never live in the primary database; store bytes in object storage and keep the reference.
## Ownership and Consistency
- One writer owns each entity. Cross-service reads use an API or an event stream, never a shared table.
- Classify each flow before choosing replication: money, stock, and identity need strong consistency; feeds, counters, and analytics tolerate eventual.
- Read replicas serve reads only, and replica lag is visible to users. Route read-after-write to the primary or pin the session.
- Cross-entity atomicity across services needs a saga with compensations, not a distributed transaction.
## Scaling Order
Apply in order and stop as soon as headroom is sufficient: index and query fixes, then read replicas,
then caching, then vertical scale, then partition or archive cold data, then shard. Sharding is last
because it costs cross-shard queries, rebalancing, and a permanent partition key commitment.
## Partitioning
- Choose a partition key that is high-cardinality, present in the hottest query, and evenly distributed.
- Hash partitioning spreads load but kills range scans; range partitioning keeps scans but creates a moving hot partition on time-ordered keys.
- Mitigate a **celebrity key** by salting the key, replicating the record, or serving it from a dedicated cache.
- Plan resharding before launch: virtual buckets mapped to physical shards let you move buckets without rewriting keys.
## Anti-Patterns
- **No premature sharding**: an unindexed query at 300 QPS is not a sharding problem.
- **No shared database between services**: it silently couples deploy and schema lifecycles.
- **No dual writes without reconciliation**: use an event log or CDC, then reconcile.
- **No unbounded table growth**: define retention, archival tier, and deletion at design time.
- **No denormalization without an update path**: every copy needs an owner and a refresh trigger.
## Verify
- [ ] Every access pattern mapped to exactly one store with a stated reason
- [ ] Single writer named per entity
- [ ] Consistency class stated per flow
- [ ] Partition key chosen with a hot-partition mitigation
- [ ] Retention and archival defined
## References
- [Database Scaling](references/database-scaling.md) - store comparison, replication topologies, sharding mechanics, migration patterns