Python- ja FastAPI-backend — nykyaikaiset ja skaalautuvat API:t
FastAPI on Pythonin ensisijainen kehys asynkronisille REST-API:ille. Se yhdistää Pythonin natiivit type hintit Pydanticin automaattiseen validointiin, automaattisesti generoituun OpenAPI-dokumentaatioon ja Node.js:n kanssa vertailukelpoiseen ASGI-suorituskykyyn — uhraamatta koodin luettavuutta.
FastAPI — nopein Python-kehys
FastAPI pyörii Uvicornilla (ASGI-palvelin) ja tuotannossa Gunicornilla monen prosessin ajoa varten. Yksinkertainen endpoint, joka lukee Redis-välimuistista, vastaa suoraan sieltä. Natiivi Dependency Injection mahdollistaa minkä tahansa kerroksen eristetyn testaamisen ilman monimutkaisia mockeja: todennus, tietokantasessio, rate limiting — kukin on injektoitava riippuvuus.
OpenAPI 3.1 -dokumentaatio generoituu automaattisesti type hinteistä — Swagger UI ja ReDoc ovat saatavilla osoitteissa `/docs` ja `/redoc` kehitysympäristössä. Pydantic v2 -skeema (Rust-pohjainen validaattori) validoi pyynnöt ja vastaukset. Jokainen virheellinen kenttä palauttaa 422-vastauksen selkein, lokalisoiduin virheilmoituksin.
- Natiivi async/await — ei-estävä I/O kaikissa tietokanta- ja HTTP-operaatioissa
- BackgroundTasks vastauksen jälkeisiin operaatioihin (sähköposti, webhook, loki)
- Natiivi WebSocket-tuki reaaliaikaisiin toimintoihin (chat, ilmoitukset)
- Rate limiting slowapilla (limits-pohjainen) — IP- ja käyttäjäkohtainen
- Middleware: CORS, pakkaus (gzip/brotli), request ID, ajoitus
PostgreSQL, SQLAlchemy ja Alembic
Käytämme SQLAlchemy 2.0 asyncia (asyncpg-ajuri) kaikkiin tietokantaoperaatioihin. Mallit määritellään Mapped-tyypeillä — tyyppiturvallisesti, ilman merkkijonoja. Monimutkaiset kyselyt kirjoitetaan SQLAlchemy Corella (käännösaikana tarkistettu) tai puhtaalla SQL:llä `text()`-funktion kautta bind-parametrein — ei koskaan merkkijonojen interpolointia (täydellinen SQLi-esto).
Alembic-migraatiot generoidaan automaattisesti mallimuutoksista ja tarkistetaan manuaalisesti ennen käyttöönottoa. Jokaisella migraatiolla on testatut `upgrade()` ja `downgrade()`. Tuotannossa migraatiot ajetaan CI:ssä ennen julkaisua — tietokanta on aina synkronissa koodin kanssa. Yhteyspoolaus asyncpgin kautta, poolin koko määritettävissä palvelukohtaisesti.
- Rivitason lukitus `SELECT ... FOR UPDATE` -lauseella kriittisiin samanaikaisiin operaatioihin
- Kokotekstihaku pg_trgm:llä ja tsvectorilla — ei Elasticsearchia yksinkertaisissa tapauksissa
- JSONB puolijäsennellylle datalle GIN-indeksoinnilla
- Taulujen partitiointi miljoonien rivien tauluille (lokit, tapahtumat)
Redis-välimuisti ja horisontaalinen skaalautuvuus
Redis 7:ää käytetään sovellusvälimuistiin (TTL endpointia kohden), sessiovarastona (JWT refresh -tokenit valikoivalla mitätöinnillä), pub/sub-tapahtumiin reaaliaikaisuutta varten sekä jonoihin taustatöille (Celery tai ARQ). Välimuististrategia on cache-aside eksplisiittisellä mitätöinnillä — ei sokeaa TTL:ää, joka voi tarjoilla vanhentunutta dataa.
- JWT-todennus access-tokenilla (15 min) + Redis-refresh-tokenilla (7 päivää)
- Celery + Redis-broker asynkronisiin tehtäviin (PDF-generointi, sähköposti, tuonnit)
- Health check -endpoint `/health`, jossa tietokannan ja Redisin tila sekä julkaisuversio
- Jäsennelty JSON-lokitus (structlog) — yhteensopiva Lokin/Datadogin/ELK:n kanssa
Edut ja rajoitukset
Edut
- ASGI-suorituskyky vertailukelpoinen Node.js:n ja Go:n kanssa I/O:ssa.
- OpenAPI-dokumentaatio generoituu automaattisesti type hinteistä.
- Nopea Pydantic v2 -validointi selkein 422-virhein.
- Luettava koodi, Python tuttu useimmille tiimeille.
Rajoitukset
- Python on edelleen Go:ta tai Rustia hitaampi suoritinintensiivisissä tehtävissä.
- async/await vaatii kurinalaisuutta — yksi estävä kutsu tukkii koko event loopin.
- Nuorempi ekosysteemi kuin Djangolla batteries-included-ominaisuuksissa.
- Ei sisällä sisäänrakennettua ORM:ää tai adminia — valitset ne erikseen.
Lyhyt yhteenveto
Valitse FastAPI asynkronisiin REST-API:ihin, mikropalveluihin ja SPA-/mobiilibackendeihin. Äärimmäisen suoritinsidonnaisiin sovelluksiin tai valmiilla adminilla varustettuihin monoliitteihin Go tai Django voivat sopia paremmin.
Tekniset tiedot
| Ominaisuus | Raja / kynnys | Tyypillinen käyttö | |
|---|---|---|---|
| Samanaikaisuus | async/await, ei-estävä I/O | Suoritinsidonnainen työ vaatii erilliset workerit | API:t, joissa paljon tietokanta-/HTTP-kutsuja |
| Viive | Endpoint Redis-välimuistilla | Kasvaa suurten payloadien serialisoinnin myötä | SaaS-backend, mobiili, reaaliaika |
| Validointi ja dokumentaatio | Pydantic v2 + OpenAPI 3.1 automaattisesti | Monimutkainen skeema pidentää käynnistysaikaa | Julkiset API:t Swaggerilla/ReDocilla |
| Tyypillinen kustannus | Avoin lähdekoodi, pyörii 1 vCPU:lla | Horisontaalinen skaalaus vaatii useampia prosesseja | MVP:stä tuotantoon |
FastAPI vs vaihtoehdot
| Kriteeri | FastAPI | Django / Express |
|---|---|---|
| Asynkroninen suorituskyky | Erinomainen (natiivi ASGI) | Django osittain, Express hyvä |
| Automaattinen OpenAPI-dokumentaatio | Kyllä, type hinteistä | Vaatii lisäpaketteja |
| Sisäänrakennettu admin / ORM | Ei (valitaan erikseen) | Django: kyllä; Express: ei |
Usein kysytyt kysymykset
Onko FastAPI nopeampi kuin Django?
Kyllä I/O:ssa. FastAPI pyörii asynkronisesti ASGI:lla, joten se käsittelee paljon enemmän samanaikaisia pyyntöjä tietokanta-/HTTP-kutsuilla kuin klassinen synkroninen Django. Djangossa on kuitenkin enemmän sisäänrakennettuja ominaisuuksia.
Mihin FastAPI ei sovellu?
Voimakkaasti suoritinsidonnaisiin tehtäviin (kuvankäsittely, raskas numeerinen laskenta) Python on Go:ta tai Rustia hitaampi; ne siirretään erillisille workereille. Eikä mukana tule valmista adminia kuten Djangossa.
Tarvitseeko FastAPI ORM:n?
Ei välttämättä. Käytämme SQLAlchemy 2.0 asyncia ja Alembicia migraatioihin, mutta voit kirjoittaa puhdasta SQL:ää. ORM:ää ei ole mukana, joten valitset sen projektin mukaan.
Miten skaalaan FastAPI-backendin?
Horisontaalisesti: ajat useita Uvicorn-prosesseja Gunicornin alla kuormantasaajan takana, Redis-välimuistilla ja raskaat tehtävät siirrettynä Celerylle. Tilaton (stateless) suunnittelu mahdollistaa instanssien lisäämisen tarpeen mukaan.