Skip to content

Benchmarks

Every number on this page is read from a raw results file in bench/results/ by make bench-report; none is typed by hand. Each file records the machine, its power state, the Go and Postgres versions and settings, the commit, and a hash of the code it measured.

0.1.0-dev · Apple M1, 8 cores, 8 GB · PostgreSQL 18.6 (Homebrew) (native) · on AC power

Target (contract §12) Measured (median of runs) Target Result Raw file
Gate · allow, no witness p50 5.81 ms · p99 19.4 ms p50 < 5 ms · p99 < 25 ms ✕ missed bench/results/2026-10-05-darwin-arm64-bench-gate.json
Policy · 50 rules p99 148 µs p99 < 1 ms ✓ met bench/results/2026-10-05-darwin-arm64-bench-policy.json
Witness · L2 at 100 writes/s p50 118 ms · p99 317 ms p50 < 1 s ✓ met bench/results/2026-10-05-darwin-arm64-bench-witness.json
Verify · 100,000 deeds 1.53 s · 80.9 MiB < 5 s · < 256 MiB ✓ met bench/results/2026-10-05-darwin-arm64-bench-verify.json
Stop · across 2 instances max 23.5 ms over 20 trials < 2 s ✓ met bench/results/2026-10-05-darwin-arm64-bench-stop.json
Quickstart · clean machine 0 min 6 s < 5 min ✓ met bench/results/2026-10-05-darwin-arm64-bench-quickstart.json

5 targets met · 1 missed.

Reported, no target Measured (median of runs) Raw file
deed · seal.one_org deeds_per_s 325 · orgs 1.00 bench/results/2026-10-05-darwin-arm64-bench-deed.json
deed · seal.ten_orgs deeds_per_s 669 · orgs 10.0 bench/results/2026-10-05-darwin-arm64-bench-deed.json
gate · actions.deny p50 4.11 ms · p99 11.6 ms bench/results/2026-10-05-darwin-arm64-bench-gate.json
gate · actions.approval_create p50 6.42 ms · p99 21.8 ms bench/results/2026-10-05-darwin-arm64-bench-gate.json
mcp · mcp.wrap_added relay_passthrough_p99_ms 0.03 · tools_call_added_p50_ms 3.18 · tools_call_added_p99_ms 4.30 · tools_list_added_p50_ms 0.72 · wrapper_peak_rss_mib 55.9 bench/results/2026-10-05-darwin-arm64-bench-mcp.json
policy · evaluate.10_rules p50 0.01 ms · p99 0.07 ms bench/results/2026-10-05-darwin-arm64-bench-policy.json
policy · evaluate.200_rules p50 0.17 ms · p99 0.42 ms bench/results/2026-10-05-darwin-arm64-bench-policy.json
policy · evaluate.500_rules p50 0.41 ms · p99 0.91 ms bench/results/2026-10-05-darwin-arm64-bench-policy.json
soak · soak.mixed rss_growth_after_5min_pct 15.4 bench/results/2026-10-05-darwin-arm64-bench-soak.json
verify · verify.100k_bundle deeds 100,000 · peak_rss_mib 68.8 · wall_s 1.58 bench/results/2026-10-05-darwin-arm64-bench-verify.json
wal · wal.update_identity_default max_record_bytes 8,515 · overhead_vs_default_pct 0.00 · record_bytes_per_txn 226 · records_per_txn 3.00 bench/results/2026-10-05-darwin-arm64-bench-wal.json
wal · wal.update_identity_full max_record_bytes 8,577 · overhead_vs_default_pct 27.4 · record_bytes_per_txn 288 · records_per_txn 3.00 bench/results/2026-10-05-darwin-arm64-bench-wal.json
wal · wal.full_plus_ledger_and_marker max_record_bytes 644 · overhead_vs_default_pct 185 · record_bytes_per_txn 644 · records_per_txn 6.00 bench/results/2026-10-05-darwin-arm64-bench-wal.json
witness · l2.10_per_s sent_in_s 59.9 bench/results/2026-10-05-darwin-arm64-bench-witness.json
witness · l2.500_per_s p50 0.00 ms · p99 0.00 ms bench/results/2026-10-05-darwin-arm64-bench-witness.json
  • Open loop. Requests leave at a fixed arrival rate. Latency is measured from each request’s intended send time, so a slow server shows in the tail instead of slowing the generator down (no coordinated omission). When 256 requests are in flight, the next one waits, and that wait counts.
  • Warm-up, runs, percentiles. 10 seconds of warm-up are discarded, then 60 seconds are measured, three times. The table shows the median of the three runs; each file keeps every run with its count, errors, achieved rate and p50/p90/p95/p99/p99.9/max. A run with any error fails its target.
  • Histogram. Log-linear buckets from 1 µs to 60 s; a percentile is within 1% of the exact value (a unit test checks it on 10⁶ samples).
  • Gate overhead is an upper bound. It is the client-observed time of POST /v1/actions over loopback against the fake.echo connector (0 ms): HTTP, JSON, the policy, the database writes and the sealed deed all count. The Gate’s own share is smaller.
  • L2 timing uses database clocks: the decoded transaction’s commit time to the deed’s issued_at.
  • What make bench-check refuses. A run on battery or unknown power, a file whose code hash differs from the working tree (stale), and quick runs (except for a release candidate).
  • Postgres settings recorded in every file include synchronous_commit, fsync, shared_buffers and wal_level.
Suite What it measures
gate POST /v1/actions: allowed (fake.echo), denied by a rule, and creating an approval; 200/s, 8 agents, one org
policy One evaluation in process at 10, 50, 200 and 500 rules, the worst case (every rule’s condition runs)
deed Sealed deeds per second through the Gate for one org and ten orgs; one org’s chain is serial by design
witness L2 commit → verdict at 10, 100 and 500 writes/s through a real server, the decoder and the Postgres connector
wal WAL bytes per single-row UPDATE: identity DEFAULT, identity FULL, and FULL with the ledger row and marker
verify deedglass verify of 100,000 deeds signed by two keys, as JSON lines and as a bundle: wall time and peak memory
stop Stop all on one instance while another serves 50 calls/s: time until the second refuses, 20 trials
mcp tools/call through deedglass mcp wrap against the same stdio server called directly
quickstart deedglass init from a clean directory to a blocked and a verified action
soak 30 minutes at 50 calls/s (70% allowed, 20% denied, 10% approval): memory, open files, connections
Terminal window
make bench # every suite on a throwaway Postgres 18 (about 45 minutes), then bench-report
make bench-soak # 30 minutes
make bench-check # the six contract targets on the newest results
make bench-report # this page's table and bench/results/SUMMARY.json

Plug the machine in first. Set DEEDGLASS_BENCH_HOST to name the machine in the file names.

  • How Deedglass behaves across a real network, on managed Postgres, or with a cold cache.
  • How other hardware compares: the numbers are for the machine in the table, with Postgres on the same machine.
  • The Gate’s own overhead without HTTP and the database, which is smaller than the upper bound.