Cloud & DevOps 12 min di lettura 5 dicembre 2025

Costruire un'Infrastruttura Globale per Piattaforme SaaS

Come progettare e operare infrastruttura multi-region per SaaS platform enterprise: architetture AWS multi-region, Edge computing con Cloudflare Workers, CDN strategy, global load balancing, disaster recovery con RPO/RTO misurabili e il trade-off active-active vs active-passive.

DR

Davide Russo

Platform Engineer

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

Edge LayerCloudflare (CDN + Workers) o AWS CloudFront — 600+ PoP globali
Global Load BalancingAWS Route 53 Latency Routing o Global Accelerator — instrada verso la region più vicina
Region US (us-east-1)ECS/EKS cluster, Aurora PostgreSQL primary, ElastiCache Redis
Region EU (eu-west-1)ECS/EKS cluster, Aurora PostgreSQL primary, ElastiCache Redis
Region APAC (ap-southeast-1)ECS/EKS cluster, Aurora PostgreSQL primary, ElastiCache Redis
Cross-region syncAurora Global Database (replication <1s), S3 Cross-Region Replication, SQS/SNS multi-region

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-auth.tstypescript
// 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

cache-headers.tstypescript
// 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.

route53-health-check.yamlyaml
# 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 fallisce

Runbook 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.

  1. 1Rilevamento (T+0): alert PagerDuty da CloudWatch per health check failure su 2+ consecutive check (20 secondi). On-call engineer riceve la notifica.
  2. 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.
  3. 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).
  4. 4Comunicazione (T+5 min): aggiornamento della status page pubblica, notifica ai team interni, apertura di un incident Slack channel dedicato.
  5. 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.
  6. 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

InfrastructureMulti-RegionCDNDisaster RecoveryAWSCloudflare WorkersEdge ComputingGlobal Load Balancing

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.