Architecture

How brakit captures, analyzes, and displays everything your API does.

The Big Idea

When you run npx brakit install, brakit adds a one-line instrumentation file to your project. When your dev server starts, that import hooks into http.Server.prototype.emit to capture every HTTP request and response. No proxy, no second process. Brakit runs inside your existing server.

┌──────────────────────────────────────────────────────────┐
│                    Your Dev Server                        │
│                                                          │
│   ┌───────────────┐    ┌──────────────────────────────┐  │
│   │  Your App     │    │  Brakit (in-process)         │  │
│   │  Code         │    │                              │  │
│   │               │    │  ├─ HTTP capture             │  │
│   │  routes       │    │  │  (http.Server.emit hook)  │  │
│   │  controllers  │    │  ├─ DB adapters              │  │
│   │  models       │    │  │  (pg, mysql2, prisma)     │  │
│   │               │    │  ├─ Fetch hook               │  │
│   │               │    │  │  (diagnostics_channel)    │  │
│   │               │    │  ├─ Console & Error hooks    │  │
│   │               │    │  ├─ Analysis engine          │  │
│   │               │    │  └─ Dashboard (/__brakit)    │  │
│   └───────────────┘    └──────────────────────────────┘  │
│                                                          │
│                    localhost:3000                         │
└──────────────────────────────────────────────────────────┘

That's the entire system. One process, one port, and a dashboard that shows everything.

Why In-Process?

Running inside the same process means brakit can see everything without any external setup:

  • From the outside (HTTP hook): Every HTTP request and response: method, URL, headers, body, status code, timing. Captured by patching http.Server.prototype.emit.
  • From the inside (instrumentation hooks): Database queries, outgoing fetch calls, console output, unhandled errors. Captured via library-level patches and Node.js diagnostics_channel.

Request Correlation

Every incoming request is wrapped in an AsyncLocalStorage context with a unique UUID. All hooks (database adapters, fetch, console, errors) read this context to tag their events with the originating request ID.

So when the dashboard shows "this request fired 4 database queries," it knows exactly which queries belong to which request.

The Hooks

When import 'brakit' runs, the following hooks are registered:

  • HTTP capture: Patches http.Server.prototype.emit to intercept every 'request' event. Wraps each request in an AsyncLocalStorage context and captures method, URL, headers, body, status, and timing.
  • Fetch hook: Captures every outgoing fetch() call via Node.js diagnostics_channel.
  • Console hook: Wraps console.log, console.error, etc. Records every message.
  • Error hook: Listens for uncaught exceptions and unhandled promise rejections.

On top of these core hooks, the adapter system auto-detects installed database libraries and patches them to capture queries.

The Dashboard

Brakit intercepts requests to /__brakit/* before they reach your app. These routes serve the dashboard HTML, REST APIs for each data store, and an SSE stream for real-time updates. Everything else passes through to your application unchanged.

Production Safety

Brakit has multiple layers to ensure it never runs in production:

  • Activation gate: Checks NODE_ENV and 15+ cloud/CI environment variables (Vercel, AWS, Railway, Heroku, etc.). If any production signal is detected, brakit silently disables itself.
  • Dev dependency: Installed as a devDependency, so it's pruned during production builds.
  • Safe wrapping: Every hook is wrapped in try/catch. If brakit throws, your app continues normally.
  • Circuit breaker: After 10 errors, brakit automatically disables all instrumentation for the rest of the session.
  • Localhost only: The dashboard only responds to requests from localhost.
  • Manual override: Set BRAKIT_DISABLE=1 to force-disable brakit in any environment.
Brakit is designed to be invisible in production. Even if the instrumentation file is accidentally left in, the activation gate and devDependency pruning prevent it from running.

The Analysis Engine

The analysis engine subscribes to all in-memory stores and recomputes whenever new data arrives. It produces two kinds of results:

  • Security findings: 8 rules that scan every response for leaked secrets, stack traces, insecure cookies, and more. See Security Rules.
  • Performance insights: N+1 detection, duplicate API calls, slow endpoints, query-heavy routes, error hotspots, and more.

Both systems are plugin-based. Adding a new security rule or insight pattern is one file implementing one interface.

Data Storage

All captured data lives in bounded in-memory arrays. No external database. Each store holds up to 1,000 entries and evicts the oldest when full:

StoreContains
RequestStoreHTTP requests and responses
QueryStoreDatabase queries from adapters
FetchStoreOutgoing fetch calls
LogStoreConsole output
ErrorStoreUncaught exceptions and unhandled rejections
MetricsStorePer-endpoint statistics, persisted to .brakit/metrics.json

Every store supports pub/sub. When a new entry is added, all subscribers are notified. This is how the SSE stream and analysis engine stay in sync without polling.