The decision framework
Work through these dimensions in order during an interview:
Five selection dimensions
- Data shape — relational, document, time-series, graph, blob?
- Access pattern — primary key lookups, range scans, full-text search, aggregations?
- Scale — read/write QPS, storage growth, geographic distribution?
- Consistency — strong transactions or eventual OK?
- Operations — managed service vs self-hosted, team experience?
# Template you can sketch on a whiteboard
workload:
entities: [users, videos, view_events]
hot_query: "get feed for user_id, last 50 items"
read_write_ratio: 100:1
consistency: eventual_ok_for_feed
scale_5yr: 500M users, 10B videos
Database selection on AWS
Mapping workloads to stores
| Workload | Recommended store | Why |
|---|---|---|
| User accounts, billing | Postgres / MySQL | ACID, joins, mature ecosystem |
| Session tokens, rate limits | Redis | Sub-ms latency, TTL native |
| Video files, images | S3 / GCS | Cheap durable blobs, CDN integration |
| Search autocomplete | Elasticsearch / OpenSearch | Inverted index, prefix queries |
| Billions of view events/day | Cassandra / Bigtable | Partitioned writes, TTL rows |
| Real-time analytics dashboard | ClickHouse / Druid | Columnar aggregations |
User accounts, billing
Recommended storePostgres / MySQLWhyACID, joins, mature ecosystemSession tokens, rate limits
Recommended storeRedisWhySub-ms latency, TTL nativeVideo files, images
Recommended storeS3 / GCSWhyCheap durable blobs, CDN integrationSearch autocomplete
Recommended storeElasticsearch / OpenSearchWhyInverted index, prefix queriesBillions of view events/day
Recommended storeCassandra / BigtableWhyPartitioned writes, TTL rowsReal-time analytics dashboard
Recommended storeClickHouse / DruidWhyColumnar aggregations
Managed vs self-hosted
| Aspect | Managed (RDS, DynamoDB, Atlas) | Self-hosted (Postgres on EC2, Cassandra cluster) |
|---|---|---|
| Ops burden | Backups, patches, failover automated | Your team owns everything |
| Cost at small scale | Higher per GB-hour | Cheaper if you have DBAs |
| Scaling | Click to resize or on-demand | Manual sharding, tuning |
| Interview default | Prefer unless specific reason not to | Only with strong justification |
Ops burden
Managed (RDS, DynamoDB, Atlas)Backups, patches, failover automatedSelf-hosted (Postgres on EC2, Cassandra cluster)Your team owns everythingCost at small scale
Managed (RDS, DynamoDB, Atlas)Higher per GB-hourSelf-hosted (Postgres on EC2, Cassandra cluster)Cheaper if you have DBAsScaling
Managed (RDS, DynamoDB, Atlas)Click to resize or on-demandSelf-hosted (Postgres on EC2, Cassandra cluster)Manual sharding, tuningInterview default
Managed (RDS, DynamoDB, Atlas)Prefer unless specific reason not toSelf-hosted (Postgres on EC2, Cassandra cluster)Only with strong justification
StreamHub selection walkthrough
Users and subscriptions → Postgres on RDS
CREATE TABLE subscriptions (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id),
plan TEXT NOT NULL CHECK (plan IN ('free', 'pro', 'studio')),
expires_at TIMESTAMPTZ
);
Hot video metadata → Redis cache-aside, Postgres source of truth
SETEX video:meta:v_9182 3600 '{"title":"Sunset timelapse","views":128400}'
Media files → S3 with lifecycle rules (Standard → Glacier for old archives)
Search → Elasticsearch index rebuilt from change-data-capture events
View analytics (at 3M+ DAU) → Cassandra partitioned by (video_id, day)
Questions to ask before committing
Sanity checks
- Can one primary handle write QPS for five years? If not, plan sharding early.
- Do you need cross-entity transactions? If yes, avoid splitting across NoSQL partitions.
- Is the query pattern stable? Search and analytics often need separate indexes.
- What is the blast radius if this store fails? Cache loss vs payment DB loss differ.
- Does the team know how to operate it on call at 3 AM?
Anti-patterns to avoid
✗ DynamoDB for heavy relational reporting (scan costs explode)
✗ Postgres single table with 50 TB and 1M writes/sec (shard or specialise)
✗ Redis as primary database without persistence strategy
✗ Elasticsearch as system of record (rebuild from source, not sole copy)
Evolution over time
Databases change as the product grows. StreamHub's path:
| Stage | DAU | Data layer |
|---|---|---|
| MVP | 500 | Single Postgres on VPS |
| Growth | 50K | RDS + Redis + S3 |
| Scale | 500K | + Elasticsearch, read replicas |
| Global | 3M+ | + Cassandra events, shard planning |
MVP
DAU500Data layerSingle Postgres on VPSGrowth
DAU50KData layerRDS + Redis + S3Scale
DAU500KData layer+ Elasticsearch, read replicasGlobal
DAU3M+Data layer+ Cassandra events, shard planning
Start simple; migrate when metrics force it — not when blog posts suggest it.
Quick recall
Everything you need if you only revisit this box.
- Select by data shape, access pattern, scale, consistency, and ops capability.
- Postgres for transactional core; Redis for cache; S3 for blobs; ES for search.
- Prefer managed services in interviews unless cost or control demands otherwise.
- Document Entity → Store → Reason for each component in your design.
- Avoid using search engines or caches as systems of record.
- Plan evolution: start simple, add specialised stores when metrics require it.
Test yourself
Answer these before moving on — recall is what makes it stick.