1---2name: storage3description: Choose and architect storage systems for applications with the right tradeoffs.4---56## Object vs Block vs File78- Object storage (S3, R2, GCS) for immutable blobs: images, videos, backups, logs — cheap, scales infinitely, but no partial updates9- Block storage (EBS, Persistent Disks) for databases and apps needing filesystem semantics — faster, but tied to single instance10- Network file systems (NFS, EFS) when multiple instances need shared filesystem access — convenient but latency and cost add up11- Default to object storage for user uploads — block storage for database files only1213## When SQL vs NoSQL1415- SQL when you need joins, transactions, or complex queries — fighting against NoSQL for relational data wastes months16- Document stores (MongoDB, Firestore) for nested/variable schemas where you always fetch the whole document17- Key-value (Redis, DynamoDB) for simple lookups by ID at massive scale — not for complex queries18- Time-series databases (InfluxDB, TimescaleDB) for metrics with timestamp-based queries — regular SQL struggles with retention policies19- Start with PostgreSQL unless you have a specific reason not to — it handles JSON, full-text search, and scales further than most assume2021## Local vs Cloud Storage2223- Local disk for ephemeral data: temp files, build artifacts, caches — assume it disappears on restart24- Cloud storage for anything that must survive instance termination — never store user data only on local disk25- Local SSD for databases in production — network-attached storage adds latency to every query26- Hybrid: local cache in front of cloud storage for frequently accessed files2728## CDN Patterns2930- Put CDN in front of static assets always — origin requests are slower and more expensive31- Set long cache TTLs with versioned URLs (`style.abc123.css`) — cache invalidation is slow and unreliable32- CDN for dynamic content only if latency matters more than freshness — adds complexity for marginal gains33- Edge caching for API responses works but cache keys get tricky — start simple, add only when needed3435## Upload Handling3637- Never accept uploads directly to app server disk in production — use presigned URLs to cloud storage38- Set file size limits at load balancer level, not just application — prevents memory exhaustion attacks39- Generate unique keys for uploads (UUIDs) — user-provided filenames cause collisions and path traversal risks40- Validate file types by content (magic bytes), not extension — extensions are trivially spoofed4142## Data Locality4344- Keep compute and storage in same region — cross-region data transfer adds latency and cost45- Replicate data to regions where users are, not where developers are46- Multi-region storage adds complexity — single region with backups elsewhere usually sufficient47- Database read replicas in user regions for read-heavy workloads4849## Retention and Lifecycle5051- Define retention policy before storing data — "keep everything" becomes expensive and legally risky52- Automate deletion of temporary data — manual cleanup never happens consistently53- Tiered storage for aging data: hot → warm → cold → archive — but check retrieval costs before archiving54- Separate storage for logs vs business data — different retention, different compliance requirements5556## Cost Traps5758- Egress fees dominate cloud storage costs — calculate before choosing provider59- Many small files cost more than few large files — batch small writes when possible60- Minimum storage duration on cold tiers — early deletion still charges full period61- API request costs matter at scale — millions of LIST operations add up6263## Backup Strategy6465- 3-2-1 rule: 3 copies, 2 different media types, 1 offsite — cloud counts as one location66- Test restores regularly — untested backups are not backups67- Point-in-time recovery for databases — daily snapshots lose a day of data68- Version important files — deletion or corruption often discovered late