Zitadel o Keycloak: quale identity provider self-hosted per una PMI
Se metti Zitadel e Keycloak uno accanto all'altro guardando la lista delle funzionalità, non decidi niente. Parlano entrambi OpenID Connect e OAuth 2.0, fanno entrambi SAML, gestiscono entrambi il secondo fattore con TOTP e chiavi hardware, si federano entrambi con provider esterni, espongono entrambi API di amministrazione complete. Su quella tabella il pareggio è quasi perfetto, ed è per questo che le comparative che trovi in rete sono inutili: confrontano la superficie che i due prodotti condividono per forza, visto che implementano gli stessi standard, e non quella su cui divergono.
Nel primo articolo di questa serie ho spiegato il modello con cui Zitadel organizza identità e autorizzazioni, e in particolare perché il confine di fiducia è il progetto e non l'applicazione. Qui passo alla domanda che viene prima nell'ordine cronologico ma dopo in quello logico, cioè perché Zitadel e non Keycloak, che è il paragone che chiunque valuti un identity provider self-hosted si trova davanti. Non è una scelta ovvia e non voglio farla sembrare tale: Keycloak ha un decennio di adozione alle spalle, un ecosistema più vasto e una comunità enorme. Ho scelto diversamente per ragioni che si possono elencare, e che dividono nettamente il caso della PMI da quello dell'azienda con un team di piattaforma.
I numeri di partenza, perché tutto il resto dipende da lì: al momento in cui scrivo Keycloak è alla 26.7.0, rilasciata il 9 luglio 2026, sotto licenza Apache 2.0; Zitadel è alla 4.16.1, rilasciata il 17 luglio 2026, sotto licenza AGPL 3.0 dalla versione 3. Sono entrambi progetti vivi, entrambi con rilasci frequenti, e chi ti dice che uno dei due è fermo non li sta seguendo.
Perché la scelta non si decide sulla lista delle funzionalità?
Perché su quella lista i due prodotti convergono per costruzione, mentre divergono su tre assi che la lista non contiene: come modellano l'autorizzazione, quanto costano da tenere accesi e cosa ti obbliga a fare la licenza se un giorno il software lo incorpori nel tuo. Sono tre domande a cui una tabella di checkmark non risponde, e sono le tre che determinano se fra due anni sarai contento della scelta.
Aggiungo una quarta domanda che quasi nessuno si pone in fase di valutazione e che è quella che poi genera i ticket: chi mantiene questa cosa aggiornata, e con quale procedura. Un identity provider è l'unico componente della tua infrastruttura il cui fermo blocca l'accesso a tutto il resto. La differenza fra un aggiornamento che è "sostituisci un binario e riavvia" e uno che è "coordina un cluster con una cache distribuita" non si vede in nessuna comparativa, e si sente ogni singola volta.
Il modello di autorizzazione: realm e client contro organizzazione e progetto
Keycloak organizza il mondo in realm. Un realm contiene utenti, client, ruoli, gruppi e policy, ed è il perimetro di isolamento: due realm non si vedono. I ruoli esistono a livello di realm o a livello di client, e c'è un sistema di gruppi con ereditarietà degli attributi, più un motore di autorizzazione fine (risorse, scope, policy, permessi) che può arrivare a modellare regole molto sofisticate dentro il prodotto.
Zitadel organizza il mondo in organizzazioni che contengono utenti, e in progetti che contengono applicazioni e ruoli, con i progetti eventualmente delegabili ad altre organizzazioni. È un modello più povero di primitive e più ricco di intento: dice esplicitamente che il perimetro di fiducia fra applicazioni è il progetto, e che la delega a un partner è un oggetto di prima classe.
La differenza pratica per chi progetta è questa. Keycloak ti permette di mettere molta autorizzazione dentro l'IdP; Zitadel ti spinge a tenerla fuori. Non è un giudizio di valore in astratto, è una scelta che ha conseguenze misurabili. Se metti le regole di business nell'identity provider, ogni cambiamento al modello commerciale diventa una modifica alla configurazione dell'infrastruttura di identità, con il suo ciclo di rilascio e le sue autorizzazioni; se le tieni nell'applicazione, cambiano alla velocità del codice applicativo, che è la velocità con cui il business si muove davvero.
Nell'integrazione da cui viene questa serie la scelta è stata netta e in una direzione sola: l'IdP risponde a "chi sei", il gestionale risponde a "quali domini puoi amministrare", perché quella risposta dipende da anagrafiche, contratti e stati di sospensione che vivono nel database del gestionale e cambiano ogni giorno. Modellarla come ruoli in un identity provider avrebbe significato sincronizzare due sorgenti di verità, che è il modo più affidabile di garantirsi una divergenza. È il tema del pezzo su chi autentica e chi autorizza, e Keycloak avrebbe funzionato benissimo anche lui in questo disegno: semplicemente non lo suggerisce, mentre Zitadel sì.
Il criterio che ne ricavo: se la tua autorizzazione è stabile e organizzativa (reparti, mansioni, livelli di accesso che cambiano con il personale), il motore di policy di Keycloak è un valore reale. Se è dinamica e di business (chi ha pagato, chi è sospeso, quali servizi ha attivi), qualunque cosa tu metta nell'IdP diventerà una copia da tenere allineata.
Footprint e costo operativo: un binario Go contro una JVM con Infinispan
Qui la differenza è strutturale e la si paga tutti i mesi. Keycloak è un'applicazione Java che dalla riscrittura su Quarkus gira su un runtime moderno, con l'immagine ufficiale basata su OpenJDK 21, e usa Infinispan per la cache distribuita fra i nodi. Zitadel è un binario Go stateless che tiene tutto lo stato in PostgreSQL, più, dalla versione 4, un'applicazione di login separata.
I numeri dichiarati, che ho verificato sulla documentazione di Keycloak sulle cache distribuite e sulla documentazione di Zitadel per il self-hosting, perché a memoria in questo campo si dicono sciocchezze:
| Keycloak 26.7.0 | Zitadel 4.16.1 | |
|---|---|---|
| Runtime | JVM, immagine ufficiale su OpenJDK 21 | binario Go statico, più applicazione di login separata |
| Licenza | Apache 2.0 | AGPL 3.0 (core, console, login), Apache 2.0 su API, SDK e chart |
| Stato condiviso | database più cache distribuita Infinispan | interamente in PostgreSQL |
| Requisiti minimi dichiarati | nessun numero fisso pubblicato, dipende dal carico e dalle cache | circa 512 MB di RAM e meno di un core per un'istanza standard |
| Riferimento per l'alta disponibilità | cache distribuita fra nodi, Infinispan esterno per gli scenari multi-cluster | tre nodi da 4 core e 16 GB per un cluster HA |
| Cache locali di default | 10.000 voci per realm, utenti e autorizzazioni; 1.000 per le chiavi | non applicabile, lo stato è nel database |
| Aggiungere un nodo | il nodo entra nel cluster della cache | avvii un altro binario contro lo stesso database |
Sulla riga dei requisiti minimi vale la pena essere precisi invece che tendenziosi: Keycloak non pubblica un numero fisso e lo dice apertamente, perché la memoria dipende dalle cache e dal numero di richieste concorrenti, non solo dai dati. È una risposta onesta, ed è anche il punto: significa che il dimensionamento è un'attività, non una lettura. Zitadel dichiara una cifra bassa perché può permetterselo, visto che non tiene stato in memoria da condividere.
C'è poi una conseguenza operativa della cache distribuita che nella valutazione va messa nero su bianco, perché è documentata dal progetto stesso ed è controintuitiva: la cache Infinispan embedded non gestisce con eleganza l'ingresso o l'uscita simultanea di più membri, e membri che se ne vanno nello stesso momento possono causare perdita di dati. Da qui la raccomandazione di far partire e fermare i nodi in sequenza. Non è un difetto nascosto, è la natura di una cache distribuita, ma è esattamente il tipo di vincolo che una PMI senza un team di piattaforma scopre durante un incidente anziché durante la valutazione.
Un dettaglio che merita di stare in questa sezione perché è una trappola da produzione: la scoperta dei nodi di Keycloak passa di default per il database, e il nome di cluster predefinito è lo stesso per tutti. Due ambienti che condividono lo stesso database e che tu credi separati si uniscono nello stesso cluster se non gli dai nomi diversi. È il genere di cosa che si scopre quando lo staging comincia a rispondere con le sessioni della produzione.
Nel modello di Zitadel, invece, il fatto che il binario sia stateless è il motivo per cui la procedura di aggiornamento si riduce a tre fasi separate e a un ordine da rispettare, che è il tema del pezzo su alta disponibilità e aggiornamenti senza fermo. Il prezzo, va detto, è che dalla versione 4 i componenti da aggiornare sono due e non più uno.
La licenza: AGPL 3.0 contro Apache 2.0, e perché stavolta conta davvero
Questo è il punto su cui la maggior parte delle comparative online è fattualmente sbagliata, perché riporta ancora Zitadel come Apache 2.0. Il cambio è avvenuto con la versione 3, il 31 marzo 2025, e riguarda il core, la console di amministrazione e la login ospitata. Restano sotto Apache 2.0 le definizioni protobuf, le API, gli SDK, la documentazione e gli artefatti di deploy. Keycloak è e resta Apache 2.0 su tutto.
Cosa significa in pratica, senza allarmismi e senza minimizzare. Se self-hosti l'identity provider per la tua azienda e lo integri via OIDC con le tue applicazioni, la AGPL non ti chiede nulla: non stai distribuendo il software né offrendolo modificato a terzi come servizio. Questo copre il caso della PMI, che è il novantacinque per cento dei lettori di questo articolo.
Diventa una questione reale in due casi. Il primo è se incorpori Zitadel in un prodotto che vendi, per esempio se sei un ISV che consegna una piattaforma con l'IdP dentro. Il secondo è se ne modifichi il codice e offri il risultato come servizio: la AGPL estende l'obbligo di rilascio anche all'uso via rete, che è precisamente la clausola per cui esiste. In entrambi i casi c'è una licenza commerciale disponibile, e quella conversazione va avuta prima di scegliere, non dopo aver costruito.
L'asimmetria è dichiarabile in una riga: con Apache 2.0 non devi pensarci mai, con AGPL 3.0 devi pensarci una volta. Se la risposta a "lo incorporo o lo rivendo?" è no, la questione è chiusa. Se è forse, Keycloak parte avvantaggiato e non c'è argomento tecnico che compensi.
Se stai valutando un identity provider per la tua azienda e vuoi che la scelta regga anche il giorno in cui i sistemi da federare diventano tre invece di uno, nel mio profilo professionale trovi il percorso su integrazioni IAM, architetture multi-tenant e infrastruttura self-hosted da cui vengono i criteri di questo confronto.
Cosa Zitadel non fa, e va saputo prima
Una comparativa onesta elenca anche le cose che il prodotto che consigli non fa.
Zitadel non espone un'interfaccia LDAP. Può usare un server LDAP esterno come sorgente di autenticazione, ma non si comporta lui stesso da directory verso applicazioni che parlano solo LDAP. Se hai in casa software che si autentica esclusivamente contro una directory, e non puoi toccarlo, questo è un vincolo che chiude la discussione. Keycloak, nella stessa situazione, non risolve magicamente il problema, ma l'ecosistema attorno è più vasto e le probabilità di trovare un ponte già fatto sono maggiori. Nel progetto da cui viene questa serie il vincolo si è manifestato per intero, ed è la ragione strutturale per cui la directory è rimasta backend dati e l'autorizzazione è diventata applicativa, come racconto nel pezzo sul passaggio dalle ACL di directory al filtraggio applicativo.
L'ecosistema è più piccolo. Meno estensioni di terze parti, meno risposte già scritte, meno consulenti che lo conoscono. Per un problema comune trovi la soluzione in entrambi i mondi; per un problema esotico, con Keycloak la trovi più spesso.
Dalla versione 4 i componenti sono due. La login è un'applicazione separata che dialoga con il core via API e che il reverse proxy deve instradare a parte. Sulle istanze nuove è richiesta per default, con una variabile d'ambiente documentata per riattivare la login legacy dentro il core. È un costo operativo reale e va messo sul piatto, non nascosto: sono due unità di servizio da tenere vive, due binari da aggiornare, due cose che possono rompersi. In cambio la personalizzazione dell'esperienza di login non richiede più di mettere le mani nel core, che è il motivo per cui la separazione esiste.
Quanto costa cambiare idea fra due anni?
Meno di quanto temi sulla parte che conta, più di quanto speri su tutto il resto, ed è una domanda che in fase di valutazione andrebbe fatta prima di quelle sulle funzionalità. La ragione per cui costa poco è che entrambi implementano gli stessi standard: le tue applicazioni parlano OpenID Connect, e un'applicazione scritta bene non sa quale prodotto ci sia dall'altra parte. Se il codice legge il sub dal token, valida la firma contro le chiavi pubbliche pubblicate all'endpoint di discovery e non contiene da nessuna parte la stringa "keycloak" o "zitadel", sostituire l'identity provider è cambiare tre variabili d'ambiente e riavviare. Questo è il singolo motivo più forte per cui vale la pena tenere l'autorizzazione fuori dall'IdP: non solo evita di sincronizzare due sorgenti di verità, ma mantiene sottile lo strato che dovresti riscrivere in caso di migrazione.
La parte che invece costa è portare le identità. Gli utenti si esportano e si reimportano, con qualche attrito sugli attributi custom, ma le password no: sono hash con algoritmi e parametri che il prodotto di destinazione deve saper verificare, e nel caso peggiore la migrazione si traduce in un reset di massa, cioè in una comunicazione a tutta la base utenti e in un picco di ticket. Chi ha già configurato il secondo fattore lo deve riconfigurare, e questo è l'attrito vero: una PMI con duecento utenti che devono tutti rifare l'enrollment di TOTP non è un'operazione tecnica, è un progetto di comunicazione interna.
C'è poi il pezzo che nessuno mette a bilancio e che ho visto pesare più degli altri due messi insieme: gli identificativi. Il claim sub di un utente è generato dall'identity provider, e le tue applicazioni quasi certamente lo hanno salvato per legare l'identità esterna al proprio record locale. Cambiare IdP significa che ogni utente ha un sub nuovo, e serve una tabella di corrispondenza fra la chiave stabile che conosci tu e il nuovo identificativo, applicata a tutti gli ambienti in modo coerente. È esattamente il problema che affronto nel pezzo sulla sincronizzazione delle identità fra ambienti, e il consiglio che ne ricavo vale dal primo giorno: non usare mai il sub come chiave primaria applicativa, tienilo come colonna di collegamento accanto a una chiave che possiedi tu. Costa una colonna in più adesso e vale una migrazione dopo.
Come si decide, in tre scenari concreti
Qui la tabella smette di essere una tabella e diventa una decisione, che è quello che serve a chi legge da una posizione di responsabilità e non di implementazione.
PMI con qualche applicazione interna e nessun team dedicato all'infrastruttura. Vince Zitadel, e il criterio decisivo non è tecnico ma di manutenzione: un binario stateless su PostgreSQL è una cosa che una persona sola può tenere aggiornata con una procedura scritta, mentre un cluster con cache distribuita richiede di sapere cosa succede quando due nodi si riavviano insieme. Il modello progetto-e-grant, per giunta, spinge nella direzione giusta, cioè lasciare le regole di business nelle applicazioni.
Azienda con un team di piattaforma, Kubernetes già in casa e requisiti di autorizzazione fine. Vince Keycloak, e non di poco. Il motore di policy interno vale davvero quando hai regole di accesso complesse e stabili da esprimere in un posto solo, l'ecosistema ripaga chi ha casi particolari, e la complessità operativa del cluster non è un costo aggiuntivo se quella competenza ce l'hai già per altri sistemi.
Software house o ISV che consegna una piattaforma a clienti terzi. Qui decide la licenza prima di ogni considerazione tecnica. Se l'identity provider viaggia dentro il prodotto che vendi, Apache 2.0 è la risposta semplice e AGPL 3.0 è una conversazione con un legale e, probabilmente, un contratto commerciale. Vale la pena aggiungere che se invece consegni al cliente un'istanza che il cliente stesso ospita e amministra, la valutazione cambia di nuovo: è la sfumatura per cui questa domanda non si risolve leggendo un articolo, incluso questo.
C'è infine un criterio trasversale che vale in tutti e tre gli scenari e che di solito nessuno mette per iscritto: quale dei due riesci a spegnere e riaccendere senza chiamare qualcuno. Un identity provider è un punto di fallimento totale, e la domanda giusta in fase di scelta non è quale sia più potente, ma quale delle due procedure di ripristino sei disposto a eseguire alle tre di notte con il telefono che squilla. Se la risposta è "nessuna delle due", il problema non è il prodotto ed è il momento di parlare di documentazione operativa prima che di software.
Un'ultima nota pratica che vale per entrambi, perché è il primo controllo che faccio quando un impianto SSO non si comporta come dovrebbe: guarda cosa c'è davvero dentro i token che emette. La maggior parte dei problemi di integrazione che ho visto era visibile a occhio nudo nei claim, e per farlo basta incollare un token nel mio strumento di audit dei JWT e leggere audience, emittente e scadenze prima di aprire un file di log.
La scelta che ho fatto è stata Zitadel, e le ragioni erano tre, in quest'ordine: il footprint compatibile con l'infrastruttura che il cliente aveva già, il modello che spinge l'autorizzazione dove sta il dato di business, e una procedura di aggiornamento che una persona sola può eseguire in venti minuti con un rollback dichiarato. La licenza non era un problema perché non c'era ridistribuzione, e l'assenza di interfaccia LDAP era un vincolo con cui abbiamo dovuto convivere disegnando l'autorizzazione in modo diverso. Se il tuo contesto è quello di una PMI che vuole smettere di avere una password diversa per ogni applicativo, la mia raccomandazione è di partire da Zitadel e di cambiare idea solo se incontri un requisito che non copre. Se invece stai leggendo con in mente un ambiente Kubernetes già maturo e un modello di permessi articolato, prendi Keycloak e non pentirtene. In entrambi i casi, se vuoi che la valutazione la faccia qualcuno che ha portato in produzione l'uno e ha studiato seriamente l'altro prima di scartarlo, scrivimi e ne parliamo. Nel prossimo articolo esco dal confronto fra self-hosted e metto il self-hosting contro i servizi gestiti, con i prezzi reali di Auth0 e Okta alla mano.