{"title":"We Reran Amber V2's Router on a $4 DigitalOcean Droplet","summary":"A controlled beta.4-versus-0.4.4 cloud rerun confirms the router improvement, corrects the old 55.7x headline, and publishes every paired trial.","date":"2026-08-13","category":"Performance","author":"Seth Tucker","url":"https://amberframework.org/blog/2026/08/13/amber-v2-router-on-a-four-dollar-droplet","markdown_url":"https://amberframework.org/blog/2026/08/13/amber-v2-router-on-a-four-dollar-droplet.md","json_url":"https://amberframework.org/blog/2026/08/13/amber-v2-router-on-a-four-dollar-droplet.json","image_url":"https://amberframework.org/assets/characters/way-sprites/performance-b-2a42ada333648e98882981886a50b7c9.webp","content_markdown":"# We Reran Amber V2's Router on a $4 DigitalOcean Droplet\n\nHere is the correction first: Amber's old `55.7x` router headline did not come\nfrom a cloud run, and it should not be repeated as a general Amber V2\nperformance claim.\n\nThe underlying router work is real. The old evidence was not strong enough for\nthe way we described it. We have now rerun the released Amber V2 beta.4 router\nagainst `amber_router` 0.4.4 on DigitalOcean's smallest $4 Basic Droplet, with\na corrected workload and every trial preserved.\n\n## What had actually run in the cloud\n\nAmber already had credible hosted performance evidence, but three different\nbenchmarks had been getting blended into one story:\n\n- The original router table was an in-process microbenchmark on an unspecified\n  local machine. Its notes recorded Crystal 1.18.2, but not the CPU, memory,\n  provider, or raw paired trials.\n- An April 21 Amber 1.4-versus-V2 HTTP comparison ran on DigitalOcean, but the\n  application server was an eight-vCPU CPU-optimized Droplet—not the smallest\n  target.\n- The July 17 mixed-application result and August 11 website result did use the\n  exact `s-1vcpu-512mb-10gb` size. Those are whole-HTTP capacity tests, not a\n  before-and-after test of the two router engines.\n\nSo the narrow question—how the released V2 router compares with Amber 1.x's\nrouter on that same tiny server—was still unanswered.\n\n## The replacement test\n\nThe measured target was DigitalOcean Basic `s-1vcpu-512mb-10gb` in NYC3: one\nshared `DO-Regular` vCPU, 512 MiB advertised memory, 469,236 KiB visible to\nLinux, no swap, and a 10 GiB disk. DigitalOcean's API listed it at $4 per month\nwhen the test ran on August 13, 2026.\n\nWe compiled two separate static x86-64 binaries with Crystal 1.21.0 using\n`--release --no-debug --static`:\n\n- before: `amber_router` 0.4.4, commit\n  `8f05718a4d49411e664f57a7f162565ce25fab75`;\n- after: Amber `2.0.0-beta.4`, commit\n  `a2128cdb4fef07025e0cc1c1578d4c807ae6c274`.\n\nBoth binaries received the same 100-, 1,000-, and 10,000-route tables. The mix\nwas 60% fixed, 25% variable, 10% variable with a fixed suffix, and 5% glob.\nEach glob route had a distinct match shape. We tested fixed, variable, glob,\nand not-found lookups with two seconds of warmup and five seconds of\nmeasurement per process.\n\nEvery scenario ran as seven before-and-after pairs. Odd repetitions ran the\nold router first; even repetitions ran V2 first. The result for each scenario\nis the median of its seven same-repetition V2/old ratios. That pairing matters\non shared cloud CPUs because both absolute rates can move when neighboring\nworkloads change.\n\n## Results\n\nAmber V2 was faster in all 84 individual pairs. Every scenario's median\nbootstrap interval stayed above `1.0x`, and alternating order did not change\nthe story: the geometric mean was `1.90x` when the old router ran first and\n`1.87x` when V2 ran first.\n\nAcross the 12 scenario medians, the geometric-mean speedup was **1.89x**.\n\n> **Unit:** every rate in this table is an in-process router lookup per second,\n> not a completed HTTP request per second.\n\n| Routes | Lookup | Amber 1.x router lookups/s | Amber V2 beta.4 router lookups/s | Median paired speedup | 95% bootstrap interval |\n| ---: | --- | ---: | ---: | ---: | ---: |\n| 100 | Fixed | 599,440/s | 885,523/s | **1.44x** | 1.35x–1.59x |\n| 100 | Variable | 796,564/s | 1,205,931/s | **1.55x** | 1.50x–1.60x |\n| 100 | Glob | 384,426/s | 608,145/s | **1.58x** | 1.56x–1.60x |\n| 100 | Not found | 669,406/s | 1,628,256/s | **2.31x** | 2.23x–2.55x |\n| 1,000 | Fixed | 481,508/s | 706,379/s | **1.43x** | 1.39x–1.55x |\n| 1,000 | Variable | 572,084/s | 999,892/s | **1.70x** | 1.66x–1.87x |\n| 1,000 | Glob | 252,411/s | 526,378/s | **2.03x** | 1.91x–2.08x |\n| 1,000 | Not found | 619,668/s | 1,280,214/s | **1.96x** | 1.92x–2.00x |\n| 10,000 | Fixed | 256,122/s | 417,707/s | **1.58x** | 1.45x–1.69x |\n| 10,000 | Variable | 306,469/s | 592,417/s | **1.95x** | 1.74x–2.02x |\n| 10,000 | Glob | 69,704/s | 310,112/s | **4.54x** | 4.33x–4.69x |\n| 10,000 | Not found | 441,333/s | 828,546/s | **1.82x** | 1.72x–1.97x |\n\nThe 100-route rows are the best shorthand for an ordinary application: fixed,\nvariable, and glob lookup medians improved by 44% to 58%, while the tested\nnot-found path improved by 131%. At the intentionally extreme 10,000-route\ntier, the corrected unique-glob lookup improved by 354%.\n\nThe intervals are deterministic percentile-bootstrap intervals over seven\npaired ratios. They describe the repeatability of this bounded run; they are\nnot a promise about every cloud host or application.\n\n## Why `55.7x` changed\n\nThe old glob generator varied the glob parameter name but reused only five\neffective URL shapes. At the 10,000-route tier, its 500 declared glob routes\nbecame 100 terminal entries behind each of those five shapes. The old test\nreally did measure that duplicate-route edge case, but the result was described\nas though it represented 10,000 unique routes.\n\nThe replacement generator gives every glob route a unique prefix and looks up\nthe last one. That is a cleaner test of a large route table and a harder test\nof the old router's linear child scan. It also produces a much smaller, much\nmore defensible number than `55.7x`.\n\nThe audit found two other historical-label problems. The old generator called\n10% of its routes \"constrained\" without ever passing a regular-expression\nconstraint, and the cross-framework script loaded stored Amber results while\nrunning only the third router fresh with a different route generator. We have\ncorrected those descriptions and marked that cross-framework output as\nhistorical mixed-provenance material, not a ranking.\n\n## What changed in V2\n\nThe Amber 1.x router kept fixed, variable, glob, and terminal children together\nin one array. Matching scanned that mixed array and performed runtime type\nchecks along the way. Beta.4 separates those structures: fixed segments use a\nhash, variable segments stay in a small array, a glob gets its own slot, and\nterminal leaves live separately as value types.\n\nV2 also registers route segments by index instead of repeatedly shifting an\narray and splits paths into a pre-sized array in one pass. Registration is\nrecorded by this benchmark but excluded from timed lookup throughput.\n\nOne earlier explanation said `RoutedResult` became a struct. It did not;\n`RoutedResult` remains a class in beta.4. The performance gain does not require\nus to overstate the implementation.\n\n## Router lookups are not HTTP requests\n\nThese rates measure only `RouteSet#find`. They exclude sockets, HTTP parsing,\nmiddleware, controller dispatch, ECR rendering, JSON serialization, databases,\nTLS, reverse proxies, and the public network. Millions of router lookups per\nsecond must never be presented as millions of HTTP requests per second.\n\nFor complete application behavior, use the separately documented hosted\nresults: the 26,271-byte Amber website homepage sustained a 5,907 requests per\nsecond median on this size, while a deterministic mixed 1,000-route JSON\nworkload sustained 21,795 requests per second. Those workloads answer a\ndifferent question and keep their own limitations.\n\n## Inspect and reproduce it\n\nThe [machine-readable summary](/benchmarks/amber-v2-router-digitalocean-2026-08-13-summary.json)\ncontains the target, source revisions, compiler, binary checksums, workload,\npaired ratios, intervals, and limitations. The [raw 168 trials](/benchmarks/amber-v2-router-digitalocean-2026-08-13-raw.jsonl)\nand [machine snapshot](/benchmarks/amber-v2-router-digitalocean-2026-08-13-machine.txt)\nare published beside it. The harness lives in Amber's\n`benchmarks/router_cloud/` directory.\n\nThe honest conclusion is better than the old headline: Amber V2's released\nrouter is measurably faster on the smallest server used for these published\nexperiments, the result survives paired cloud trials, and you can inspect every\nnumber we used to say so.\n"}