CompanyBelgium

Rate limits, quota en caching om een KBO/BCE-applicatie te schalen: referentie-architectuur

Uw app bevraagt de KBO/BCE-API in volume — hoe 429's vermijden, kosten beheersen en latency garanderen? Referentie-architectuur met meerlaags cache, requestwachtrij, observability en webhooks. Concrete patronen en streefcijfers.

11 mei 20269 min leestijd

In het kort

De KBO/BCE-API van Company Belgium biedt leesbare rate-limit headers voor uw code. Om te schalen zonder uw quotum te overschrijden, combineert u een cache in 4 lagen (CDN, geheugen, gedeelde cache, DB-snapshot) met webhooks voor continue opvolging. Deze architectuur vangt 95 % van het verkeer op vóór de API en houdt de latency onder 50 ms.

Het probleem: van 100 naar 100 000 verzoeken/dag

U start met enkele calls per dag. Het product groeit. Zes maanden later doet uw app 100 000 lookups per dag. Als u de API roept bij elke pageview van elke gebruiker:

  • Verzadigt u uw quotum
  • Krijgt u 429 Too Many Requests
  • Betaalt u de volumefactuur
  • Verhoogt u de latency voor de gebruiker

De architectuur van dit artikel voorkomt dat. Ze is in productie getest.

Rate limits begrijpen

Anatomie van een venster

Een API biedt typisch een quotum per glijdend venster:

  • Free plan: 10 req/min, 100 req/dag
  • Starter plan: 60 req/min, 5 000 req/dag
  • Pro plan: 600 req/min, 100 000 req/dag
  • Enterprise plan: volgens contract

Company Belgium-headers:

Code
1
2
3
4
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 432
X-RateLimit-Reset: 1746541234
Retry-After: 30   (alleen bij 429)
X-RateLimit-Reset is een Unix-timestamp: op die seconde herstart het quotum.

De 3 types limieten

  • Burst (req/seconde) — voorkomt korte pieken
  • Sustained (req/minuut) — beschermt de infra
  • Daily quota — facturatie
  • Een goede app moet alle drie afhandelen, niet alleen de incidentele 429.

    Referentie-architectuur in 4 lagen

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [ User Request ]
    
    [ Browser cache + CDN ]            ← Laag 1 (gratis, buiten quotum)
    
    [ App-geheugencache (LRU TTL) ]    ← Laag 2 (10-100 ms)
    
    [ Gedeelde cache (memcached) ]     ← Laag 3 (1-10 ms netwerk)
    
    [ Database snapshot ]              ← Laag 4 (10-50 ms, versheid ~24u)
    
    [ KBO/BCE API ]                    ← Quotum & kost

    Doel: dat minder dan 5 % van de gebruikersverzoeken effectief de API in laag 5 raakt.

    Laag 1 — CDN / Browser

    Voor publieke endpoints zonder gevoelige gegevens, stel uw proxy-routes bloot met Cache-Control: public, max-age=300, s-maxage=600. CloudFront, Cloudflare, Vercel Edge Network doen de rest.

    Typisch effect: 50 tot 70 % van de verzoeken wordt vóór uw app opgevangen.

    Laag 2 — App-geheugencache

    LRU met TTL (zie de Python-tutorial en de Node.js-tutorial):

    • Capaciteit: 500 tot 5 000 fiches naargelang RAM
    • TTL: 5 min voor de fiche, 30 min voor NACE-codes
    • Eviction: LRU

    Typisch effect: +20 % opvang.

    Laag 3 — Gedeelde cache tussen processen

    Als u meerdere app-instanties hebt (Docker, Kubernetes, Vercel functions), is een lokale cache niet gedeeld. Gebruik:

    • Memcached: eenvoudig, snel, shared-nothing
    • In-cluster cache type Caffeine (Java), Tinybird (analytics)
    • Postgres met cache-tabel + index op de key (volstaat voor typisch SaaS-volume)

    Effect: een MISS op instantie A kan een HIT zijn op laag 3, 10 seconden eerder gevuld door instantie B.

    Laag 4 — DB-snapshot

    Voor apps die veel lookups op hun eigen cliënten doen (CRM, ERP, boekhouding), houd een lokale kopie van de KBO-fiches van de gevolgde ondernemingen. Gesynchroniseerd via webhooks.

    Voordelen:

    • Lokale queries: 10-50 ms
    • Geen netwerkafhankelijkheid bij lezen
    • SQL-filters/groepering mogelijk

    Nadelen:

    • Gegevens mogelijk enkele uren oud
    • Onderhoud van een tabel

    Het goede compromis voor 80 % van de SaaS B2B-cases.

    Laag 5 — Directe API-call

    Wanneer alle voorgaande lagen falen, roepen we de API. Omkaderd door:

    • Exponentiële retry op 429/5xx met respect voor Retry-After
    • Circuit breaker: bij > 50 % fouten over 1 min, stop calls 30 seconden
    • Harde timeout (10 s)
    • Lokale limiet: semafoor van max N gelijktijdige verzoeken

    Strategieën per gebruikscase

    A. Leveranciersverificatie (zelden, moet fris zijn)

    • Geheugencache 1 minuut
    • Geen CDN (cliëntafhankelijke gegevens)
    • Directe call bij miss

    Typisch API-volume: 1 req per dossier.

    B. Publieke directory weergeven (frequent, mag iets ouder)

    • CDN 30 min
    • Geheugencache 5 min
    • DB-snapshot 's nachts ververst
    • Directe call alleen bij volledige miss

    Typisch API-volume: 1 req per 100 views.

    C. Full-text zoeken (frequent, moet fris zijn)

    • Geen CDN (unieke query-URL)
    • Geheugencache 1 min met key = hash(query+filters)
    • Directe call bij miss

    Typisch API-volume: 1 req per 5-10 zoekopdrachten.

    D. Monitoring/waarschuwingen (continu, eventgedreven)

    • Geen polling — webhooks
    • DB-snapshot up-to-date via webhook
    • Geheugencache optioneel

    Typisch API-volume: 0 req per dag (alles komt via webhooks).

    Webhooks vs polling: de berekening

    U volgt 1 000 cliënten en wilt wijzigingen detecteren binnen 15 min.

    Polling:

    • 1 000 ondernemingen × (60/15) lookups/u × 24u = 96 000 req/dag
    • Pro plan nodig (100 000/dag)
    • Kost: ~300 €/maand

    Webhooks:

    • ~20 wijzigingen/dag (werkelijk geobserveerd)
    • 20 webhooks = 20 optionele lookups = 20 req/dag
    • Free plan volstaat
    • Kost: 0 €/maand

    Het verschil is 4 800×. Webhooks zijn bijna altijd het juiste antwoord voor monitoring.

    429's correct afhandelen

    Pseudocode voor een slimme retry:

    Code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function callApi(req):
      attempt = 0
      while attempt < 4:
        res = http.send(req)
        if res.status == 429:
          delay = res.header("Retry-After") || base * 2^attempt
          sleep(delay + jitter())
          attempt++
          continue
        if res.status in [500, 502, 503, 504]:
          sleep(base * 2^attempt + jitter())
          attempt++
          continue
        return res
      throw RateLimitExhausted()

    Jitter = willekeurige vertraging ±25 % om thundering herd te vermijden (alle instanties die tegelijk retryen).

    Observability

    Bloot te stellen metrics (Prometheus / Datadog / OpenTelemetry):

    MetricTypeWaarom
    bce_api_requests_total{status}counterVolume per HTTP-code
    bce_api_request_duration_mshistogramLatency p50/p95/p99
    bce_api_rate_limit_remaininggaugeResterend quotum (alert < 10 %)
    bce_cache_hits_total{layer}counterEffect per laag
    bce_circuit_breaker_stategauge0 closed / 1 half / 2 open

    Alert bij X-RateLimit-Remaining < 10 % → schakel over op DB-snapshot.

    Capaciteitstabel

    GebruikersvolumeMinimale strategieVereist API-quotum
    < 1 000 req/dagDirecte calls + retryFree
    1 K - 10 K req/dag+ geheugencacheStarter
    10 K - 100 K req/dag+ gedeelde cache + CDNPro
    100 K - 1 M req/dag+ DB-snapshot + webhooksPro of Enterprise
    > 1 M req/dagAlles + cache-shardingEnterprise + dedicated SLA

    Vaak voorkomende valkuilen

  • Foutresponses cachen — TTL=0 voor 4xx/5xx, anders "lockt" u een mislukking
  • Cache key zonder normalisatie"0200.065.765" en "0200065765" moeten dezelfde key delen
  • Geen deduplicatie — als 100 gebruikers dezelfde KMO in 100 ms vragen, doet u 100 calls. Implementeer een singleflight die identieke verzoeken in-flight groepeert
  • Geen fallback — als de API valt, valt uw app. Heb altijd een DB-snapshot
  • Gedeeld quotum tussen prod en batch — scheid de API-keys
  • Hoe Company Belgium helpt te schalen

    • Transparante rate-limit headers: uw code past zich aan
    • Webhooks voor 9 eventtypes (company.updated, company.ubo.changed, company.peppol.registered, enz.) — zie endpoints-referentie
    • Planstappen afgestemd op echte architecturen (Free, Starter, Pro, Enterprise)
    • Sandbox om te testen zonder het prod-quotum te verbruiken
    • Bulk endpoint op pro-plannen (100 fiches in één call)

    Samenvatting

    Een KBO/BCE-app schalen is niet gewoon een duurder plan betalen. De juiste architectuur vangt 95 % van het verkeer op vóór de API, via 4 cache-lagen en webhooks. Het quotum wordt een formaliteit, de latency blijft onder 50 ms, en de factuur volgt de waarde, niet het geluid.

    Drie hefbomen om in volgorde te activeren: geheugencache + retry, webhooks i.p.v. polling, DB-snapshot voor eigen cliënten. Daarmee verwerkt u 100 K req/dag gebruikersvolume met 5 K API-req/dag.

    Veelgestelde vragen

    Wat is een rate limit op de KBO/BCE-API van Company Belgium?

    Een rate limit begrenst het aantal verzoeken dat een applicatie per tijdvenster naar de API kan sturen. Op Company Belgium gelden limieten per minuut en per dag, afhankelijk van uw plan: 10 req/min op het gratis plan, 600 req/min op het Pro-plan. De headers X-RateLimit-Remaining en Retry-After informeren u realtime over de status van uw quotum.

    Hoe vermijdt u 429 Too Many Requests fouten bij de KBO/BCE-API?

    Implementeer een meerlaagse cache om herhaalde verzoeken op te vangen en een exponentiële retry met jitter voor verzoeken die toch de limiet bereiken. Het gebruik van webhooks in plaats van polling vermindert het aantal API-calls drastisch, vaak met een factor 4800. Scheid ook uw API-sleutels voor productie- en batchomgevingen om contention te vermijden.

    Welke cachestrategie is aanbevolen voor een Belgische SaaS B2B-app die de KBO-API gebruikt?

    De aanbevolen architectuur combineert 4 lagen: een CDN-cache voor publieke endpoints (TTL 5-10 min), een LRU-geheugencache per instantie (TTL 5 min), een gedeelde Memcached- of Postgres-cache tussen instanties, en een lokale DB-snapshot voor gevolgde ondernemingen. Deze combinatie vangt 95 % van het gebruikersverkeer op vóór de API en verlaagt kosten en latency.

    Webhooks of polling voor het opvolgen van wijzigingen in de KBO/BCE in 2026?

    Webhooks zijn vrijwel altijd te verkiezen. Met polling elke 15 minuten op 1000 ondernemingen verbruikt u circa 96 000 verzoeken per dag. Met de webhooks van Company Belgium ontvangt u alleen echte gebeurtenissen, gemiddeld circa 20 meldingen per dag voor dezelfde dekking. Het verbruiksverschil bedraagt een factor 4800, waardoor u vaak op het gratis plan kunt blijven.

    Klaar om te beginnen?

    Maak gratis een account aan en ontvang uw API-sleutels in enkele minuten.

    Reacties

    Reacties laden…

    Laat een reactie achter

    Niet gepubliceerd — alleen om u te verwittigen.

    Reacties worden gemodereerd voor publicatie.

    Gerelateerde artikelen

      Rate limits & caching KBO-API: schaalbare architectuur | CompanyBelgium