FastAPI è un framework Python progettato soprattutto per costruire API Web, con un approccio in cui i type hint del linguaggio non servono soltanto all’editor: diventano parte del contratto dell’applicazione, della validazione dei dati e della documentazione OpenAPI.
Questo cambia parecchio il modo in cui si sviluppa un backend API-first. Un parametro dichiarato come int, un modello Pydantic o il tipo restituito da una funzione possono essere utilizzati dal framework per controllare input e output, produrre errori coerenti e descrivere automaticamente l’API.
Il vantaggio reale, però, non è che FastAPI faccia sparire la complessità. Sposta e automatizza una parte del lavoro ripetitivo, mentre restano da progettare database, autenticazione, autorizzazioni, struttura del codice, logging, deployment e sicurezza.
Se conosci già Python e vuoi capire come passare da script e programmi a servizi Web, FastAPI è uno dei framework da conoscere. Se invece stai ancora prendendo confidenza con funzioni, moduli, ambienti virtuali ed errori, conviene prima consolidare le basi con la guida su come programmare in Python.
In questa guida costruiremo una piccola API, ma soprattutto vedremo perché il framework si comporta in un certo modo, dove l’async porta vantaggi reali e quando FastAPI ha più senso di Flask o Django.
Cos’è FastAPI e a cosa serve
FastAPI è un framework Web open source per Python orientato alla creazione di API. Si appoggia a componenti maturi dell’ecosistema, in particolare Starlette per il livello Web/ASGI e Pydantic per la gestione e validazione dei dati.
La definizione è breve, ma il punto importante è il modello operativo.
Con un framework più minimale puoi definire una route, leggere manualmente valori dalla richiesta, validarli, trasformarli, costruire la risposta e aggiungere separatamente uno strumento per descrivere l’API.
FastAPI prova invece a ricavare buona parte di queste informazioni dalle dichiarazioni Python che stai già scrivendo.
FastAPI è un framework Python per costruire API
Un endpoint elementare può essere definito così:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
app è l’applicazione FastAPI.
Il decoratore:
@app.get("/")
dichiara che la funzione successiva deve gestire richieste HTTP GET inviate al percorso /.
Il dizionario Python restituito dalla funzione viene poi convertito in una risposta JSON.
Con poche righe hai quindi già collegato:
metodo HTTP → percorso → funzione Python → risposta
Se non ti è ancora chiaro cosa rappresentino endpoint, metodi HTTP, request e response, conviene affiancare a questa guida l’approfondimento su cosa sono e come funzionano le API. FastAPI rende molto rapido implementarle, ma non sostituisce il modello mentale di HTTP.
Starlette, Pydantic e type hint: chi fa cosa
Tre livelli vengono facilmente confusi.
FastAPI fornisce l’esperienza di sviluppo, integra i componenti e usa le dichiarazioni Python per definire il comportamento dell’API.
Starlette gestisce una parte importante dell’infrastruttura Web sottostante: request, response, routing ASGI, middleware, WebSocket e altri meccanismi.
Pydantic si occupa invece del modello e della validazione dei dati.
Il collegamento fra questi componenti diventa evidente quando scrivi:
async def leggi_prodotto(prodotto_id: int):
...
Quel : int non è soltanto documentazione per chi legge il codice. FastAPI può usarlo per interpretare il parametro, convertirlo quando possibile, validarlo e descriverlo nello schema dell’API.
È questa integrazione tra tipizzazione Python e contratto HTTP a rendere FastAPI diverso da un semplice router con qualche utility aggiuntiva.
Quali progetti si prestano bene a FastAPI
Il framework è particolarmente naturale quando il prodotto nasce soprattutto come API: backend per applicazioni JavaScript separate, app mobile, integrazioni tra servizi, API pubbliche o private, microservizi, servizi che interrogano database o altre API e sistemi in cui OpenAPI ha un ruolo importante.
Ha meno senso sceglierlo soltanto perché hai letto che è “veloce”.
Un framework si sceglie soprattutto in base alla complessità che vuoi ricevere già organizzata e a quella che preferisci progettare direttamente.
Se devi costruire un’applicazione con amministrazione contenuti, ORM strettamente integrato, form, autenticazione completa e molte convenzioni già coordinate, un framework più ampio può ridurre più lavoro di FastAPI.
Come funziona FastAPI: dalla richiesta alla risposta
Per capire il framework conviene seguire il viaggio di una richiesta invece di memorizzare decoratori.
Immagina questa chiamata:
GET /prodotti/42?lingua=it
Il server riceve la richiesta, FastAPI individua la route compatibile, estrae i parametri, li interpreta secondo i tipi dichiarati, esegue eventuali dipendenze, chiama la funzione corretta e costruisce la risposta.
Questa catena è la parte centrale del backend: il framework la rende più comoda, ma il flusso richiesta → logica → dati → risposta rimane.

Routing, endpoint e metodi HTTP
Una stessa risorsa può avere comportamenti diversi in base al metodo HTTP.
Per esempio:
@app.get("/prodotti/{prodotto_id}")
async def leggi_prodotto(prodotto_id: int):
return {"id": prodotto_id}
Il valore tra parentesi graffe è un path parameter.
Se visiti:
/prodotti/15
FastAPI passa 15 alla funzione come prodotto_id.
Poiché hai dichiarato:
prodotto_id: int
il framework si aspetta un intero.
Puoi aggiungere anche parametri opzionali nella query:
@app.get("/prodotti/{prodotto_id}")
async def leggi_prodotto(
prodotto_id: int,
lingua: str | None = None
):
return {
"id": prodotto_id,
"lingua": lingua
}
Una richiesta a:
/prodotti/15?lingua=it
produrrà quindi una struttura coerente con entrambi i valori.
La cosa interessante è che la firma della funzione sta già descrivendo una parte del contratto dell’endpoint.
Validazione e serializzazione dei dati
I parametri semplici sono solo l’inizio.
Quando una richiesta deve inviare un oggetto JSON, puoi rappresentarlo con un modello Pydantic:
from pydantic import BaseModel
class ProdottoIn(BaseModel):
nome: str
prezzo: float
disponibile: bool = True
Poi lo utilizzi nell’endpoint:
@app.post("/prodotti")
async def crea_prodotto(prodotto: ProdottoIn):
return prodotto
Se il client invia:
{
"nome": "Tastiera",
"prezzo": 79.9,
"disponibile": true
}
FastAPI e Pydantic controllano che la struttura corrisponda al modello atteso.
Se manca un dato obbligatorio o un valore non è compatibile, non devi scrivere a mano lo stesso controllo in ogni endpoint: il client riceve un errore di validazione strutturato.
Questo non elimina la validazione di business.
Sapere che prezzo è un numero è diverso dal sapere se quel prezzo è consentito, se il prodotto esiste, se l’utente può modificarlo o se l’operazione rispetta le regole del dominio.
OpenAPI, Swagger UI e ReDoc
Da route, parametri e modelli FastAPI costruisce anche uno schema OpenAPI.
È uno dei vantaggi più concreti del framework perché evita di trattare documentazione e implementazione come due mondi completamente separati.
Avviando l’applicazione puoi normalmente consultare:
/docs
per la documentazione interattiva basata su Swagger UI e:
/redoc
per l’interfaccia alternativa ReDoc.
Puoi vedere endpoint, metodi, parametri e modelli e inviare richieste direttamente dal browser.
Lo schema OpenAPI, però, non va confuso con una buona progettazione dell’API.
Un endpoint può essere perfettamente documentato e avere comunque nomi poco chiari, errori incoerenti, autorizzazioni sbagliate o un modello di dominio fragile.
Installare FastAPI e preparare il progetto
Per un progetto nuovo partirei da un ambiente virtuale dedicato.
La documentazione corrente usa Python moderno e mostra esempi compatibili con Python 3.10 o versioni successive. Se stai lavorando con un’installazione molto vecchia, aggiornerei prima l’interprete invece di costruire il progetto su una baseline già problematica.
Crea un ambiente virtuale
Dal terminale:
python -m venv .venv
Su macOS e Linux puoi attivarlo con:
source .venv/bin/activate
Su Windows:
.venv\Scripts\activate
A questo punto l’ambiente del progetto è separato dai package installati globalmente.
Installa FastAPI Standard
Per una configurazione iniziale completa:
python -m pip install "fastapi[standard]"
La documentazione ufficiale mostra anche workflow basati su uv, ma non è necessario introdurre un nuovo package manager solo per capire il framework.
L’installazione fastapi[standard] porta con sé anche i componenti standard necessari al normale percorso di sviluppo, compresa la CLI.
Per eventuali cambiamenti nell’installazione conviene comunque verificare i primi passi della documentazione ufficiale quando avvii un nuovo progetto.
Crea main.py
Nel progetto crea:
main.py
con:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "La mia prima API FastAPI"}
Poi avvia il server di sviluppo:
fastapi dev main.py
La CLI individua l’applicazione e avvia il server in modalità adatta allo sviluppo, con reload automatico quando modifichi i file.
fastapi dev è uno strumento di sviluppo, non la tua architettura di produzione.
La distinzione sembra banale, ma evita uno degli errori più frequenti dei tutorial: mostrare un server locale e lasciare intendere che il problema del deployment sia risolto.
Creare la prima API con FastAPI passo passo
Costruiamo adesso qualcosa di leggermente più realistico di Hello World.
Supponiamo di voler gestire un catalogo prodotti.
Creare un endpoint GET
Partiamo da un piccolo dataset in memoria:
from fastapi import FastAPI
app = FastAPI()
prodotti = {
1: {"nome": "Mouse", "prezzo": 29.9},
2: {"nome": "Tastiera", "prezzo": 79.9},
}
@app.get("/prodotti/{prodotto_id}")
async def leggi_prodotto(prodotto_id: int):
return prodotti.get(prodotto_id)
Una chiamata a:
GET /prodotti/1
restituisce il primo elemento.
Questo esempio serve a capire il routing, non a mostrare come progettare persistenza e gestione degli errori.
Se l’ID non esiste, restituire semplicemente None non è il comportamento che vorresti in un’API reale.
Puoi essere più esplicito:
from fastapi import HTTPException
@app.get("/prodotti/{prodotto_id}")
async def leggi_prodotto(prodotto_id: int):
prodotto = prodotti.get(prodotto_id)
if prodotto is None:
raise HTTPException(
status_code=404,
detail="Prodotto non trovato"
)
return prodotto
Ora il comportamento HTTP rappresenta davvero ciò che è successo.
Path parameter e query parameter risolvono problemi diversi
Un path parameter identifica normalmente una risorsa o una parte essenziale del percorso:
/prodotti/42
Una query string modifica o filtra invece il modo in cui la risorsa viene richiesta:
/prodotti?disponibile=true
FastAPI può rappresentare entrambi direttamente nella firma Python:
@app.get("/prodotti")
async def lista_prodotti(
disponibile: bool | None = None
):
return {
"filtro_disponibile": disponibile
}
Il vantaggio non sta nella quantità di codice risparmiato in questo singolo esempio.
Emergerà quando l’API avrà decine di endpoint e vorrai mantenere coerenti tipi, validazione e documentazione.
Provare l’API dalla documentazione interattiva
Con il server in esecuzione apri la pagina /docs.
Da lì puoi selezionare l’endpoint, compilare i parametri ed eseguire la richiesta.
Per imparare è molto utile perché rende visibile la relazione tra:
firma Python → schema OpenAPI → form della documentazione → richiesta HTTP → risposta
Quello che non farei è usare Swagger UI come unico strumento di test.
Quando il progetto cresce, le verifiche ripetibili devono entrare nella suite automatizzata.
Validare request e response con Pydantic
La validazione dell’input è uno dei punti in cui il modello FastAPI diventa davvero utile.
Definiamo due oggetti distinti:
from pydantic import BaseModel
class ProdottoIn(BaseModel):
nome: str
prezzo: float
disponibile: bool = True
class ProdottoOut(BaseModel):
id: int
nome: str
prezzo: float
disponibile: bool
Ora possiamo dichiarare sia ciò che accettiamo sia ciò che intendiamo restituire:
@app.post(
"/prodotti",
response_model=ProdottoOut,
status_code=201
)
async def crea_prodotto(prodotto: ProdottoIn):
return {
"id": 3,
**prodotto.model_dump()
}
Cosa succede quando i dati non sono validi
Se prezzo deve essere un numero e il client invia un valore incompatibile, Pydantic non crea magicamente un dato corretto a qualsiasi costo.
La richiesta viene validata e FastAPI può restituire al client informazioni strutturate sull’errore.
Questo riduce parecchio il codice ripetitivo, ma non significa che ogni regola debba finire in Pydantic.
Controlli come:
“questo SKU è già presente?”
oppure:
“l’utente ha diritto a modificare questo prodotto?”
appartengono alla logica applicativa e possono richiedere database, servizi e autorizzazioni.
Separare input e output evita errori reali
Usare lo stesso oggetto per tutto è comodo nei tutorial, meno in un’applicazione reale.
Immagina un modello utente che contenga:
email password_hash ruolo token_interno
Non vorresti che ogni campo interno venisse restituito soltanto perché l’oggetto Python lo contiene.
Definire esplicitamente il modello di risposta consente di filtrare l’output secondo il contratto pubblico dell’endpoint.
È una scelta di sicurezza e di architettura, non solo di stile.
Async e await in FastAPI: quando servono davvero
L’async è probabilmente la parte di FastAPI raccontata peggio.
La semplificazione più comune è:
FastAPI usa async, quindi è più veloce.
La realtà è più interessante.
Il problema principale è l’attesa dell’I/O
Un server trascorre spesso una parte importante del tempo aspettando qualcosa:
database rete servizio esterno file coda
Durante quell’attesa la CPU potrebbe occuparsi di altre richieste.
Il modello asincrono permette di sospendere un’operazione in attesa senza tenere inutilmente occupato il flusso di esecuzione.
Ecco perché un endpoint può essere scritto così:
@app.get("/utenti/{utente_id}")
async def leggi_utente(utente_id: int):
risultato = await servizio_async(utente_id)
return risultato
Il punto decisivo è quell’await: la libreria utilizzata deve offrire realmente un’operazione asincrona.
La guida ufficiale ad async e await insiste proprio su questa distinzione.
Quando usare async def
Lo userei quando le librerie impiegate espongono API awaitable e il workload contiene molta attesa I/O.
È il caso tipico di client HTTP asincroni, driver database async o altre operazioni di rete costruite per questo modello.
Non scriverei async def come rituale in ogni endpoint solo perché il framework lo permette.
Quando una normale def è appropriata
Se utilizzi una libreria sincrona che esegue I/O bloccante e non espone await, una normale funzione:
def endpoint():
...
può essere corretta.
FastAPI sa gestire anche path operation sincrone, eseguendole senza costringerti a trasformare artificialmente ogni dipendenza in codice asincrono.
Questo rende possibile avere nello stesso progetto endpoint def e async def.
La scelta deve seguire il comportamento reale delle librerie, non una regola estetica.
Async non rende più veloce il lavoro CPU-bound
Se devi comprimere enormi file, elaborare video, eseguire calcoli numerici pesanti o fare altre operazioni che saturano la CPU, await non moltiplica la capacità del processore.
Concorrenza e parallelismo sono problemi differenti.
Per workload CPU-bound possono servire processi separati, worker dedicati, code di task o altri modelli architetturali.
FastAPI è particolarmente efficace nel coordinare applicazioni I/O-heavy, ma async non è un acceleratore universale.
Da main.py a un progetto FastAPI strutturato
Un singolo file è perfetto per imparare.
Diventa rapidamente un problema quando contiene utenti, autenticazione, prodotti, ordini, database e integrazioni esterne.
Organizzare le route con APIRouter
Puoi separare gruppi di endpoint usando APIRouter.
Per esempio:
from fastapi import APIRouter
router = APIRouter(
prefix="/prodotti",
tags=["prodotti"]
)
@router.get("/{prodotto_id}")
async def leggi_prodotto(prodotto_id: int):
return {"id": prodotto_id}
Nel file principale:
from fastapi import FastAPI from routes.prodotti import router as prodotti_router app = FastAPI() app.include_router(prodotti_router)
La struttura può quindi evolvere verso qualcosa come:
app/ ├── main.py ├── routes/ │ ├── utenti.py │ └── prodotti.py ├── models/ ├── services/ └── dependencies.py
Non esiste una cartella magica che rende automaticamente buona l’architettura.
La struttura deve seguire le responsabilità del progetto.
Dependency injection e dipendenze condivise
FastAPI include un sistema di dependency injection basato su Depends.
Può essere utile per elementi come autenticazione, sessioni database, configurazioni, controlli condivisi o parametri comuni.
Il vantaggio è evitare di duplicare lo stesso codice in ogni route mantenendo comunque le dipendenze visibili.
Anche qui è possibile abusarne.
Se ogni funzione dipende da una catena difficile da seguire, hai solo spostato la complessità.
Una buona dipendenza dovrebbe rappresentare una responsabilità riutilizzabile e riconoscibile.
Database e ORM: cosa FastAPI non impone
FastAPI non include un ORM obbligatorio.
Puoi quindi scegliere la tecnologia di persistenza più adatta al progetto, ma la libertà ha un costo: devi prendere tu decisioni che altri framework prendono in anticipo.
Dovrai valutare almeno connessioni, transazioni, migrazioni, lifecycle delle sessioni, mapping dei modelli e comportamento sync/async del driver.
Per un piccolo servizio questa libertà è piacevole.
Per un prodotto grande può significare più integrazioni da progettare e mantenere.
Sicurezza, test e deploy: cosa cambia fuori dal tutorial
Far rispondere /docs è l’inizio, non la fine.
Un’applicazione reale introduce confini di sicurezza, test automatizzati, configurazione, segreti, observability e un ambiente di esecuzione stabile.
Autenticazione, OAuth2 e JWT
FastAPI offre strumenti per implementare schemi di sicurezza e integrarli nella documentazione OpenAPI.
La documentazione ufficiale sulla sicurezza mostra, tra le altre cose, flussi OAuth2 e token JWT.
Questo non significa che basti aggiungere una dependency per rendere sicura un’applicazione.
Devi ancora occuparti correttamente di password hashing, durata e rotazione dei token, autorizzazioni, revoca quando necessaria, gestione dei segreti, HTTPS e protezione delle risorse.
Un JWT firmato, inoltre, non equivale automaticamente a un contenuto segreto: il payload non va trattato come uno spazio in cui inserire informazioni sensibili soltanto perché il token è firmato.
Testare gli endpoint
FastAPI mette a disposizione TestClient, che permette di chiamare l’applicazione dai test con una sintassi molto simile a un client HTTP.
Esempio:
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_home():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {
"message": "La mia prima API FastAPI"
}
Questi test possono essere eseguiti normalmente con pytest.
Il vantaggio non è soltanto verificare che l’endpoint restituisca 200.
Puoi controllare errori, autorizzazioni, payload, casi limite e regressioni ogni volta che il codice cambia.
fastapi run e ambiente di produzione
Per un’esecuzione production-oriented la CLI fornisce:
fastapi run main.py
Ma il comando non è la tua strategia di produzione.
Un deployment reale deve considerare anche HTTPS, terminazione TLS, riavvio dei processi, disponibilità, replica, uso della memoria, logging, configurazione e gestione dei segreti.
La documentazione ufficiale sul deployment tratta questi problemi separatamente proprio perché non esiste un comando universale che risolva ogni infrastruttura.
Reverse proxy, HTTPS e processi
A seconda dell’ambiente potresti avere un reverse proxy o un load balancer davanti all’application server, più istanze dell’applicazione oppure una piattaforma che gestisce replica e restart.
La configurazione corretta dipende da dove stai distribuendo il servizio.
Il principio da ricordare è:
server di sviluppo ≠ processo applicativo ≠ infrastruttura di produzione
Tenere separati questi livelli rende molto più facile capire dove intervenire quando qualcosa non funziona.
FastAPI vs Flask vs Django: quale scegliere
FastAPI, Flask e Django permettono tutti di costruire software server-side con Python, ma spostano la complessità in punti differenti.
| Criterio | FastAPI | Flask | Django |
|---|---|---|---|
| Orientamento | API-first | Web framework minimale e componibile | Framework Web ampio e integrato |
| Contratto API dai type hint | Centrale | Non centrale nel core | Non centrale nel core |
| Validazione API | Integrata tramite Pydantic | Da comporre | Da comporre per il layer API |
| OpenAPI automatico | Sì | Richiede componenti aggiuntivi | Non è una funzione centrale del core |
| Modello server | ASGI | Core WSGI | WSGI e ASGI |
| ORM incluso | No | No | Sì |
| Admin integrato | No | No | Sì |
| Template server-side | Possibili, ma non centrali | Tipicamente Jinja | Integrati |
| Libertà sullo stack | Alta | Molto alta | Minore, più convenzioni |
| Scenario naturale | API tipizzate e servizi API-first | Servizi e web app componibili | Applicazioni con molte funzioni integrate |
La tabella non stabilisce un vincitore.
Serve a capire quali decisioni vengono prese dal framework e quali restano a te.
Scegli FastAPI per un progetto API-first
Lo sceglierei quando l’API è il prodotto o una parte centrale del prodotto e vuoi che type hint, validazione, OpenAPI e modello ASGI siano elementi nativi del normale flusso di sviluppo.
È particolarmente naturale se frontend, app mobile o altri servizi consumano il backend attraverso JSON.
Ha anche senso quando una parte rilevante del carico consiste nell’attendere database e servizi esterni e puoi usare librerie asincrone adeguate.
Quando Flask è più naturale
Flask rimane molto interessante quando vuoi un core piccolo e preferisci comporre direttamente i pezzi dello stack.
Per un servizio semplice o per un’applicazione in cui vuoi vedere chiaramente il rapporto fra route, request e response, la quantità ridotta di convenzioni può essere un vantaggio.
La stessa libertà diventa un costo se il progetto cresce e devi selezionare, integrare e mantenere molti componenti separati.
Quando Django offre più valore
Django parte dal problema opposto.
Integra ORM, migrazioni, autenticazione, admin, template e molte convenzioni applicative.
Se sai già che il prodotto richiederà gestione utenti, backoffice, molti modelli relazionali e una web app data-driven, avere questi componenti coordinati può ridurre parecchio lavoro.
Usare Django per un progetto API-first non è sbagliato; allo stesso modo, usare FastAPI per un progetto grande non è sbagliato.
La dimensione del progetto da sola non decide il framework. Decide quali problemi devi risolvere e quali componenti vuoi già integrati.
Vantaggi e limiti di FastAPI
La caratteristica migliore di FastAPI è la coerenza tra codice Python e contratto dell’API.
Scrivi tipi e modelli che sono utili al programmatore e lo stesso materiale alimenta validazione, schema e documentazione.
Questo riduce la duplicazione e rende piacevole lavorare con editor e strumenti di type checking.
Dove FastAPI riduce davvero il lavoro
Il vantaggio emerge soprattutto nella zona di confine tra HTTP e dati.
Parametri, body, response model, errori di validazione e OpenAPI possono essere descritti senza mantenere manualmente più rappresentazioni dello stesso contratto.
Il risparmio diventa più significativo man mano che cresce il numero degli endpoint.
Anche il sistema di dependencies e APIRouter aiuta a passare dal tutorial a una codebase più organizzata senza imporre immediatamente uno stack applicativo enorme.
Cosa devi ancora progettare o integrare
FastAPI non decide per te:
database e ORM, struttura del dominio, strategia di autenticazione completa, autorizzazioni, logging, code di task, cache, monitoring, deployment e gran parte delle scelte infrastrutturali.
Questo non è necessariamente un limite.
È un trade-off.
Se vuoi controllo e una base API molto efficace, la libertà è un vantaggio. Se desideri un prodotto con molte funzionalità Web già coordinate, potresti finire per ricostruire pezzi che un framework più integrato offre nativamente.
FastAPI è davvero più veloce?
FastAPI è progettato per offrire ottime prestazioni e si appoggia a uno stack ASGI efficiente.
Da questo, però, non segue che una qualsiasi applicazione FastAPI sarà automaticamente più veloce di qualsiasi applicazione Flask o Django.
Un benchmark può misurare il routing minimale del framework, mentre la tua applicazione reale trascorre il tempo su query SQL, API esterne, serializzazione, autenticazione, cache e logica di business.
Anche la documentazione del progetto invita a leggere con attenzione i benchmark tra componenti che lavorano a livelli diversi dello stack.
La domanda utile è quindi:
il framework introduce un overhead adeguato al mio workload e mi permette di costruire correttamente l’architettura che mi serve?
Non:
quale framework vince il benchmark più corto?
Errori comuni quando inizi con FastAPI
Il primo è usare async def ovunque senza controllare come funzionano database client, SDK e librerie sottostanti. L’asincronia deve seguire il workload.
Il secondo è confondere fastapi dev con una configurazione di produzione. Il server locale serve a sviluppare; disponibilità, HTTPS, processi e restart sono un altro problema.
Il terzo è utilizzare lo stesso modello per database, input e output fino a esporre accidentalmente campi interni. Separare i contratti quando serve è una misura architetturale, non burocrazia.
Il quarto è concentrare tutta la codebase in main.py. Appena le responsabilità diventano distinguibili, APIRouter, servizi e dipendenze aiutano a rendere espliciti i confini.
Il quinto è pensare che OpenAPI automatico renda automaticamente buona un’API. La documentazione può descrivere perfettamente anche un contratto progettato male.
Il sesto è scegliere FastAPI solo per una promessa di performance. Se il collo di bottiglia è una query inefficiente o un’elaborazione CPU-bound, cambiare decoratore non risolve il problema.
Domande frequenti su FastAPI
FastAPI è adatto ai principianti?
Sì, se possiedi già le basi di Python e hai almeno un’idea di request, response e HTTP.
Il primo endpoint è molto semplice da creare, ma imparare contemporaneamente Python, async, API, database, autenticazione e deployment può rendere difficile capire quale livello stia causando un problema.
Per questo eviterei FastAPI come primissimo contatto con Python, ma lo considererei un ottimo passo successivo dopo piccoli programmi e una comprensione ragionevole del linguaggio.
FastAPI serve solo per API REST?
No.
La sua identità rimane fortemente orientata alle API HTTP, ma lo stack supporta anche funzionalità come WebSocket, streaming, middleware, file e altri comportamenti Web.
Non lo ridurrei quindi a un generatore di CRUD REST, anche se le API HTTP tipizzate restano il caso d’uso più riconoscibile.
FastAPI sostituisce Django?
No, perché non offrono lo stesso insieme di decisioni preconfezionate.
Se ti servono soprattutto API tipizzate, OpenAPI e uno stack ASGI leggero, FastAPI può essere più diretto.
Se il progetto beneficia di ORM, admin, autenticazione, form, template e convenzioni integrate, Django può toglierti più lavoro.
Il confronto va fatto sull’architettura del prodotto, non sulla popolarità del framework.
Serve Uvicorn per usare FastAPI?
FastAPI è il framework; per ricevere richieste HTTP serve un application server ASGI.
Nel normale percorso di installazione e con i comandi della CLI, Uvicorn viene utilizzato come server.
È utile distinguere i due ruoli perché potresti cambiare strategia di esecuzione senza cambiare l’applicazione FastAPI.
FastAPI può gestire anche un frontend?
Sì, ma con una distinzione importante.
FastAPI può servire i file prodotti da build frontend statiche tramite app.frontend(), per esempio l’output di un progetto React, Vue, Svelte o altri strumenti che generano file statici.
Le route dell’API hanno precedenza sui percorsi frontend.
Questa funzione non trasforma però FastAPI in un motore di server-side rendering per quei framework: serve il risultato statico già costruito.
La documentazione ufficiale dedicata al frontend chiarisce questa separazione.
Conclusione
FastAPI è una scelta molto convincente quando vuoi costruire API Python tipizzate, con validazione e OpenAPI integrate nel normale modo di scrivere il codice.
La sua forza non è soltanto la rapidità con cui puoi ottenere un endpoint funzionante. È la possibilità di mantenere vicini firma Python, contratto dei dati, validazione e documentazione senza duplicare continuamente le stesse informazioni.
Lo sceglierei soprattutto per backend API-first, servizi consumati da frontend separati, integrazioni machine-to-machine e applicazioni in cui l’I/O asincrono ha un ruolo reale.
Sceglierei invece Flask quando desidero un core più minimale e la massima libertà nel comporre lo stack. Preferirei Django quando il progetto beneficia da subito di ORM, admin, autenticazione e altre componenti Web coordinate.
E soprattutto non sceglierei FastAPI perché “async è sempre più veloce”.
Lo sceglierei quando il suo modello di sviluppo coincide con il problema che devo risolvere.