Skip to content

Architecture

Patomic is Cloudflare-native end to end. Every request hits a Worker; nothing lives behind a load balancer. This page is the mental model — the moving parts and what each is for.

client
│ Authorization: Bearer ptmc_…
Cloudflare edge (~250 colos)
│ Worker cold-start: 0 ms (kept warm), p95 cold ≈ 5 ms
secureHeaders → structuredLogger → onError(global)
▼ /v1/* only:
authMiddleware
│ 1. Bearer extract (in-memory)
│ 2. PBKDF2(key, secret) (Web Crypto, ~ms)
│ 3. SELECT api_keys (D1, ~5–20 ms)
│ 4. attach { user, apiKey }
rateLimitMiddleware
│ INSERT rate_limits ON CONFLICT DO UPDATE RETURNING count
│ Atomic. No race. Per-(key, minute-window).
idempotencyMiddleware (non-safe methods only)
│ KV.get → if cached, replay verbatim.
route handler
│ validation (Zod) → repo → response
client

Every middleware emits structured JSON logs correlated by cf-ray, surfaced as x-request-id. Errors flow through Sentry with environment + release tags.

The system of record. Holds:

  • users — accounts
  • api_keys — authentication
  • audit_log — every auth event, rate-limit breach, key mutation
  • rate_limits — minute-window counters
  • (Phase 2) patents, assignees, inventors, cpc_codes, citations

Reads scale to ~50k/sec via read replicas. Writes go to the primary region (currently WEUR / London). Roughly 10 ms p50 from a colo near WEUR; ~150 ms from far regions for writes.

Hot reads, idempotency cache, future per-API-key caches. Sub-millisecond reads at the colo level. Eventually consistent globally — fine for caches, not used as a system of record.

(Phase 2.) Patent full-text, original PDFs from each jurisdiction, archival audit log dumps when retention expires.

(Phase 3.) Embeddings of claim text, abstract, and key element extracts. Semantic search over millions of patents in under 100 ms.

(Phase 2.) Ingestion pipeline. New patent batches from USPTO/EPO/WIPO/JPO/CNIPA are pushed onto a Queue; per-jurisdiction consumers pull, normalise, write to D1+R2+Vectorize. Durable Objects coordinate the canonicalisation across jurisdictions.

ConcernChoiceWhy
RuntimeCloudflare WorkersGlobal edge, sub-100 ms p95, free tier scales
HTTP frameworkHonoWorkers-first, type-safe, OpenAPI integration
ValidationZod (via @hono/zod-openapi)One schema → runtime validation + OpenAPI doc
ORMDrizzleType-safe, no codegen, Workers-friendly
Auth hashPBKDF2-SHA256 with server-side saltDeterministic for O(1) lookup, brute-force-resistant
Rate limitAtomic D1 upsertTrue atomic — no Promise.all([COUNT, INSERT]) race
Webhook sigHMAC-SHA256, Stripe-compatible headerEngineers familiar with Stripe webhooks recognise it instantly
PaginationSigned-cursor keysetStable under concurrent inserts, O(1) per page
Error contractStripe-grade envelopetype, code, message, docs_url, request_id, suggestion