Design and dispatch benchmarks

What ships in OPTZ 0.4, what remains an integration, and measured static dispatch costs.

On this page

Research date: 2026-10-28. Baseline: f5a5bb0 (the merged security/deployment work). The design target is the existing Bun + React/Preact islands framework on a small VPS, with SQLite and revocable server-side sessions, as requested. The comparisons below describe capabilities, not interchangeable APIs or a claim of complete compatibility.

What the other frameworks actually contribute

FrameworkUseful model to adoptHow OPTZ applies it
Next.jsServer-side data access layer, authorize each data operation, Server Actions, server-only boundaries, request instrumentationKeep existing actions/rendering; add guarded .server.ts modules, optional observation and a starter that authorizes in SQL/data access
SvelteKitNative form actions, fail() field errors, progressive enhancement, cookie/local request context, adaptersStandard Schema/function validation with safe 422 field errors; HTML forms in the starter work without JS; storage contracts stay separate from rendering
AstroSessions with pluggable drivers, validated Actions, islands, schema-validated content collections, isolated server islandsAdd revocable session stores and validation; retain client islands; defer a new content compiler and isolated server-island protocol until workloads justify them
React Router (Remix model)Route-oriented loaders/actions, cookie/session storage contracts, upload handlingReuse current loaders/API/actions; provide a small session store contract and bounded private upload storage
Nuxt/NitroServer utilities, middleware, route caching, deployment adapters, lazy hydration and performance budgetsKeep SSR/ISR/proxy/edge features; add optional security/observation utilities while preserving the static path
HonoSmall opt-in CSRF, CORS, secure-header and SSE helpersOffer explicit optz/security and optz/stream modules without adding a middleware stack to every request
TanStack StartTyped server functions, middleware and an authentication integration boundaryPreserve generated API types/actions; avoid hard-wiring a hosted auth provider or ORM into core

Authentication libraries, email delivery, payment services, authorization policies and durable job infrastructure are product choices. Next.js, SvelteKit and TanStack document integrations; they do not bundle a universal production identity service, ORM and background-job service. This release provides a working local app and replaceable primitives, while keeping those external choices explicit.

Gap analysis and what ships

AreaBefore this changeThis implementationCost when unused
Pages, nested/parallel/intercepted routes, streaming, ISR, i18nAlready presentPreserved and regression-testedExisting configurable behavior
Client islands, Preact, prefetch and accessible navigationAlready presentPreservedPages without islands do not ship React
Typed APIs and Server ActionsAlready presentPreservedFeatures can be disabled
SessionsCookie primitives and social-demo bearer tokensoptz/sessions: opaque 256-bit tokens, hash-only server keys, rotation/revocation/expiry, custom store contractNo session lookup or store in core
Persistent app dataProject-specific Rust feed engineoptz/sqlite: Bun native DB, WAL/foreign keys, transactional checksum-protected migrations, persistent session adapterBun SQLite is imported only by applications using it
Input validationTyped JSON parsing, application checksoptz/forms: Standard Schema V1 or a function validator; bounded JSON/form parsing, safe structured field errorsNo bundled schema dependency
Browser/server separationLoader export strippingBrowser build rejects transitive .server.*, app/lib/server/ and private OPTZ importsBuild-time only
Request securityApplication-authored middlewareOpt-in CSRF, allowlisted CORS, safe headers, bounded local rate limiterNo global auth/security middleware added
AttachmentsStatic assets and image optimizeroptz/storage: streaming writes, quotas supplied by caller, random keys, private attachment reads, no path traversal or symlink readsNo storage code or file I/O in the core request path
Live updatesGeneric Response streamsoptz/stream: pull-based SSE, event-size budget, framing validation, cancellation and cleanupNo connection pool or timer unless an app opens one
ObservationRequest log optionoptz/observe: request ID, Server-Timing, response/error callbacks excluding queries/credentials/bodiesOpt-in middleware
Complete starterRendering/API examplesoptz create DIR --template fullstack: accounts, private notes, private attachments, SSE endpoint, native forms and environment/state guideSeparate template/app
Large route tablesLinear server route scansExact-route map plus ordered dynamic prefix candidatesO(routes) startup index; tiny per-request lookup

Full application shipped

apps/fullstack/ is executable application code, not pseudocode. It demonstrates:

  1. A static public landing page, dynamic login/error page, and protected dashboard.
  2. Argon2id password hashes through Bun's native async password API, with a bounded hash-work budget.
  3. Session identity rotation at login, persistent hashed tokens in SQLite and logout revocation.
  4. Authentication at the data access boundary and owner predicates on every note/file query.
  5. Create, list, toggle and delete private notes through native HTML forms.
  6. Bounded multipart parsing, upload concurrency and per-user file quotas; private attachment downloads.
  7. Cookie-authenticated mutation origin checks and strict response security headers.
  8. Bounded authenticated SSE connections; streams observe disconnects and session revocation.
  9. API-level integration tests for two identities, cross-user denial, CSRF and process restart persistence.
  10. A browser suite that performs registration, notes, upload and logout with JavaScript disabled.

The example rate limiter and SSE connection budget are per process. Multi-replica deployments must use an external/shared limiter and session store. The cookie/session manager itself is portable; the provided SQLite store is a Bun/single-machine option. Password recovery, verified email, OAuth, MFA, invites and account administration are not silently approximated by the demo. Use a maintained identity provider when the product needs them.

The separate authentication package now supplies maintained Better Auth integration, verified email, recovery, OAuth/OIDC, passkeys and MFA. Its example is apps/auth/; it does not change the deliberately small fullstack template.

Performance changes and evidence

  • Compile the immutable server manifest once. Exact static paths no longer scan unrelated routes. Dynamic candidates are filtered by their leading static segment and merged in original order, preserving catch-all, optional and custom manifest precedence. Fully generic dynamic patterns can still require a linear candidate scan.
  • Skip middleware identity planning when no middleware is registered. Authentication remains checked in the data layer; the security middleware pipeline is preserved when installed.
  • Optional app modules are separate package exports, never imported by the default client API. No ORM, auth SDK, validator or middleware framework was added to runtime dependencies.
  • Repeated form fields append to an array instead of repeatedly copying its full contents.
  • Notes use one conditional SQL insert for quota enforcement; file metadata insertion also checks the quota atomically. Prepared statements are reused by Bun's SQLite query cache.
  • Request-time database initialization is lazy, migrations run once per app process, and public page builds do not create a database. Async native password work has a concurrency budget.

bench/fullstack.ts compares linear matching and the prior full handler with the updated code. Raw results, CPU/runtime, baseline commit, source hash, dirty-tree flag and individual samples are in bench/fullstack-results.json. Measurements are warmed in-process static dispatch, not network throughput, database latency, SSR rendering or a fresh comparison with other frameworks. Use the separate existing network benchmark for production HTTP claims.

Reproduce against the merged baseline:

git worktree add --detach /tmp/optz-base f5a5bb0
ln -s "$PWD/node_modules" /tmp/optz-base/node_modules
bun bench/fullstack.ts --baseline /tmp/optz-base --out bench/fullstack-results.json

Measured dispatch result

The final local run used Bun 1.4.4 on AMD EPYC 9V45 96-Core Processor. Five warmed, interleaved samples per case, median shown. These fixtures request the last static route in a manifest; the middleware case adds one response-header middleware. Small-manifest differences can be within machine noise.

Static dispatch as the route table grows

Microseconds / operation · lower is better

Previous handlerIndexed handler
View exact values
Static dispatch as the route table grows (Microseconds / operation · lower is better)
CasePrevious handlerIndexed handler
10 routes · no middleware3.6352.127
10 routes · 1 header3.6863.397
100 routes · no middleware4.7471.832
100 routes · 1 header5.0432.935
1000 routes · no middleware20.3372.109
1000 routes · 1 header20.0233.16
Measured October 28, 2026, Bun 1.4.4, AMD EPYC 9V45. Five warmed, interleaved samples; medians shown. Last static route in the manifest. Dirty working tree recorded in source. In-process dispatch only: no network, database, SSR or production tail latency claim. Raw data and provenance.
RoutesHeader middlewarePrevious handler µsUpdated handler µsRatio
1003.642.131.71×
1013.693.401.08×
10004.751.832.59×
10015.042.941.72×
1000020.342.119.64×
1000120.023.166.34×

The route matcher alone improved more than complete dispatch, because response construction, security policies and rendering still cost time. No new network req/s, p99 or full-app SSR performance claim follows from this table. All optional application modules remained off in these fixtures.

Route matching cost

Route matching cost

Microseconds / lookup · lower is better

Linear scanIndexed lookup
View exact values
Route matching (microseconds / lookup)
RoutesLinear scanIndexed lookup
100.7340.183
1004.8450.237
100052.8500.258
Same October 28 fixture, route matcher only. Both axes are linear and start at zero; points are measured at 10, 100 and 1,000 routes. Lines connect samples and do not predict intermediate results. The indexed series stays near zero at this scale; exact measurements are available below. Raw data and provenance.

Matching alone excludes response construction, security policy and rendering. Its improvement does not imply the same speedup for a complete request. See the exact-value disclosure for the three measured route counts.

Verification

The following records the original routing/full-stack release checks. Current optional-module checks and browser-size budgets are recorded separately in Optional modules.

  • 111 framework tests, 617 assertions; includes persistent-session and two-user application tests.
  • Framework and all six applications type-check; all six production builds pass.
  • Portfolio browser checks: 30/30; features: 25/25; SPA: 7/7; full-stack registration/notes/upload/ logout also pass with JavaScript disabled.
  • Existing feature app still builds as an edge worker; the SQLite starter targets Bun.
  • All 24 package exports import cleanly. Dependency audit reports no known vulnerabilities across 175 checked packages. No runtime ORM, schema validator or auth SDK was added.
  • Existing deployment controller/runner checks pass (13 + 4 Python tests).

Further work worth doing, with reasons

The optional status, analytics/PostHog, S3-compatible uploads, Cloudflare cache, database integrations and Doppler workflow are implemented. The remaining priorities are:

  1. Further identity integrations. Enterprise SAML/SCIM and operational provider policies remain separate from the existing Better Auth, OAuth/OIDC, passkey and MFA integration.
  2. Distributed operational state. Shared rate-limit enforcement and failover need production adapters and operational checks. SQL sessions and object storage are available integration boundaries; local SQLite and in-memory budgets do not become multi-machine services.
  3. Durable work and scheduling. Email/webhook retry and long tasks need a durable queue, idempotency and a separate worker. after()/SSE are not durable jobs.
  4. WebSocket adapter support. Bun upgrades, per-connection authorization, limits and shutdown must be designed together. SSE is implemented for one-way events now.
  5. Asset memory budgets. Large public media should stream from disk/object storage; the current all-in-memory static map suits small sites. Private uploads already stream from storage.
  6. Content collections. A schema-validated build-time loader layer can replace app-specific Markdown code without putting Markdown/MDX dependencies into every application.
  7. Isolated server islands. Astro-style deferred personalization could keep a public shell cacheable, but requires a separate authenticated fragment protocol, not just another Suspense boundary.
  8. Lifecycle and instrumentation adapters. OpenTelemetry export, graceful shutdown and worker draining should be opt-in and cover Bun/compiled/edge targets rather than global mutable hooks.
  9. Response protocol completeness. Shared encoding-quality negotiation is tested; range requests and streaming large public assets still need coverage before advertising file-server parity.
  10. Benchmarks and budgets. Track network p95/p99, cold starts, RSS under load, protected API latency, build time and browser JS alongside dispatch. A routing microbenchmark alone does not establish that a complete app is faster than another framework.

Avoid importing a default ORM, globally checking sessions on static requests, hydrating the whole application for a form, or adding a background process to serve public HTML. These would spend the framework's existing static-first advantage without solving an application need.

Primary sources consulted

Official documentation was retrieved directly, with Context7 cross-checks for the three requested frameworks. These links describe capabilities; they are not performance evidence.