OgerJS

TypeScriptMIT★ 0forks 0

README

OgerJS

Ultra-fast Bun-native HTTP framework with fluent macro ergonomics, zero-dependency core, native Bun.serve({ routes }) routing, composable plugins, and built-in t validation.

Version 0.2.0 · Bun >= 1.2.3 · Node.js 18+ via HTTP fallback (ogerjs/compat) · Published on npm by Ogulcan Studio

npm i ogerjs
# or
bun add ogerjs

The speed story

OgerJS is built around the number teams feel first: how many banking-shaped requests your API can serve per second — with real auth, validation, nested routes, and batch JSON payloads, not just a hello-world ping.

Measured with the Go runner in benchmark/ (500 requests, 128 concurrency, 50 warmup, 8 runtimes × 12 scenarios):

bun run build
cd benchmark
go run benchmark.go

OgerJS (Bun) wins 12 / 12 scenarios. Local run: Windows AMD64, Bun 1.3.14, Go 1.26.3.

Speed signal OgerJS (Bun) vs Hono (Bun) vs Express
Plain ping GET / 39,708 req/s +66% faster 7.6× faster
JSON body parse 32,533 req/s 2.2× faster 9.6× faster
Transfer validation 32,958 req/s 1.5× faster 5.0× faster
Large JSON batch 25,488 req/s 1.8× faster 4.9× faster
Auth gate 21,280 req/s 1.3× faster 3.2× faster
Middleware chain 36,495 req/s 1.5× faster 4.2× faster
Average throughput ~26,540 req/s +46% vs Hono (Bun) 3.9× vs Express

Full benchmark output (req/s, p50, p99)

── GET / (ping) ──
  Vanilla Bun     32702 req/s |  500 ok | p50  2.73 ms | p99  7.13 ms | err 0
  Vanilla Node    12312 req/s |  500 ok | p50  6.73 ms | p99 34.25 ms | err 0
  OgerJS (Bun)    39708 req/s |  500 ok | p50  2.07 ms | p99  6.40 ms | err 0
  OgerJS (Node)    6908 req/s |  500 ok | p50 13.72 ms | p99 62.11 ms | err 0
  Hono (Bun)      23929 req/s |  500 ok | p50  3.85 ms | p99 11.18 ms | err 0
  Hono (Node)      9393 req/s |  500 ok | p50 10.24 ms | p99 39.48 ms | err 0
  Elysia          28437 req/s |  500 ok | p50  3.76 ms | p99  8.07 ms | err 0
  Express          5237 req/s |  500 ok | p50 12.36 ms | p99 93.33 ms | err 0
  → fastest: OgerJS (Bun) (39708 req/s)

── POST /bench/json-parse ──
  Vanilla Bun     14974 req/s |  500 ok | p50  7.33 ms | p99 15.45 ms | err 0
  Vanilla Node     9719 req/s |  500 ok | p50  9.38 ms | p99 40.92 ms | err 0
  OgerJS (Bun)    32533 req/s |  500 ok | p50  2.19 ms | p99  8.11 ms | err 0
  OgerJS (Node)    4579 req/s |  500 ok | p50 20.29 ms | p99 80.17 ms | err 0
  Hono (Bun)      14779 req/s |  500 ok | p50  6.31 ms | p99 15.23 ms | err 0
  Hono (Node)      2972 req/s |  500 ok | p50 36.63 ms | p99 114.57 ms | err 0
  Elysia          15758 req/s |  500 ok | p50  5.48 ms | p99 15.61 ms | err 0
  Express          3377 req/s |  500 ok | p50 27.62 ms | p99 114.47 ms | err 0
  → fastest: OgerJS (Bun) (32533 req/s)

── GET /bench/json-serialize ──
  Vanilla Bun     17797 req/s |  500 ok | p50  4.06 ms | p99 11.31 ms | err 0
  Vanilla Node    12360 req/s |  500 ok | p50  6.78 ms | p99 29.90 ms | err 0
  OgerJS (Bun)    26164 req/s |  500 ok | p50  2.23 ms | p99 12.15 ms | err 0
  OgerJS (Node)    9050 req/s |  500 ok | p50 11.47 ms | p99 28.94 ms | err 0
  Hono (Bun)      18951 req/s |  500 ok | p50  4.31 ms | p99 13.12 ms | err 0
  Hono (Node)      9080 req/s |  500 ok | p50 12.28 ms | p99 23.01 ms | err 0
  Elysia          20333 req/s |  500 ok | p50  3.17 ms | p99 16.71 ms | err 0
  Express          5875 req/s |  500 ok | p50 17.69 ms | p99 46.58 ms | err 0
  → fastest: OgerJS (Bun) (26164 req/s)

── GET /bench/item/42 ──
  Vanilla Bun     14150 req/s |  500 ok | p50  8.97 ms | p99 19.34 ms | err 0
  Vanilla Node    14422 req/s |  500 ok | p50  5.94 ms | p99 24.18 ms | err 0
  OgerJS (Bun)    24958 req/s |  500 ok | p50  2.12 ms | p99 12.68 ms | err 0
  OgerJS (Node)    8953 req/s |  500 ok | p50 11.29 ms | p99 31.38 ms | err 0
  Hono (Bun)      19171 req/s |  500 ok | p50  3.27 ms | p99 16.41 ms | err 0
  Hono (Node)     10856 req/s |  500 ok | p50  8.13 ms | p99 30.41 ms | err 0
  Elysia          18948 req/s |  500 ok | p50  3.67 ms | p99 16.69 ms | err 0
  Express          6404 req/s |  500 ok | p50 16.18 ms | p99 49.42 ms | err 0
  → fastest: OgerJS (Bun) (24958 req/s)

── GET /bench/auth ──
  Vanilla Bun     10523 req/s |  500 ok | p50  9.48 ms | p99 18.42 ms | err 0
  Vanilla Node    12767 req/s |  500 ok | p50  6.84 ms | p99 26.40 ms | err 0
  OgerJS (Bun)    21280 req/s |  500 ok | p50  2.63 ms | p99 14.91 ms | err 0
  OgerJS (Node)   12165 req/s |  500 ok | p50  6.92 ms | p99 27.87 ms | err 0
  Hono (Bun)      15998 req/s |  500 ok | p50  3.88 ms | p99 17.77 ms | err 0
  Hono (Node)      8708 req/s |  500 ok | p50 11.05 ms | p99 35.66 ms | err 0
  Elysia          17220 req/s |  500 ok | p50  3.16 ms | p99 20.52 ms | err 0
  Express          6569 req/s |  500 ok | p50 15.69 ms | p99 42.79 ms | err 0
  → fastest: OgerJS (Bun) (21280 req/s)

── GET /bench/async-io ──
  Vanilla Bun     18229 req/s |  500 ok | p50  3.15 ms | p99 17.50 ms | err 0
  Vanilla Node    10628 req/s |  500 ok | p50  7.79 ms | p99 27.73 ms | err 0
  OgerJS (Bun)    19716 req/s |  500 ok | p50  2.69 ms | p99 18.35 ms | err 0
  OgerJS (Node)   10080 req/s |  500 ok | p50  9.15 ms | p99 31.22 ms | err 0
  Hono (Bun)      15208 req/s |  500 ok | p50  4.41 ms | p99 19.04 ms | err 0
  Hono (Node)      8975 req/s |  500 ok | p50  9.53 ms | p99 35.00 ms | err 0
  Elysia          14953 req/s |  500 ok | p50  3.65 ms | p99 22.57 ms | err 0
  Express          5882 req/s |  500 ok | p50 16.56 ms | p99 52.31 ms | err 0
  → fastest: OgerJS (Bun) (19716 req/s)

── GET /bench/search (query) ──
  Vanilla Bun     17103 req/s |  500 ok | p50  3.17 ms | p99 19.11 ms | err 0
  Vanilla Node    11078 req/s |  500 ok | p50  7.38 ms | p99 34.78 ms | err 0
  OgerJS (Bun)    18810 req/s |  500 ok | p50  2.63 ms | p99 18.69 ms | err 0
  OgerJS (Node)   10519 req/s |  500 ok | p50  7.53 ms | p99 36.23 ms | err 0
  Hono (Bun)      14744 req/s |  500 ok | p50  4.22 ms | p99 20.44 ms | err 0
  Hono (Node)      9467 req/s |  500 ok | p50  8.16 ms | p99 39.41 ms | err 0
  Elysia          14960 req/s |  500 ok | p50  3.69 ms | p99 21.68 ms | err 0
  Express          6901 req/s |  500 ok | p50 14.01 ms | p99 43.61 ms | err 0
  → fastest: OgerJS (Bun) (18810 req/s)

── GET /bench/api/v1/accounts/42/balance ──
  Vanilla Bun      9552 req/s |  500 ok | p50  9.53 ms | p99 22.14 ms | err 0
  Vanilla Node    12083 req/s |  500 ok | p50  5.43 ms | p99 31.46 ms | err 0
  OgerJS (Bun)    16355 req/s |  500 ok | p50  2.62 ms | p99 23.72 ms | err 0
  OgerJS (Node)    9140 req/s |  500 ok | p50  9.55 ms | p99 28.90 ms | err 0
  Hono (Bun)      15356 req/s |  500 ok | p50  3.15 ms | p99 23.54 ms | err 0
  Hono (Node)      9612 req/s |  500 ok | p50  8.13 ms | p99 29.87 ms | err 0
  Elysia          14107 req/s |  500 ok | p50  3.17 ms | p99 25.97 ms | err 0
  Express          9217 req/s |  500 ok | p50 11.62 ms | p99 38.57 ms | err 0
  → fastest: OgerJS (Bun) (16355 req/s)

── GET /bench/middleware (chain) ──
  Vanilla Bun     12016 req/s |  500 ok | p50  9.12 ms | p99 12.38 ms | err 0
  Vanilla Node    20258 req/s |  500 ok | p50  4.22 ms | p99 18.91 ms | err 0
  OgerJS (Bun)    36495 req/s |  500 ok | p50  2.11 ms | p99  7.40 ms | err 0
  OgerJS (Node)   18018 req/s |  500 ok | p50  5.21 ms | p99 19.52 ms | err 0
  Hono (Bun)      24572 req/s |  500 ok | p50  4.19 ms | p99  9.34 ms | err 0
  Hono (Node)     12626 req/s |  500 ok | p50  7.42 ms | p99 28.69 ms | err 0
  Elysia          24535 req/s |  500 ok | p50  3.16 ms | p99 11.98 ms | err 0
  Express          8717 req/s |  500 ok | p50 10.12 ms | p99 40.35 ms | err 0
  → fastest: OgerJS (Bun) (36495 req/s)

── POST /bench/transfer ──
  Vanilla Bun     23616 req/s |  500 ok | p50  3.69 ms | p99 10.02 ms | err 0
  Vanilla Node    15613 req/s |  500 ok | p50  5.89 ms | p99 23.90 ms | err 0
  OgerJS (Bun)    32958 req/s |  500 ok | p50  2.11 ms | p99  8.23 ms | err 0
  OgerJS (Node)    8918 req/s |  500 ok | p50 10.59 ms | p99 36.02 ms | err 0
  Hono (Bun)      21646 req/s |  500 ok | p50  4.23 ms | p99 11.44 ms | err 0
  Hono (Node)      5661 req/s |  500 ok | p50 17.92 ms | p99 58.96 ms | err 0
  Elysia          13728 req/s |  500 ok | p50  5.33 ms | p99 23.02 ms | err 0
  Express          6588 req/s |  500 ok | p50 15.69 ms | p99 40.21 ms | err 0
  → fastest: OgerJS (Bun) (32958 req/s)

── POST /bench/large-json ──
  Vanilla Bun     14119 req/s |  500 ok | p50  7.39 ms | p99 13.72 ms | err 0
  Vanilla Node    10173 req/s |  500 ok | p50 10.02 ms | p99 27.07 ms | err 0
  OgerJS (Bun)    25488 req/s |  500 ok | p50  2.62 ms | p99 12.09 ms | err 0
  OgerJS (Node)    7868 req/s |  500 ok | p50 14.31 ms | p99 23.44 ms | err 0
  Hono (Bun)      13998 req/s |  500 ok | p50  6.34 ms | p99 15.22 ms | err 0
  Hono (Node)      5235 req/s |  500 ok | p50 20.42 ms | p99 58.60 ms | err 0
  Elysia          12810 req/s |  500 ok | p50  7.71 ms | p99 18.52 ms | err 0
  Express          5224 req/s |  500 ok | p50 21.29 ms | p99 51.82 ms | err 0
  → fastest: OgerJS (Bun) (25488 req/s)

── GET /bench/headers ──
  Vanilla Bun     21667 req/s |  500 ok | p50  3.19 ms | p99 13.32 ms | err 0
  Vanilla Node    18050 req/s |  500 ok | p50  4.73 ms | p99 15.69 ms | err 0
  OgerJS (Bun)    23979 req/s |  500 ok | p50  2.65 ms | p99 13.25 ms | err 0
  OgerJS (Node)   13187 req/s |  500 ok | p50  6.29 ms | p99 24.50 ms | err 0
  Hono (Bun)      19798 req/s |  500 ok | p50  3.28 ms | p99 15.15 ms | err 0
  Hono (Node)     11132 req/s |  500 ok | p50  7.97 ms | p99 31.15 ms | err 0
  Elysia          15123 req/s |  500 ok | p50  5.66 ms | p99 19.86 ms | err 0
  Express          7484 req/s |  500 ok | p50 14.09 ms | p99 37.08 ms | err 0
  → fastest: OgerJS (Bun) (23979 req/s)

Throughput matrix (req/s)

Target ok json-parse json-serialize route-param auth async-io query nested middleware validation large-json headers
OgerJS (Bun) 39,708 32,533 26,164 24,958 21,280 19,716 18,810 16,355 36,495 32,958 25,488 23,979
Vanilla Bun 32,702 14,974 17,797 14,150 10,523 18,229 17,103 9,552 12,016 23,616 14,119 21,667
Vanilla Node 12,312 9,719 12,360 14,422 12,767 10,628 11,078 12,083 20,258 15,613 10,173 18,050
OgerJS (Node) 6,908 4,579 9,050 8,953 12,165 10,080 10,519 9,140 18,018 8,918 7,868 13,187
Hono (Bun) 23,929 14,779 18,951 19,171 15,998 15,208 14,744 15,356 24,572 21,646 13,998 19,798
Hono (Node) 9,393 2,972 9,080 10,856 8,708 8,975 9,467 9,612 12,626 5,661 5,235 11,132
Elysia 28,437 15,758 20,333 18,948 17,220 14,953 14,960 14,107 24,535 13,728 12,810 15,123
Express 5,237 3,377 5,875 6,404 6,569 5,882 6,901 9,217 8,717 6,588 5,224 7,484

Methodology and env vars: docs/BENCHMARKS.md


Why OgerJS

Capability Detail
Performance Native Bun.serve routes + compile-time specialization — see benchmarks above
Zero core deps @ogerjs/core uses only Bun / Web APIs
Enterprise plugins Security, observability, audit, idempotency, rate limits — opt-in via .use()
Validation Built-in t schemas, RFC 7807 errors, Static<T> inference
Testing In-process app.inject() — no sockets
Cross-runtime Same routes on Bun and Node (@ogerjs/core fallback + @ogerjs/compat)

Quickstart

bun add ogerjs
import { Oger, t } from "ogerjs";

const app = new Oger()
  .get("/", () => "ok")
  .post(
    "/users",
    ({ body }) => body,
    { body: t.Object({ name: t.String({ minLength: 1 }) }) },
  )
  .listen(3000);

New project

bunx ogerjs my-api --yes
cd my-api && bun install && bun run start

Monorepo development

git clone <repo-url> ogerjs && cd ogerjs
bun install
bun test
bun run --cwd apps/example-basic start

Repository layout

packages/          29 @ogerjs/* workspace packages (core + plugins)
apps/              Reference apps (basic, auth, banking, bench)
benchmark/         Go HTTP comparison harness + peer targets
docs/              Guides and architecture reference
scripts/           Build and maintenance tooling

Shipped packages and roadmap gaps: docs/OVERVIEW.md · docs/ENTERPRISE_ROADMAP.md


Shipped packages (v0.2.0)

Area Packages
Core @ogerjs/core, @ogerjs/router, @ogerjs/testing, create-oger
Security cors, helmet, csrf, jwt, basic-auth, bearer, api-key, body-limit, cookie
HTTP json, html, compress, etag, static, stream, upload
Ops logger, request-id, health, audit-log, rate-limit, idempotency
Real-time sse, ws, events
Runtime compat

Full table with descriptions: docs/OVERVIEW.md#package-table


Examples

App Command Focus
Basic API bun run --cwd apps/example-basic start Routes + validation
Auth bun run --cwd apps/example-auth start JWT, API keys
Banking bun run --cwd apps/example-banking start REST + WebSocket + OpenAPI export

Banking walkthrough: docs/BANKING.md


Development

bun install          # Workspace deps
bun test packages    # Package tests
bun run typecheck    # TypeScript
bun run build        # Build all packages
cd benchmark && go run benchmark.go   # HTTP benchmark (see docs/BENCHMARKS.md)

CI runs on main, master, and v0.2 branches.


Benchmarks

Go runner: benchmark/benchmark.go — 8 runtimes × 12 banking-oriented scenarios.

bun run build
cd benchmark
go run benchmark.go

Methodology and env vars: docs/BENCHMARKS.md


Publishing (Ogulcan Studio npm)

Everything ships as one ogerjs package on the ogulcanstudio npm account (framework, plugins, CLI).

npm login                    # log in as ogulcanstudio
bun run publish:packages     # dry-run pack check
bun run publish:packages -- --yes   # publish ogerjs only

Documentation

Guide Topic
docs/GETTING_STARTED.md Install, concepts, commands
docs/OVERVIEW.md Architecture, package map
docs/CORE.md Oger class, lifecycle, context
docs/ROUTING.md Routes, groups, guards, macros
docs/VALIDATION.md t schemas
docs/PLUGINS.md Plugin authoring
docs/SECURITY.md Helmet, CORS, CSRF, rate limits
docs/AUTH.md JWT, Basic, API keys
docs/DEPLOYMENT.md Production checklist
docs/BENCHMARKS.md Benchmark reference
docs/BANKING.md Enterprise reference app

Full index: docs/README.md


Security defaults

  • Cookies: HttpOnly, SameSite=Lax, Secure in production
  • CORS with credentials: true requires explicit origin allowlist
  • JWT verification rejects wrong algorithms and expired tokens
  • Static files: path traversal blocked
  • Body parse errors: safe 4xx, no stack leaks

Details: docs/SECURITY.md


License

MIT — see LICENSE. Copyright Ogulcan Studio.