API gateway con Kong per microservizi PHP: autenticazione, rate limiting e routing centrali
A novembre 2025 un'azienda del settore logistica per il trasporto di merci B2B - fatturato annuo intorno ai 22 milioni di euro, circa 80 dipendenti, infrastruttura su Hetzner con un cluster di sei VPS - mi ha chiesto un audit architetturale della loro piattaforma di gestione tracciabilità. La piattaforma era stata sviluppata negli ultimi cinque anni come un insieme di otto microservizi PHP/Laravel interconnessi: ordini, tracking spedizioni, anagrafica clienti, fatturazione, calcolo tariffe, integrazioni con vettori esterni (DHL, UPS, Bartolini), notifiche, reporting. Tecnicamente funzionava, ma ogni servizio aveva la propria implementazione di autenticazione JWT con logica sottilmente diversa: il servizio tracking validava il token sul middleware, il servizio ordini usava un Policy custom, il servizio fatturazione aveva una combinazione di middleware e Gate che gestiva ruoli in modo differente da tutti gli altri, e il servizio integrazioni vettori aveva un API key legacy che bypassava JWT completamente per questioni storiche. Ogni nuovo microservizio introdotto richiedeva di replicare (o reinventare) la logica di auth, e quando il team ha deciso di introdurre MFA per alcuni ruoli amministrativi, la modifica è stata deployata solo su tre servizi su otto perché la propagazione su tutti gli altri avrebbe richiesto sei settimane di lavoro coordinato.
Il risultato di quella frammentazione era un attacco di superficie che nessuno capiva interamente. Un pentest esterno del trimestre precedente aveva rilevato due bug nel servizio fatturazione dove il controllo di scope JWT era implementato in modo differente e permetteva ad alcuni utenti di vedere fatture non proprie. Il team aveva fixato quei due, ma nessuno era in grado di dimostrare che gli stessi pattern non esistessero negli altri sette servizi. In quattro settimane ho riarchitettato il perimetro introducendo Kong Gateway come API gateway centrale, progetto open source mantenuto da Kong Inc. e documentato ufficialmente su docs.konghq.com, togliendo l'autenticazione dai singoli microservizi, configurando rate limiting per client key, aggiungendo circuit breaker su servizi esterni, e centralizzando i log delle richieste in Loki. Al termine del lavoro, i servizi PHP non contenevano più alcuna logica di autenticazione JWT - ricevevano un header X-Authenticated-User con l'identificativo validato upstream da Kong, e tutta la sicurezza di perimetro era concentrata in un singolo punto auditabile.
Perché un API gateway e non "middleware condiviso" fra microservizi?
La prima obiezione ragionevole è: perché introdurre uno strumento esterno e non creare un package Composer condiviso che i microservizi importano per avere la stessa logica di autenticazione? È una domanda seria, perché la soluzione del "middleware condiviso" è spesso proposta nei team che hanno il giusto riflesso DRY ma non hanno mai gestito la distribuzione di un package infrastrutturale in un'architettura distribuita. Le risposte sono tre e diventano progressivamente più pesanti.
Prima: la distribuzione di un package condiviso richiede coordinamento del rilascio fra microservizi. Un fix di sicurezza nel package di auth richiede di aggiornare composer.json di ogni microservizio, ricompilare, ridistribuire e deployare. Se un microservizio è fermo per manutenzione o ha un pipeline CI rotta, l'aggiornamento dell'auth rimane parziale. Sul cliente logistica, questo pattern era esattamente quello che aveva portato all'MFA non propagato completamente: la richiesta di business era "introduci MFA ovunque", l'implementazione tecnica richiedeva un update coordinato di otto servizi, e nella pratica il coordinamento si era rotto a metà strada.
Seconda: il package condiviso non elimina la duplicazione della applicazione dell'auth. Anche se la logica JWT è in un package, ogni controller di ogni microservizio deve comunque dichiarare middleware('auth.jwt') e gestire gli errori di auth in modo consistente. Un nuovo developer che aggiunge un endpoint può dimenticare il middleware, e la dimenticanza diventa una vulnerabilità. Un API gateway centralizzato impone l'autenticazione come precondizione strutturale - non c'è modo che una richiesta raggiunga un microservizio senza essere prima passata dal gateway, quindi il dimenticare il middleware diventa impossibile per design.
Terza: centralizzare l'auth nell'API gateway abilita funzionalità che non avrebbero senso replicate in ogni microservizio. Rate limiting cross-servizio (un client non può saturare un solo servizio ma ha un budget globale), throttling differenziato per fascia cliente (enterprise hanno limiti più alti dei free), logging uniforme di tutte le richieste in entrata con tracing ID propagato, autenticazione a chiamata (mTLS per i client B2B che usano certificati), transformation delle richieste per compatibilità backwards (riscrivere header obsoleti, gestire version upgrade di API). Tutte queste funzionalità hanno senso solo in un punto centrale; nel mondo "middleware condiviso" sono o assenti o implementate in otto modi diversi.
L'architettura operativa: Kong davanti, servizi dietro, mTLS nel mezzo
Kong è un'istanza Nginx con logica Lua aggiunta che funge da reverse proxy intelligente. La configurazione che installo per clienti PMI è quasi sempre la versione "Community Edition" self-hosted, che è gratuita e copre la maggioranza delle esigenze. Le versioni Enterprise (Kong Gateway con dashboard grafica, plugin avanzati, support) hanno senso per aziende con requisiti di governance più stringenti o con team dedicati alla gestione del gateway. Sul cliente logistica siamo partiti con Community e dopo sei mesi valutavamo l'upgrade; al momento in cui scrivo, Community rimane sufficiente per il loro caso d'uso.
L'architettura di rete del deployment è questa: i client esterni (app mobile, web SPA, integrazioni B2B via API key) arrivano a Kong esposto via Nginx su api.azienda-logistica.local con TLS terminato. Kong valida l'autenticazione (JWT per utenti interattivi, API key per client B2B, mTLS per partner certificati), applica rate limiting basato sul client identity, applica policy di CORS, e inoltra la richiesta al microservizio appropriato via HTTP plain sulla rete interna 10.0.0.0/24 non esposta pubblicamente. I microservizi rispondono su porte interne (:8001 per ordini, :8002 per tracking, :8003 per fatturazione, etc.), e ogni microservizio ascolta solo sul loopback del suo container Docker, accessibile esclusivamente via Kong come upstream Nginx.
L'aspetto critico che molti team dimenticano è che i microservizi devono essere inaccessibili direttamente - il loro unico punto di ingresso deve essere Kong. Se anche uno solo dei microservizi è raggiungibile bypassando Kong (per esempio perché la sua porta è esposta sulla LAN o peggio pubblicamente), l'intera architettura di sicurezza centralizzata crolla: un attaccante può colpire direttamente il servizio ignorando tutte le policy del gateway. Sul cliente logistica il setup originale aveva tre servizi con porta esposta sulla LAN interna accessibile via VPN aziendale, e un dipendente malintenzionato avrebbe potuto (in teoria) bypassare Kong usando la VPN e chiamando direttamente il servizio. La remediation è stata configurare il firewall di ogni host in modo che la porta del microservizio accettasse connessioni solo dall'IP interno di Kong, rifiutando qualunque altra sorgente.
Il setup base di Kong in modalità DB-less (la configurazione è dichiarativa in YAML, senza bisogno di PostgreSQL backing) è questo:
# kong/kong.yaml - configurazione dichiarativa
_format_version: "3.0"
services:
- name: ordini-service
url: http://10.0.0.11:8001
routes:
- name: ordini-api
paths: ["/api/v1/ordini"]
strip_path: false
plugins:
- name: jwt
config:
claims_to_verify: ["exp"]
header_names: ["Authorization"]
- name: rate-limiting
config:
minute: 120
policy: local
- name: request-transformer
config:
add:
headers: ["X-Authenticated-User:$(consumer.username)"]
- name: fatturazione-service
url: http://10.0.0.12:8002
routes:
- name: fatturazione-api
paths: ["/api/v1/fatture"]
strip_path: false
plugins:
- name: jwt
- name: rate-limiting
config:
minute: 60
- name: acl
config:
allow: ["group:fatturazione", "group:admin"]
consumers:
- username: acme-mobile-app
jwt_secrets:
- algorithm: HS256
key: acme-mobile-key
secret: "{vault://env/JWT_SECRET_MOBILE}"
acls:
- group: standard-customer
- username: partner-dhl
keyauth_credentials:
- key: "{vault://env/DHL_API_KEY}"
acls:
- group: partner-apiTre scelte meritano approfondimento. Prima: l'attivazione del plugin request-transformer per iniettare l'header X-Authenticated-User nelle richieste che arrivano ai microservizi. Questo è il punto chiave: i microservizi non validano più JWT, ricevono solo un header che già sanno essere validato (perché è stato iniettato da Kong, che è l'unico path possibile). Seconda: l'uso di acl plugin per gestire autorizzazione per gruppi - il consumer acme-mobile-app è nel gruppo standard-customer e non può accedere alle rotte di fatturazione; il consumer partner-dhl è nel gruppo partner-api con accesso diverso. Terza: il riferimento ai secreti via sintassi {vault://env/...} che in Kong permette di leggere valori sensibili da environment variables invece di inserirli in chiaro nel config file. Il config file è versionato in Git; i secret no, restano in un file separato o nel vault dell'orchestratore.
Stai cercando un Consulente Informatico esperto per centralizzare la sicurezza delle API di un'architettura a microservizi PHP con Kong, Traefik o servizi mesh come Istio, eliminando duplicazione di middleware e coordinamento doloroso fra servizi? Nel mio profilo professionale trovi l'esperienza concreta su architetture distribuite PHP, autenticazione JWT/OAuth2, rate limiting e pattern di resilienza per microservizi aziendali.
Rate limiting: come proteggere il backend dai client cattivi e da quelli sbagliati
Il rate limiting in un API gateway è uno strumento di protezione multifunzione che molti team sottovalutano. Non è solo "bloccare chi fa troppe richieste" - è prevenire scenari di degrado del servizio che possono derivare da tre cause distinte: client malintenzionati che fanno scraping o brute force, client benigni con bug che fanno richieste ridondanti, e picchi di traffico legittimo che saturano il backend più lento della catena.
Sul cliente logistica ho applicato una configurazione a due livelli. Il primo livello è il rate limiting per consumer, con limiti differenziati per tipologia di client: 120 richieste/minuto per app mobile standard, 600 richieste/minuto per web frontend dell'azienda (che fa richieste aggregate più intense), 3000 richieste/minuto per partner B2B enterprise che integrano sistemi di trasporto merci ad alto volume, e 30 richieste/minuto per API pubbliche di tracciamento spedizioni dove un utente finale inserisce il codice della sua spedizione. Il secondo livello è il rate limiting aggregato per endpoint critici: /api/v1/ordini ha un limite complessivo di 10.000 req/minuto su tutti i client combinati, perché oltre quel valore il microservizio ordini inizia a degradare le prestazioni del database condiviso. Se il limite aggregato viene raggiunto, Kong restituisce 429 Too Many Requests anche a client che non hanno esaurito il loro budget individuale - un trade-off deliberato che privilegia la stabilità del sistema sulla disponibilità percepita da singoli client.
La calibrazione dei limiti è un processo iterativo. Il primo mese dopo l'introduzione di Kong ho tenuto sotto osservazione le metriche di rate limit triggered (Kong espone metriche Prometheus nativamente) e ho alzato o abbassato i limiti in funzione del profilo reale di traffico. Ho visto emergere tre anomalie: un partner B2B aveva un loop di retry implementato male che generava 15.000 richieste/minuto in burst quando il suo sistema di trasporto merci aveva un momento di congestione, e veniva bloccato dal rate limit - una segnalazione al partner ha portato alla correzione del bug; la web app interna aveva un componente di aggiornamento automatico che polling ogni 30 secondi su ogni utente attivo, generando carico sproporzionato, e ho suggerito al team di migrare a WebSocket per eliminare il polling; un endpoint di calcolo tariffe era chiamato dall'applicazione partner in modalità "calcola tariffa per ogni ordine prima di salvarlo" invece di "calcola batch alla fine", generando 3-4x il traffico necessario, e la correzione lato partner ha ridotto il carico complessivo del 60%. Tutte e tre le anomalie sono emerse grazie al rate limiting: senza Kong, sarebbero state invisibili nei log dei microservizi individuali.
Circuit breaker e resilienza: quando un servizio esterno cade, cosa succede?
Kong supporta circuit breaker via il plugin proxy-cache e via integrazione con upstream health check. Il pattern operativo è: Kong monitora la salute di ogni upstream (i microservizi, ma anche servizi esterni come le API dei vettori DHL/UPS/Bartolini) con healthcheck attivi periodici; se un upstream non risponde per N volte consecutive, Kong lo segna come "unhealthy" e smette di inoltrare traffico verso di esso per un periodo di grazia. Questo protegge i client da errori propagati e dà tempo all'upstream di recuperare senza essere travolto da nuovo traffico.
Sul cliente logistica questo pattern ha avuto un impatto diretto e misurabile durante un incidente di febbraio 2026, quando l'API di un vettore esterno ha avuto un'interruzione di 2 ore nella sua infrastruttura. Prima di Kong, una situazione simile avrebbe portato a un degrado a cascata: i microservizi interni della logistica che chiamavano l'API del vettore andavano in timeout a 30 secondi, saturavano i worker PHP-FPM aspettando risposta, il database di sessione si riempiva di connessioni stale, e la intera piattaforma rallentava drammaticamente. Con Kong come circuit breaker, dopo tre tentativi consecutivi falliti Kong ha marcato l'upstream del vettore come unhealthy, ha restituito immediatamente 503 Service Unavailable a tutti i client che cercavano di chiamare quel servizio, e i microservizi interni hanno mantenuto capacità normale per le altre operazioni. Gli utenti della piattaforma hanno visto la sezione "tracking DHL" temporaneamente non funzionante, ma tutto il resto (ordini, fatturazione, tracking di altri vettori) è rimasto perfettamente operativo.
Lo stesso pattern si compone bene con il service mesh Istio per microservizi PHP con osservabilità e sicurezza che copre mTLS, circuit breaker e tracing distribuito per architetture più complesse dove la resilienza va gestita anche sulla comunicazione interna fra servizi, non solo sui punti di ingresso pubblici. La scelta fra "solo API gateway" e "API gateway + service mesh" dipende dalla complessità e dalla dimensione del parco servizi; per il cliente logistica con otto microservizi Kong da solo era sufficiente.
Migrazione progressiva: come togliere l'auth dai microservizi senza rompere la produzione
L'aspetto operativo più delicato dell'introduzione di un API gateway in un'architettura preesistente è la migrazione della logica di auth dai microservizi a Kong senza downtime. La strategia che applico è il dual-path: per un periodo di 4-6 settimane, i microservizi accettano sia il vecchio modello (JWT validato internamente) che il nuovo (header X-Authenticated-User da Kong), e progressivamente il traffico viene migrato attraverso Kong.
Il piano operativo su cinque fasi per il cliente logistica è stato questo. Fase 1 (settimana 1): deploy di Kong come reverse proxy passivo che inoltra tutto il traffico ai microservizi senza applicare alcuna policy. A questo punto Kong è nel path ma è trasparente, e se c'è un problema lo si può togliere da /etc/hosts in cinque minuti rimettendo il DNS al vecchio path diretto. Fase 2 (settimana 2): attivazione delle policy di rate limiting e logging, ma mantenendo l'autenticazione ancora nei microservizi. Questo valida che Kong sia correttamente nel path e che le metriche siano accurate. Fase 3 (settimane 3-4): modifica dei microservizi per accettare l'header X-Authenticated-User come alternative a JWT, mantenendo entrambi i path attivi. Fase 4 (settimana 5): attivazione del plugin JWT in Kong, che inizia a validare i token e a iniettare l'header. I microservizi preferiscono l'header quando presente, altrimenti fanno fallback sul JWT interno. Fase 5 (settimana 6): rimozione della validazione JWT dai microservizi, che da questo momento usano solo l'header. Kong è l'unico punto di autenticazione.
Il passaggio critico è la fase 5, perché è quella che rende il sistema incapace di funzionare senza Kong. Prima di passare alla fase 5 ho fatto due cose: ho verificato che Kong fosse deployato in alta disponibilità (due istanze dietro un load balancer, non una singola istanza single-point-of-failure), e ho creato una procedura di disaster recovery specifica per "Kong è completamente down": i microservizi possono essere ripristinati in modalità "auth diretta" riattivando un feature flag ambientale che rimette in funzione la validazione JWT interna. La procedura non è mai stata esercitata in produzione - Kong è stato affidabile per tutti i 18 mesi successivi - ma averla documentata mi ha permesso di dormire la notte sapendo che un'emergenza Kong non avrebbe bloccato il cliente indefinitamente.
Metriche a 18 mesi: i numeri dell'adozione
Dopo 18 mesi dall'introduzione di Kong sul cliente logistica, i numeri misurabili sono questi. La latenza P95 delle richieste API è aumentata di 6-8 ms (il salto attraverso Kong aggiunge un piccolo overhead), ma la P99 è diminuita di 40-50 ms perché il rate limiting aggregato ha prevenuto i picchi di latenza che prima si verificavano quando un client impazzito saturava un singolo microservizio. Il tempo medio di introduzione di una nuova policy di sicurezza (ad esempio un aggiornamento dei requisiti JWT per ruoli admin) è sceso da 6 settimane (propagazione across servizi) a 1 giorno (modifica al config di Kong). Il numero di incidenti di sicurezza legati ad autenticazione inconsistente è sceso da 4 l'anno precedente a 0 nell'anno successivo.
Il beneficio meno quantificabile ma forse più importante è l'auditabilità. Quando a marzo 2026 un cliente enterprise del settore bancario ha richiesto un'evidenza di come le API fossero protette in termini di autenticazione, autorizzazione, rate limiting e logging, la risposta è stata "tutto è centralizzato in Kong, ecco il repository Git con la configurazione dichiarativa e il report di audit degli ultimi 90 giorni". Prima di Kong, la risposta avrebbe richiesto di compilare informazioni da otto servizi diversi con logiche differenti, e il risultato sarebbe stato disomogeneo e difficile da difendere in un'audit formale. Il valore dell'auditabilità single-point è sproporzionato rispetto al costo di introduzione dell'API gateway.
Se gestisci una piattaforma a microservizi PHP con autenticazione duplicata fra servizi, rate limiting implementato diversamente in ognuno, e il team spende troppo tempo a coordinare aggiornamenti di sicurezza cross-servizio, oppure stai pianificando una nuova architettura distribuita e vuoi evitare di accumulare quel debito operativo, contattami per una consulenza: in una giornata di assessment mappo lo stato attuale dell'auth e delle policy dei tuoi microservizi, valuto fra Kong, Traefik Enterprise e Tyk quale sia l'API gateway migliore per le tue esigenze di budget e scala, e ti consegno un piano di migrazione in cinque fasi con dual-path che ti porta a un'architettura centralizzata senza downtime e senza momenti di "punto di non ritorno" irreversibili.