Quando un SaaS conquista clienti enterprise in più continenti, la domanda non è più se costruire un'infrastruttura globale, ma quando e come farlo. Un'applicazione deployata in singola region introduce latenza strutturale per gli utenti remoti, crea un single point of failure geografico e può violare requisiti di data residency imposti da normative come GDPR o LGPD. Costruire infrastruttura veramente globale è però un'operazione ingegneristica seria: richiede scelte architetturali precise, comprensione profonda dei trade-off e una disciplina operativa che va ben oltre il semplice aggiungere region AWS.
In questo articolo documentiamo l'approccio che usiamo in Nexora per piattaforme SaaS che devono servire utenti in Europa, Nord America e Asia-Pacifico con SLA di disponibilità del 99,95% e latenza p99 inferiore a 200ms da qualsiasi punto del globo.
I fondamentali: perché la latenza geografica è ineliminabile
La velocità della luce in fibra ottica è circa 200.000 km/s. Da Milano a Singapore ci sono circa 10.000 km in linea d'aria: il round-trip minimo fisicamente possibile è 100ms. In pratica, con hop di rete, TLS handshake e processing, una request da Singapore verso un'applicazione deployata in eu-west-1 (Irlanda) accumula facilmente 300-400ms solo di latenza di rete. Per applicazioni interactive, questo è inaccettabile. La soluzione non è ottimizzare il codice — è avvicinare il processing ai dati dell'utente.
Architettura AWS multi-region: i building block
AWS offre oggi 33 region geografiche. Per un SaaS globale, la strategia più comune è deployare in 3 region primarie che coprono i principali mercati (tipicamente us-east-1, eu-west-1, ap-southeast-1) e usare CloudFront come CDN globale con oltre 600 edge location per servire asset statici e response cacheabili dall'edge più vicino all'utente.
Architettura SaaS multi-region su AWS
Global Load Balancing: Route 53 vs Global Accelerator
AWS Route 53 Latency Routing instrada il traffico DNS verso la region che ha il latency record più basso per il client. È semplice, senza costo aggiuntivo per il routing, ma ha due limitazioni: il TTL DNS (tipicamente 60s) introduce ritardo nel failover, e il routing è basato su misurazioni DNS periodiche che possono non riflettere la latenza reale della connessione. AWS Global Accelerator supera questi limiti usando la rete backbone di AWS (anziché l'internet pubblico) e BGP anycast per dirigere il traffico verso il nearest endpoint con failover in pochi secondi. Per applicazioni con requisiti di alta disponibilità, Global Accelerator vale il costo aggiuntivo.
Edge Computing con Cloudflare Workers
Il vero cambio di paradigma negli ultimi anni è l'edge computing: eseguire codice applicativo direttamente negli edge node della CDN, non solo servire file statici. Cloudflare Workers gira in oltre 330 datacenter in tutto il mondo, a meno di 50ms dalla maggior parte degli utenti internet. Il runtime è V8 Isolates — non container Node.js — il che significa cold start di pochi millisecondi anziché secondi.
// Cloudflare Worker: middleware di autenticazione e routing edge
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
// 1. Serve asset statici dalla KV store dell'edge (latenza ~1ms)
if (url.pathname.startsWith("/static/")) {
const asset = await env.STATIC_ASSETS.get(url.pathname);
if (asset) {
return new Response(asset, {
headers: {
"Cache-Control": "public, max-age=31536000, immutable",
"Content-Type": getContentType(url.pathname),
},
});
}
}
// 2. Valida JWT all'edge — evita round-trip all'origin per request non autorizzate
const authHeader = request.headers.get("Authorization");
if (authHeader?.startsWith("Bearer ")) {
const token = authHeader.slice(7);
const isValid = await verifyJWT(token, env.JWT_SECRET);
if (!isValid) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
}
// 3. Geolocation-based routing verso la region più vicina
const cf = (request as any).cf;
const continent = cf?.continent ?? "EU";
const originMap: Record<string, string> = {
NA: "https://us.api.example.com",
EU: "https://eu.api.example.com",
AS: "https://ap.api.example.com",
};
const origin = originMap[continent] ?? originMap["EU"];
// 4. Proxy verso l'origin con header aggiuntivi
return fetch(new Request(origin + url.pathname + url.search, {
method: request.method,
headers: {
...Object.fromEntries(request.headers),
"X-User-Region": continent,
"X-Edge-PoP": cf?.colo ?? "unknown",
},
body: request.body,
}));
},
};Con questo approccio, la validazione JWT avviene a meno di 50ms dall'utente finale senza mai toccare i server applicativi. Le request non autorizzate vengono rifiutate all'edge, riducendo il carico sull'origin e proteggendo da DDoS a livello applicativo. Il geolocation routing indirizza ogni request verso la region AWS più vicina, riducendo la latenza percepita anche per le chiamate API che richiedono processing backend.
CDN Strategy: cosa cachare e dove
Una CDN strategy efficace non riguarda solo i file statici. Per un SaaS moderno, la distinzione rilevante è tra contenuto statico (assets JS/CSS/immagini — cache infinita con fingerprinting), contenuto semi-statico (pagine HTML renderizzate server-side, risposta delle API pubbliche — cache con stale-while-revalidate), e contenuto dinamico (dati utente-specifici — no cache, serve all'origin). L'obiettivo è massimizzare il cache hit rate per le prime due categorie, spingendo il CDN Offload ratio il più vicino possibile al 90%.
Cache Headers corretti per applicazioni SaaS
// Next.js / Node.js: impostazione cache headers per diversi tipi di contenuto
// Asset statici con content hash nel filename (es. main.abc123.js)
// → Cache infinita: il filename cambia ad ogni deploy
res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
// Pagine HTML dell'applicazione
// → Nessuna cache: contengono session state e dati utente
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
// API endpoint pubblici (es. pricing plans, feature flags)
// → Cache breve con stale-while-revalidate per performance senza staleness
res.setHeader("Cache-Control", "public, max-age=60, stale-while-revalidate=600");
// API endpoint con dati semi-pubblici (es. catalogo prodotti per tenant)
// → Cache per tenant, invalidata esplicitamente alla scrittura
res.setHeader("Cache-Control", "private, max-age=300");
res.setHeader("Vary", "Authorization"); // Cloudflare/CDN separa le cache per tenant
// Webhook e endpoint di scrittura
// → Mai cachare operazioni di mutazione
res.setHeader("Cache-Control", "no-store");Disaster Recovery: RPO, RTO e la scelta architetturale
Il Disaster Recovery per infrastruttura globale ruota attorno a due metriche fondamentali. RPO (Recovery Point Objective) definisce quanta perdita di dati è accettabile: un RPO di 0 significa zero perdita di dati, un RPO di 1 ora significa che puoi perdere al massimo un'ora di transazioni. RTO (Recovery Time Objective) definisce quanto tempo puoi stare down prima che l'impatto sul business diventi inaccettabile: un RTO di 5 minuti significa che il sistema deve essere operativo entro 5 minuti dall'evento. RPO e RTO tendono a essere inversamente correlati al costo: avvicinarsi a zero su entrambe le dimensioni richiede architetture active-active sincrone che costano significativamente più di soluzioni active-passive con failover manuale.
Active-Passive: semplicità con failover accettabile
In un'architettura active-passive, una sola region serve tutto il traffico in condizioni normali. La seconda region (standby) riceve i dati tramite replica asincrona ed è pronta a prendere over in caso di failure della region primaria. Il failover può essere automatico (Route 53 health check + failover routing) o manuale. I vantaggi sono la semplicità operativa, il costo inferiore (la region standby può girare a capacità ridotta), e la consistenza dei dati (una sola region scrive). Il limite è il RTO: anche con failover automatico, il DNS propagation e il warm-up dell'ambiente standby tipicamente richiedono 5-15 minuti.
Active-Active: disponibilità massima con complessità distribuita
In un'architettura active-active, tutte le region servono traffico di produzione simultaneamente. Non c'è failover nel senso tradizionale: se una region cade, il traffico viene redistribuito automaticamente sulle region rimanenti con RTO vicino a zero. Il prezzo da pagare è la complessità: le write devono essere coordinate tra region, il database deve supportare multi-master o write forwarding, e i conflitti di scrittura devono essere gestiti esplicitamente. Aurora Global Database con write forwarding permette di scrivere in qualsiasi region con replica cross-region in meno di un secondo, ma la latenza di write è necessariamente più alta rispetto a un single-region setup.
# AWS CloudFormation: health check e failover DNS per active-passive
Resources:
PrimaryHealthCheck:
Type: AWS::Route53::HealthCheck
Properties:
HealthCheckConfig:
Type: HTTPS
FullyQualifiedDomainName: eu.api.example.com
Port: 443
ResourcePath: /health
RequestInterval: 10 # Controlla ogni 10 secondi
FailureThreshold: 2 # Failover dopo 2 check falliti (20s)
EnableSNI: true
PrimaryDNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref HostedZone
Name: api.example.com
Type: A
AliasTarget:
DNSName: eu-alb.example.com
EvaluateTargetHealth: true
Failover: PRIMARY
HealthCheckId: !Ref PrimaryHealthCheck
SetIdentifier: primary-eu
SecondaryDNSRecord:
Type: AWS::Route53::RecordSet
Properties:
HostedZoneId: !Ref HostedZone
Name: api.example.com
Type: A
AliasTarget:
DNSName: us-alb.example.com
EvaluateTargetHealth: true
Failover: SECONDARY
SetIdentifier: secondary-us
# La secondary entra in gioco automaticamente quando il primary health check fallisceRunbook operativo: come gestire un'outage regionale
L'architettura è inutile senza procedure operative testate. Un runbook di disaster recovery deve essere eseguito in drill periodici — almeno ogni trimestre — perché la prima volta che esegui un failover non deve essere durante un'emergenza reale. Ogni passo deve avere un owner, un timeout atteso e un criterio di successo verificabile.
- 1Rilevamento (T+0): alert PagerDuty da CloudWatch per health check failure su 2+ consecutive check (20 secondi). On-call engineer riceve la notifica.
- 2Valutazione (T+2 min): l'engineer verifica se si tratta di un'outage regionale AWS o di un problema applicativo isolato. AWS Service Health Dashboard + runbook di diagnostica.
- 3Decisione di failover (T+3 min): se l'outage regionale è confermata, si procede con il failover DNS automatico (Route 53 lo attiva autonomamente) o manuale (modifica del record A).
- 4Comunicazione (T+5 min): aggiornamento della status page pubblica, notifica ai team interni, apertura di un incident Slack channel dedicato.
- 5Monitoraggio post-failover (T+10 min): verifica che la region secondaria stia gestendo il traffico correttamente, che il database replica sia in sync, che non ci siano errori anomali nei log.
- 6Recovery e rientro (variabile): una volta che la region primaria è ripristinata, esegui il failback in una finestra di manutenzione pianificata per evitare un secondo evento imprevisto.
Data residency e compliance
Per SaaS europei, il GDPR impone che i dati personali di cittadini UE non vengano trasferiti fuori dal SEE senza adeguate garanzie. In un'architettura multi-region, questo significa che i dati di un tenant EU devono risiedere ed essere processati solo nella region EU. La soluzione standard è il tenant-level data isolation: ogni tenant viene assegnato a una region specifica al momento dell'onboarding, e tutte le sue richieste vengono instradate verso quella region tramite un tenant routing layer. Questo è un vincolo che va progettato dall'inizio — retrofittarlo su un sistema esistente è estremamente costoso.
Un'infrastruttura globale non si costruisce in un weekend sprint. Inizia con una singola region ben instrumentata e definisci i tuoi RPO/RTO target prima di scegliere l'architettura. In Nexora proponiamo sempre una fase di assessment della maturità infrastrutturale prima di consigliare active-active: per molti SaaS B2B, un active-passive ben configurato con RTO di 10 minuti è più che sufficiente e costa un quinto dell'alternativa.
Conclusioni
Costruire infrastruttura globale per SaaS è un percorso che si percorre per gradi. Il CDN e il global load balancing risolvono il 70% dei problemi di latenza con configurazione relativamente semplice. Cloudflare Workers porta l'edge computing a un livello di astrazione accessibile a qualsiasi team di engineering. La scelta tra active-active e active-passive deve essere guidata dai requisiti di RTO e dal budget operativo, non dall'aspirazione a un'architettura nominalmente più avanzata. E il disaster recovery è una pratica, non una configurazione: vale quanto spesso lo eserciti.
Tag
Prossimo passo
Hai bisogno di implementare questa architettura?
Il nostro team di ingegneria costruisce e scala i sistemi descritti in questo articolo. Dalla discovery alla produzione — con risultati misurabili.