Tag: system-design, distributed-systems, scalability, architecture, load-balancing, caching, database, api-design
Livello: avanzato
TL;DR: Framework pratico in quattro fasi per strutturare qualsiasi colloquio di System Design, dai requisiti e stime fino al deep dive architetturale.
Chiarire subito requisiti funzionali ed extra-funzionali (latenza, disponibilità, consistenza).
Calcolare stime di scala: DAU, QPS di picco, throughput di rete e storage a 5 anni.
Definire contratti API precisi (REST o gRPC) prima di disegnare i componenti.
Disegnare l'architettura ad alto livello: client, CDN, load balancer, API gateway e servizi.
Scegliere il database corretto in base all'accesso: SQL per ACID, NoSQL per throughput orizzontale.
Scalare i dati con sharding, partizionamento, replication lag e pattern master-replica.
Introdurre caching multi-livello: client, edge CDN, Redis cluster con eviction policy adeguata.
Gestire elaborazioni asincrone e picchi tramite message broker come Kafka o RabbitMQ.
Trattare il teorema CAP chiarendo il trade-off esplicito tra Availability e Consistency.
Indirizzare Single Points of Failure, rate limiting, circuit breaker e ridondanza geografica.
Q: Come approcci un problema aperto di System Design all'inizio del colloquio?R: Dedico i primi cinque minuti a porre domande chiarificatrici, stabilendo l'ambito del problema, i casi d'uso primari, il target di utenti attivi e i vincoli di SLO/SLA.
Q: SQL vs NoSQL: quale criterio guida la tua scelta architetturale?R: Valuto le relazioni e le garanzie transazionali: scelgo RDBMS per query complesse e vincoli ACID, mentre passo a NoSQL (documentale o key-value) se servono scalabilità orizzontale spinta e schemi flessibili.
Q: Come garantisci la consistenza dei dati tra cache e database?R: Adotto il pattern Cache-Aside con invalidazione esplicita su scrittura o Write-Through, impostando sempre un TTL cautelativo per mitigare eventuali discrepanze residue.
Q: Come gestisci picchi improvvisi di traffico su un endpoint di scrittura critico?R: Inserisco un message broker a monte per assorbire il carico (load leveling) ed elaborare le scritture in modo asincrono tramite worker scalabili.
Q: Qual è la strategia per partizionare un database che supera la capacità di un singolo nodo?R: Implemento uno sharding orizzontale basato su una shard key uniforme (come hash di user_id), integrando Consistent Hashing per ridurre il riallocamento dei dati durante l'aggiunta di nodi.
Saltare direttamente al diagramma dei blocchi senza aver quantificato QPS e storage.
Sovraingegnerizzare la soluzione introducendo microservizi o cluster distribuiti non giustificati dai volumi.
Dimenticare l'eviction policy della cache (LRU, LFU) o trascurare il problema del Cache Stampede.
Trattare la rete come affidabile e priva di latenza, ignorando timeout, retry esponenziali e jitter.
Omettere l'autenticazione, l'autorizzazione e le policy di rate limiting al livello del gateway.
```Client -> Cloudflare (CDN/WAF)
-> API Gateway (Auth & Rate Limit)
-> Service Cluster (Stateless)
|-> Cache Layer (Redis Cluster / LRU)
|-> Primary DB (Write) -> Replica DB (Read)
|-> Message Queue (Kafka) -> Async Consumers
```
[ ] Formule rapide per stima QPS: 1 milione di richieste al giorno corrispondono a circa 12 QPS costanti.
[ ] Consistent Hashing e gestione del ring con virtual nodes.
[ ] Strategie di mitigazione del failure: bulkhead, circuit breaker e fallback gracefull.
[ ] Trade-off di replica: sincrona, asincrona e semi-sincrona.
[ ] Protocolli di comunicazione: polling lungo, Server-Sent Events e WebSocket.