System design
Two halves: the integration/resilience track (what this repo’s owner keeps being asked in take-homes) and the classic scaling track.
| # | Folder | Covers |
|---|---|---|
| 01 | api_integrations/ | adapters behind a Protocol, schema/model layering, a worked clean-architecture walkthrough |
| 02 | resilience/ | timeouts and retries, breakers and bulkheads, fallbacks, saga orchestration |
| 03 | async_patterns/ | in-request concurrency vs background work, and the durability line between them |
| 04 | secrets_config/ | typed config, secrets managers, rotation, workload identity |
| 05 | observability/ | structured logs, correlation, RED/USE, sampling, cardinality |
| 06 | design_framework/ | the interview framework, capacity estimation, latency numbers |
| 07 | worked_designs/ | URL shortener, rate limiter, fanout, feed, chat, cache, scheduler, payments |
| 08 | scaling_building_blocks/ | load balancing, CDN, replication, sharding, CAP/PACELC, consistency |
The five answers that carry most interviews
Retry amplification. Three retries at three layers is nine requests per user action. Under partial degradation, retry load is what turns a slow service into a dead one.
Idempotency is the precondition for retrying. A timeout is precisely the case where you don’t know whether the operation applied, so a blind retry can double-charge.
Adapter behind a Protocol. The service depends on an interface, each provider gets an adapter, and their schema stops at the translation function. Adding a provider is a new adapter, not a service change.
Alert on symptoms, diagnose with traces. Error rate and p99 page you; traces tell you where; logs confirm the specific case. Alerting on CPU trains people to ignore alerts.
Cardinality kills metrics. User IDs as metric labels create a time series per user and take down the backend. High-cardinality context belongs in logs and traces.