Skip to content

← Back to projects

Publicaciones

APQ Case Study

Period: Nov 2025 —

Shipped

The challenge

Large GraphQL schemas pay full request-body cost on every operation even when the operation is a repeat. The cost shows up as bandwidth, CPU on the server, and p95 latency on the wire.

My role

I published a case study on Automatic Persisted Queries at scale: 90.9% cache hit rate over a 135,504-line schema, 2,089 query types, 707 Prisma models, with a cgroup v2-isolated compile runner and a five-phase auto-warmup.

What I did

  1. 01

    Two-layer cache (server-side APQ + client-side persist)

    Why: Server-side APQ cuts the request body to a hash; client-side IndexedDB + Service Worker cache cuts the round trip entirely for repeat queries. The two layers cover different cases — same query, different transport.

    Trade-off: Two cache surfaces to invalidate on schema change. The schema-hash invalidation pattern handles the bulk of the problem; the edge cases need manual review.

  2. 02

    Auto-warmup pre-caches the hot 2,130 queries

    Why: Cold-start latency is the cost a new replica pays until the cache fills. The five-phase auto-warmup pre-caches the queries most clients will hit in the first 30 seconds, so a replica warms up before the first real client arrives.

    Trade-off: Five-minute startup ceremony per replica. Worth it for a 30-second cold-start improvement on the live traffic path.

  3. 03

    cgroup v2 runner isolation for the compile step

    Why: Schema compilation can OOM a shared node. The compile runner runs in a cgroup v2 slice with MemoryMax=16G so a compile spike cannot cascade into the production workers.

    Trade-off: Compile runs slower in the slice than it would on bare metal. The latency cost is bounded; the safety win is total.

What changed

  • Cache hit rate in production

    Before: 0%

    After: 90.9%

    Evidence: case-study-apq-performance telemetry, 2026-Q3

  • p95 latency reduction

    Before: 25 ms without APQ

    After: 12 ms with APQ

  • Payload reduction on cached queries

    Before: 100% body

    After: 25% body (75% reduction)

  • External SaaS spend for the APQ stack

    Before: $0 — not yet implemented

    After: $0/month — self-hosted Redis + Lua EVAL

Trade-offs

The cgroup v2 isolation adds operational surface. We chose it over a hosted compile service because the audit chain had to be self-hostable end to end.

What I learned

Two-layer caches pay back only when invalidation is honest. Schema-hash invalidation is the honest version; TTL-based invalidation is a lie that compounds over time.

Stack

  • GraphQL
  • Apollo Server v4
  • Redis 7
  • IndexedDB

Evidence

← Back to projects · curated 2026-09-20