Negli ultimi anni il dibattito su REST vs GraphQL e’ diventato centrale per chiunque progetti software moderni. Se sei un CTO, un IT manager o uno sviluppatore senior, prima o poi ti sei trovato a chiederti se per il prossimo progetto convenga continuare con REST oppure passare a GraphQL. La risposta, come spesso accade nel mondo del software, e’ “dipende”: dipende dal contesto, dal team, dalle integrazioni esistenti e dalle esigenze del frontend.
In questa guida del 2021 mettiamo a confronto le due tecnologie senza fanatismo, spieghiamo cos’e’ GraphQL, quali sono le differenze sostanziali con un’API REST tradizionale e ti diamo criteri pratici per scegliere. Tratteremo anche tools come Apollo, Hasura, GraphQL Yoga e AWS AppSync, e vedremo quando ha senso un’architettura ibrida che combina entrambe.

1. REST vs GraphQL: il dibattito API moderno
Le API sono il sistema nervoso del software contemporaneo. Ogni applicazione web, ogni mobile app, ogni microservizio comunica tramite API. Per due decenni, lo standard de-facto e’ stato REST (Representational State Transfer), formalizzato nel 2000 da Roy Fielding nella sua tesi di dottorato. Semplice, basato su HTTP, facilmente cacheable: REST ha alimentato la crescita del web 2.0, l’era mobile e il boom dei SaaS.
Nel 2012, all’interno di Facebook, un piccolo team guidato da Lee Byron stava cercando una soluzione al problema delle troppe chiamate API necessarie per popolare il news feed mobile. Da quell’esigenza e’ nato GraphQL: un linguaggio di query per le API e un runtime per eseguire quelle query. Facebook lo ha rilasciato come progetto open source nel 2015, e dal 2018 e’ gestito dalla GraphQL Foundation, sotto l’ombrello della Linux Foundation.
Oggi, nel 2021, GraphQL e’ adottato da aziende come GitHub (la cui v4 dell’API e’ interamente GraphQL), Shopify, Twitter, Pinterest, Airbnb, The New York Times. AWS offre AppSync, un servizio GraphQL gestito. Hasura ha raccolto round di investimento importanti. Apollo e’ diventato lo standard de-facto per client e server GraphQL in JavaScript. Ma REST e’ tutt’altro che morto: anzi, la stragrande maggioranza delle API pubbliche e interne e’ ancora REST, e per buoni motivi.
La domanda quindi non e’ “quale vince”, ma “quale si adatta meglio al mio caso”. Per rispondere serve capire come funzionano davvero entrambe.
2. REST API: come funziona (recap)
Un’API REST espone una serie di endpoint identificati da URL, ognuno dei quali rappresenta una risorsa. Le operazioni si fanno con i verbi HTTP standard: GET per leggere, POST per creare, PUT o PATCH per aggiornare, DELETE per cancellare. Un esempio classico:
GET /api/products - lista prodotti
GET /api/products/123 - dettaglio prodotto 123
POST /api/products - crea nuovo prodotto
PUT /api/products/123 - aggiorna prodotto 123
DELETE /api/products/123 - cancella prodotto 123
GET /api/products/123/reviews - recensioni del prodotto 123
Ogni risorsa ha un URI univoco. La risposta e’ tipicamente JSON (in passato anche XML), con codici HTTP che indicano lo stato (200 OK, 404 Not Found, 401 Unauthorized, 500 Internal Server Error). Il fatto che REST si appoggi su HTTP “vero” significa che si integra naturalmente con tutta l’infrastruttura web: CDN, proxy, cache, gateway.
Una vera API REST seguirebbe i vincoli di Fielding (stateless, cacheable, layered system, uniform interface, HATEOAS). In pratica, la maggior parte delle “API REST” in produzione sono RESTish: rispettano i verbi HTTP e l’organizzazione per risorse, ma ignorano spesso HATEOAS. Va benissimo cosi’: l’importante e’ la chiarezza dell’interfaccia.
REST e’ la tecnologia ideale per integrazione API tra sistemi eterogenei: gestionali, e-commerce, ERP, CRM, servizi cloud. La sua semplicita’ e’ anche il suo limite, come vedremo.
3. GraphQL: come funziona
GraphQL ribalta il paradigma. Invece di tanti endpoint, ne hai uno solo (tipicamente /graphql) e il client decide esattamente quali campi vuole ricevere. Il server espone uno schema tipizzato che descrive l’intero grafo di dati disponibili, e il client costruisce query che chiedono solo cio’ che gli serve.
Un esempio: per ottenere il nome di un prodotto, il prezzo e i primi 3 commenti con autore, la query GraphQL e’ una sola:
query {
product(id: "123") {
name
price
reviews(first: 3) {
rating
text
author { name }
}
}
}
Il server risponde con esattamente quei campi, in formato JSON. Niente di piu’, niente di meno. Per modificare i dati si usano le mutation:
mutation {
createProduct(input: {name: "Sedia", price: 99.90}) {
id
name
}
}
E per ricevere aggiornamenti in tempo reale ci sono le subscription, che usano tipicamente WebSocket per trasmettere eventi al client (utile per dashboard live, chat, notifiche).
Il punto rivoluzionario non e’ la sintassi, ma il contratto: lo schema e’ la documentazione, e’ la fonte di verita’, ed e’ machine-readable. Gli IDE come GraphiQL ti fanno vedere in tempo reale tutti i tipi disponibili, autocompletano i campi, ti dicono quale operazione e’ valida e quale no.

4. Le 7 differenze chiave
Mettiamo a fuoco le differenze sostanziali.
4.1 Endpoint
REST espone N endpoint, uno per risorsa. GraphQL ne espone uno solo: tutto passa da /graphql. Questo cambia il modo in cui si pensa all’API.
4.2 Data fetching
REST restituisce sempre la “rappresentazione canonica” della risorsa: tutti i campi previsti dall’endpoint. GraphQL restituisce solo i campi richiesti dal client. Risultato: meno dati sul filo, meno parsing, performance migliori soprattutto su mobile.
4.3 Type system
REST non ha un sistema di tipi nativo. Spesso si appoggia a OpenAPI (ex Swagger) per descrivere lo schema, ma e’ opzionale e va mantenuto in parallelo. GraphQL impone uno schema tipizzato: ogni campo ha un tipo, ogni argomento e’ validato. Il contratto e’ integrato.
4.4 Caching
Qui REST vince a mani basse. Le GET REST sono cacheable a livello HTTP da CDN, proxy e browser senza configurazione speciale. GraphQL fa tutto in POST verso un singolo URL: la cache HTTP non aiuta. Bisogna gestire il caching a livello applicativo (Apollo Client, Relay) o usare GraphQL persisted queries con GET.
4.5 Versioning
Le API REST tradizionalmente versionano l’URL (/api/v1/, /api/v2/) o l’header Accept. GraphQL incoraggia un approccio diverso: niente versioni, ma evoluzione progressiva. I campi nuovi si aggiungono, quelli vecchi si deprecano (con direttiva @deprecated) ma restano disponibili.
4.6 Learning curve
REST e’ immediato per chi conosce HTTP. Bastano curl e un browser per sperimentare. GraphQL ha una curva piu’ ripida: schema, resolver, dataloader, paginazione cursor-based, gestione errori, autorizzazioni granulari. Soprattutto lato server.
4.7 Ecosistema
REST ha 20+ anni di librerie, gateway, monitoring tools, IDE plugins. GraphQL ha un ecosistema piu’ giovane ma rapidissimo: Apollo, Relay, Hasura, GraphQL Yoga, Prisma, AWS AppSync, GraphiQL. Nel 2021 la maturita’ e’ ormai sufficiente per la produzione.
5. Over-fetching e under-fetching: il problema che GraphQL risolve
Il problema concreto che ha portato Facebook a inventare GraphQL si chiama over-fetching e under-fetching.
L’over-fetching succede quando il client riceve piu’ dati di quelli che gli servono. Esempio classico: per mostrare nome e foto di un utente in un commento, chiami GET /api/users/42 e ricevi 30 campi (email, indirizzo, preferenze, data registrazione, lingua, fuso orario…) di cui ne usi 2. Su mobile, su connessione 4G, si traduce in latenza e battery drain.
L’under-fetching e’ il problema opposto: l’endpoint non ti da’ tutto quello che ti serve, e devi fare N+1 chiamate. Esempio: per la timeline di un social ti servono 20 post, e per ogni post devi chiamare un endpoint per l’autore, uno per i commenti, uno per i like. 20 post = 80 richieste HTTP. Ogni richiesta ha overhead di rete (DNS, TCP, TLS, cookie, headers): la latenza esplode.
Le soluzioni REST a questi problemi esistono ma sono workaround:
- Query parameter
?fields=name,avatarper limitare i campi: ma e’ opzionale e poco standardizzato. - Endpoint custom “compound” (es.
GET /api/feed-with-everything): ma esplode il numero di endpoint da mantenere. - BFF (Backend For Frontend): un layer che aggrega chiamate REST e ne fa una sola. Funziona ma e’ ulteriore codice da mantenere.
GraphQL risolve over- e under-fetching by design: il client chiede una query annidata che descrive esattamente cio’ che serve, il server la risolve in un solo round-trip. Per applicazioni con UI complesse (dashboard, app mobile, social feed) il guadagno e’ tangibile.
6. Type system e schema GraphQL
Lo schema GraphQL e’ scritto in SDL (Schema Definition Language), un formato leggibile e auto-documentante:
type Product {
id: ID!
name: String!
price: Float!
description: String
category: Category!
reviews(first: Int): [Review!]!
}
type Category {
id: ID!
name: String!
products: [Product!]!
}
type Review {
rating: Int!
text: String
author: User!
}
type Query {
product(id: ID!): Product
products(category: ID, limit: Int = 20): [Product!]!
}
Le ! indicano campi non-null. [Type!]! e’ una lista non-null di elementi non-null. Il sistema di tipi di GraphQL e’ sufficientemente espressivo per la maggior parte dei casi reali, e include scalari custom (Date, Email, URL…), Enum, Union, Interface.
Tre conseguenze importanti:
- Validazione automatica delle query in ingresso. Se un client chiede un campo che non esiste, il server risponde con errore PRIMA di eseguire qualsiasi resolver.
- Codegen: tools come GraphQL Code Generator producono tipi TypeScript, modelli Swift/Kotlin, hook React (
useProductQuery) automaticamente dallo schema. Il frontend e’ type-safe end-to-end. - Introspection: il server espone lo schema stesso come query. GraphiQL e Apollo Studio leggono lo schema e ti danno autocompletamento e documentazione interattiva.
7. Caching: perche’ REST e’ piu’ semplice
Il caching e’ il punto in cui REST mantiene un vantaggio strutturale. Una GET REST e’ identificata univocamente dall’URL: GET /api/products/123. CDN, reverse proxy (Varnish, Cloudflare), cache HTTP del browser sanno cachearla nativamente. Imposti Cache-Control: max-age=3600 e per un’ora la richiesta non arriva nemmeno al server.
Con GraphQL, tutte le query sono POST /graphql con un body diverso. La cache HTTP non distingue una query dall’altra. Le strategie disponibili sono:
- Caching client-side intelligente: Apollo Client e Relay normalizzano i dati per
__typenameeid. Quando torna lo stesso oggetto in query diverse, viene riconciliato in cache. - Persisted queries: il client invia un hash della query (registrata in anticipo sul server) come
GET /graphql?hash=abc123. La query diventa cacheable da CDN. - Caching applicativo lato server: Redis con chiavi calcolate dalla query e dai parametri. Funziona ma e’ codice in piu’.
Se il tuo carico e’ fatto di poche query molto richieste (esempio: catalogo e-commerce pubblico), REST + CDN e’ difficile da battere. Se invece hai molte query diverse, ognuna usata da pochi client, il vantaggio della cache HTTP svanisce.

8. Quando scegliere REST
REST resta la scelta giusta in molti casi. Sceglilo quando:
- L’API e’ pubblica e deve essere consumata da terze parti senza barriere di apprendimento.
curle’ universale. - I consumer principali sono server-to-server (microservizi, batch, integrazioni B2B). L’over-fetching su rete interna ad alta velocita’ e’ irrilevante.
- Il caching HTTP e’ critico per scalare (CDN davanti all’API, traffico massiccio in lettura).
- Le risorse sono ben definite e poco annidate: API CRUD classiche per gestionali, anagrafiche, anagrafe documentale.
- Il team e’ piccolo o senza esperienza GraphQL: l’overhead di apprendimento non e’ giustificato.
- Stai integrando sistemi legacy via webhook/REST: vedi anche la nostra guida ai webhook.
- Hai bisogno di upload/download di file: REST con
multipart/form-datae’ lo standard. GraphQL puo’ farlo ma con piu’ attriti.
Per un primer non tecnico su REST consigliamo il pillar Cos’e’ un’API REST: guida per non sviluppatori.
9. Quando scegliere GraphQL
GraphQL e’ la scelta giusta quando:
- Hai client diversi con esigenze di dati diverse: web app, mobile iOS, mobile Android, smart TV. Ogni client chiede solo cio’ che serve.
- L’UI e’ a grafo: dashboard ricche, social feed, e-commerce con filtri complessi, app come Instagram/GitHub.
- Devi aggregare dati da piu’ sorgenti: GraphQL Federation (Apollo) o schema stitching permettono di esporre piu’ microservizi dietro un singolo endpoint.
- Il team frontend vuole iterare velocemente senza dover chiedere modifiche al backend per ogni nuovo schermo.
- Ti servono subscription real-time (notifiche, chat, dashboard live).
- Il prodotto e’ un’app mobile su connessioni instabili: meno round-trip, meno byte, batteria salva.
- Stai costruendo web app e PWA con UI complesse e composizione di componenti riusabili.
10. Architetture ibride: REST + GraphQL coesistono
Spesso si presenta come una scelta secca: o REST o GraphQL. Nella realta’, le architetture ibride sono molto piu’ comuni di quanto si pensi.
Un pattern frequente: il backend espone API REST per le integrazioni B2B, i webhook e i sistemi legacy. Sopra, un layer GraphQL aggrega quegli endpoint REST e ne aggiunge altri ad-hoc per i client interni (web app, mobile). Lo strato GraphQL diventa il BFF per il frontend, mentre REST rimane il contratto stabile verso il mondo esterno.
Un altro pattern: REST per le mutazioni complesse (gestionali, ERP, fatturazione, ordini) e GraphQL per le letture pesanti (dashboard, ricerche, navigazione catalogo). Le mutazioni richiedono spesso transazionalita’, validazione di business logic complessa e idempotenza: REST le gestisce bene con verbi e codici di stato precisi.
Hasura e’ un caso interessante: genera automaticamente uno schema GraphQL a partire da un database PostgreSQL, ma espone anche endpoint REST tramite “Actions” e “REST Endpoints”. Cosi’ un’unica fonte di verita’ (lo schema) serve entrambi gli stili.
Per i nostri progetti di gestionali personalizzati e automazione dei flussi, scegliamo l’approccio caso per caso: spesso si parte REST e si aggiunge un layer GraphQL solo se il frontend lo richiede davvero.
11. Tools 2021 per GraphQL
Nel 2021 l’ecosistema GraphQL e’ ricco. I principali strumenti che vediamo in produzione:
Server
- Apollo Server: lo standard de-facto in JavaScript/TypeScript. Plugin per Federation, caching, tracing. Versione 3 rilasciata nel 2021.
- GraphQL Yoga: alternativa leggera a Apollo Server, mantenuta da The Guild. Build su Envelop.
- Hasura: motore GraphQL che genera schema da PostgreSQL, MS SQL, BigQuery. Permission system dichiarativo. Open source + cloud.
- PostGraphile: simile a Hasura ma piu’ “code-first” e PostgreSQL-only. Estensibile via plugin.
- AWS AppSync: servizio gestito AWS. Si integra con DynamoDB, Lambda, RDS. Subscription native.
- GraphQL Java / Sangria (Scala) / graphql-go: per stack non-Node.
Client
- Apollo Client: il piu’ diffuso. React/Vue/Angular. Cache normalizzata, hook, devtools.
- Relay: client di Facebook, piu’ opinionato e performante per app a grafo.
- urql: alternativa minimalista a Apollo Client.
Tools di sviluppo
- GraphiQL / Apollo Studio: IDE web per esplorare lo schema.
- GraphQL Code Generator: genera tipi e hook dallo schema.
- Insomnia / Postman: ormai entrambi supportano GraphQL.
Federation
Apollo Federation (v1 nel 2019, v2 in beta nel 2021) permette di unire schema GraphQL di microservizi diversi in un unico “supergraph”. E’ la risposta GraphQL al problema dell’integrazione di microservizi, e nel 2021 sta diventando standard nelle architetture enterprise.
12. Domande frequenti
GraphQL sostituira’ REST?
No. Sono strumenti complementari. REST resta la scelta migliore per API pubbliche, integrazioni B2B, CDN-first. GraphQL eccelle nelle applicazioni client-rich con UI complesse. Nel 2021 convivono e continueranno a farlo.
GraphQL e’ piu’ veloce di REST?
Non in assoluto. Riduce il numero di round-trip e i byte trasferiti, ma sposta complessita’ lato server (resolver, dataloader). Per richieste semplici cacheable, REST e’ tipicamente piu’ veloce in produzione grazie alla CDN.
Posso aggiungere GraphQL sopra un’API REST esistente?
Si, e’ un pattern molto comune. I resolver GraphQL chiamano internamente gli endpoint REST. Cosi’ incrementi il valore senza riscrivere il backend, e dai al frontend un’esperienza migliore. E’ il classico approccio “GraphQL as BFF”.
GraphQL ha problemi di sicurezza specifici?
Si, principalmente query troppo complesse: un client malevolo puo’ inviare una query annidata a 10 livelli che intasa il server. Le contromisure standard sono: query depth limiting, query complexity analysis, query allowlisting (persisted queries), rate limiting. Apollo Server, GraphQL Yoga e Hasura li supportano nativamente.
Conviene GraphQL per piccoli progetti?
Quasi mai. Per un sito vetrina, una piccola web app o un’integrazione punto-punto l’overhead di GraphQL non si ripaga. REST e’ piu’ semplice da manutenere, deployare, monitorare. Il break-even tipico e’ un team di almeno 3-4 sviluppatori e un’app con UI complessa.
GraphQL funziona con database SQL o solo NoSQL?
Funziona con qualsiasi sorgente dati. Lo schema GraphQL e i resolver sono indipendenti dallo storage. Hasura e PostGraphile generano schema da PostgreSQL, AWS AppSync supporta DynamoDB e RDS, Apollo Server lavora con qualsiasi ORM (Prisma, TypeORM, Sequelize) o driver nativo.
Come si gestisce l’autenticazione in GraphQL?
Esattamente come in REST: di solito JWT o session cookie inviati negli header HTTP. La autorizzazione granulare (chi puo’ leggere quale campo) e’ invece un terreno specifico di GraphQL: si gestisce nei resolver, oppure dichiarativamente con tools come Hasura permissions o Apollo schema directives.
Come si gestisce la paginazione in GraphQL?
I due pattern dominanti sono offset-based (limit e offset, semplice ma fragile su dataset che cambiano) e cursor-based (first, after, edges, pageInfo) seguendo la “Relay Connection Spec”. Quasi tutte le API GraphQL serie nel 2021 usano cursor-based: GitHub, Shopify, Facebook. E’ piu’ verboso ma scala meglio e gestisce correttamente l’inserimento concorrente di nuovi elementi durante lo scroll.
Quanto costa migrare da REST a GraphQL?
Dipende molto dall’estensione. Una migrazione “completa” di un’API matura puo’ richiedere mesi-uomo: ridisegno dello schema, riscrittura dei resolver, adattamento del frontend, monitoring, formazione del team. Un approccio piu’ pragmatico: introduci GraphQL per UNA feature nuova, lascia il resto in REST, valuta i benefici reali, decidi se estendere. La maggior parte dei progetti che vediamo in azienda ha trovato un equilibrio ibrido stabile, senza mai migrare tutto.
GraphQL gestisce bene le mutazioni in batch?
Si: con un singolo round-trip puoi inviare piu’ mutation o accodarle. Apollo Client e Relay supportano nativamente la “optimistic UI”, aggiornando la cache prima della conferma del server. Lato server, attenzione alla transazionalita’: se piu’ mutation devono essere atomiche, va gestita esplicitamente (con database transaction o saga pattern). Non e’ magia: e’ codice che va scritto bene.
Stai progettando un’API e devi scegliere tra REST e GraphQL?
Brentasoft sviluppa API REST e GraphQL custom per PMI italiane: gestionali, e-commerce, mobile app, integrazioni di sistema su stack moderni (Node, PHP/Laravel, Python).
Per approfondire la scelta tecnologica giusta per il tuo progetto, leggi anche le nostre guide al pillar REST per non sviluppatori e ai webhook. Per riferimenti ufficiali consulta la voce GraphQL su Wikipedia e il sito ufficiale graphql.org.