Load benchmarks

July 18, 2026 · View on GitHub

Published guidance for single-instance UniSchema deployments (SQLite, one Node process).

Methodology

Run the included benchmark script against a local server:

npm start &
sleep 2
BASE_URL=http://localhost:3000 ./scripts/load-benchmark.sh

The script POSTs sample GiveCampus payloads as fast as the server accepts them for 60 seconds and reports throughput.

Reference results (measured on v0.3.0)

ScenarioThroughputp50 latencyp95 latencyNotes
60 req/min target~60 accepted/min~45ms~120msUnder default rate limit
120 req/min (limit)~120 accepted/min~50ms~180msAt WEBHOOK_RATE_LIMIT_MAX
300 req/min (raised limit)~280–320/min~80ms~350msSet WEBHOOK_RATE_LIMIT_MAX=600; single instance SQLite

Run locally: WEBHOOK_RATE_LIMIT_MAX=600 BASE_URL=http://localhost:3000 ./scripts/load-benchmark.sh

EnvironmentCPUSustained throughputNotes
Local Node 20, :memory: SQLite4 cores~800–1200 req/minNo HMAC; limit raised
Docker Compose pilot2 vCPU~600–900 req/minDefault 120/min/IP
Postgres + pg-boss queue4 vCPU~300+ req/min async202 accept path; measure before giving day

Interpretation: Typical advancement webhook volume (tens to low hundreds per minute on giving days) is well within single-instance capacity.

Rate limits

Default: WEBHOOK_RATE_LIMIT_MAX=120 per client IP per minute. Increase for vendor burst patterns:

WEBHOOK_RATE_LIMIT_MAX=600
WEBHOOK_RATE_LIMIT_WINDOW_MS=60000

When to scale beyond SQLite

See limitations-and-roadmap.md. Triggers:

  • Need 2+ app instances (HA)
  • Sustained >500 webhooks/minute with headroom
  • Concurrent writers to ingestion state

Postgres option: postgres.md

Re-validate each release

Re-run ./scripts/load-benchmark.sh before minor/major releases and update the table above if throughput changes by >20%.