Building a GraphQL Video Discovery API
Toen onze videodatabase groeide naar honderdduizenden records, werd onze API de bottleneck.
Eén enkel scherm had vijf verschillende REST-aanroepen nodig om trending video's, kanaalgegevens, tags, weergaveaantallen en aanbevelingen te tonen. Mobiele gebruikers met trage verbindingen moesten 30 verzoeken versturen om slechts één pagina te laden.
GraphQL lost dit op. De client vraagt precies wat hij nodig heeft in één enkel verzoek.
Ik heb een productie-waardige video discovery API gebouwd met Strawberry en FastAPI. Hier is hoe ik dat heb gedaan.
Why Strawberry?
Ik heb Graphene en Ariadne getest, maar Strawberry won om de volgende redenen:
• Type hints zijn het schema. Je schrijft Python-code en Strawberry bouwt de GraphQL-types. Handmatige synchronisatie is niet nodig. • Het is async-native. Hierdoor kan de API veel verzoeken afhandelen zonder de event loop te blokkeren. • De integratie met FastAPI is naadloos. Het GraphQL-endpoint bevindt zich direct naast de bestaande REST-routes. • Ingebouwde DataLoader. Deze tool lost het N+1-probleem direct op.
The Data Stack
De data staat in een SQLite-database die wordt beheerd door een PHP-site. Ik gebruik SQLite FTS5 voor snelle full-text search.
De Python-service leest deze database als een read-only laag. Dit zorgt ervoor dat er slechts één source of truth is.
Om de zoekervaring prettig te maken, combineer ik FTS5-relevantiescores met een populariteitssignaal. Dit voorkomt dat één virale video alle andere zoekresultaten overschaduwt.
Solving the N+1 Problem
Een veelvoorkomende valkuil in GraphQL is het N+1-probleem. Als je 20 video's ophaalt en vervolgens voor elke video het kanaal ophaalt, zal een naïeve API 21 databasequeries uitvoeren.
DataLoader lost dit op door middel van batching. Het verzamelt alle kanaal-ID's in één 'tick' en voert één enkele query uit om ze allemaal op te halen. Hierdoor daalde onze querytijd van 40ms naar minder dan 5ms.
Key Design Choices
• Opaque ID's: Ik gebruik strings voor ID's. Dit maakt toekomstige wijzigingen mogelijk zonder dat client-apps kapot gaan. • Bewuste nullability: Ik definieer welke velden leeg kunnen zijn. Dit helpt clients om ontbrekende data af te handelen zonder vast te lopen. • Read-only schema: De GraphQL API verwerkt geen writes. Dit voorkomt veel hoofdpijn op het gebied van beveiliging. • Edge Caching: GraphQL gebruikt standaard POST, wat lastig te cachen is. Ik gebruik Automatic Persisted Queries (APQ) om caching via Cloudflare mogelijk te maken.
Als je worstelt met te veel aangepaste endpoints of complexe queryparameters, dan is deze stack een sterke optie.
