npm package: @mila.solutions/express
Description: Fast, unopinionated, minimalist web framework (Mila fork with fast-json-stringify)
Author: TJ Holowaychuk
Latest version: 5.2.1-mila.0

# @mila.solutions/express

Performance-focused fork of [Express](https://expressjs.com/) 5.2.1 with integrated [`fast-json-stringify`](https://github.com/fastify/fast-json-stringify) and internal optimizations.

**100% compatible with Express 5** — all 1,342 tests pass. Drop-in replacement.

## What's different

| Feature | Express 5.2.1 | @mila.solutions/express |
|---|---|---|
| JSON serialization | `JSON.stringify` | `fast-json-stringify` (pre-compiled via JSON Schema) |
| Route-level schemas | No | Yes — per-route, per-status-code |
| `res.locals` | Allocated every request | Lazy — only allocated on first access |
| Error handler binding | New closure per request | Pre-bound at init |
| `req.fresh` check | Always runs | Short-circuited for non-conditional requests |
| ETag on JSON | Always | Configurable via `json etag` setting |

### Benchmark results (10K requests, 20 concurrent)

```
Express 5.2.1 (original)   ███████████████████████████████████  6,647 rps
@mila (no schema)           ████████████████████████████████████████  7,577 rps  (+14%)
@mila (schema)              ███████████████████████████████████████   7,377 rps  (+11%)
@mila (schema + no etag)    ███████████████████████████████████████   7,414 rps  (+12%)
```

**+10-19% faster** depending on configuration. Improvement comes from reduced allocations per request and pre-compiled JSON serialization.

## Installation

```bash
npm install @mila.solutions/express
```

## Quick start

Works exactly like Express:

```js
const express = require('@mila.solutions/express')
const app = express()

app.get('/users', (req, res) => {
  res.json({ id: 1, name: 'John' })
})

app.listen(3000)
```

## Schema-based JSON serialization

Define a JSON Schema on your route to enable `fast-json-stringify`. The schema is compiled once at startup and reused for every request.

### Basic usage

```js
const express = require('@mila.solutions/express')
const app = express()

app.get('/user', {
  schema: {
    response: {
      type: 'object',
      properties: {
        id: { type: 'integer' },
        name: { type: 'string' },
        email: { type: 'string' }
      }
    }
  }
}, (req, res) => {
  res.json({ id: 1, name: 'John', email: 'john@example.com' })
})
```

### Per-status-code schemas

```js
app.post('/users', {
  schema: {
    response: {
      201: {
        type: 'object',
        properties: {
          id: { type: 'integer' },
          name: { type: 'string' }
        }
      },
      400: {
        type: 'object',
        properties: {
          error: { type: 'string' },
          details: { type: 'array', items: { type: 'string' } }
        }
      }
    }
  }
}, (req, res) => {
  // Schema for 201 is used automatically
  res.status(201).json({ id: 1, name: 'John' })
})
```

### Generic status code groups

Use `2xx`, `3xx`, `4xx`, `5xx` to match any status code in a range:

```js
app.get('/data', {
  schema: {
    response: {
      '2xx': {
        type: 'object',
        properties: {
          data: { type: 'string' }
        }
      },
      '4xx': {
        type: 'object',
        properties: {
          error: { type: 'string' }
        }
      }
    }
  }
}, handler)
```

### Resolution order

When `res.json()` is called, the serializer is resolved in this order:

1. **Exact match** — status code matches exactly (e.g. `200`)
2. **Generic match** — status code group matches (e.g. `2xx`)
3. **Default** — a plain schema object (no status code keys)
4. **Fallback** — standard `JSON.stringify`

### App-level schemas

Set a default schema for all routes:

```js
app.set('json schema', {
  type: 'object',
  properties: {
    data: {},
    meta: {}
  }
})
```

Route-level schemas always take priority over app-level.

## Additional settings

### `json etag`

Disable ETag generation for JSON responses:

```js
app.set('json etag', false)
```

This skips the `etag` computation on every `res.json()` call, which saves CPU when your clients don't use conditional requests (`If-None-Match`).

## How it works

### fast-json-stringify

Standard `JSON.stringify` inspects every value at runtime to determine its type. `fast-json-stringify` uses JSON Schema to generate a specialized serializer function at startup that knows the exact shape of your data. This avoids type checking per-value and produces strings ~1.5x faster for typical API payloads.

Schemas are compiled once and cached via `WeakMap`, so the same schema object always returns the same pre-compiled serializer.

### Internal optimizations

These apply to all requests, even without schemas:

- **Pre-bound error handler** — `logerror` is bound once at `app.init()` instead of creating a new closure per request in `app.handle()`
- **Lazy `res.locals`** — Uses a self-replacing getter. The object is only created when your code actually accesses `res.locals`, saving an allocation on routes that don't use it
- **`req.fresh` short-circuit** — Skips the full freshness check when the request has no `If-None-Match` or `If-Modified-Since` headers
- **Buffer fast-path in `_sendJson()`** — Pre-computes Content-Length from the buffer byte length instead of going through the full `res.send()` path

## Compatibility

- Based on Express **5.2.1**
- Requires Node.js **>= 18**
- All **1,342** Express tests pass
- Drop-in replacement — no API changes for existing code
- Schemas are opt-in; without them, it behaves identically to Express

## Running tests

```bash
npm install
npm test
```

## Running benchmarks

```bash
# A/B comparison (Express original vs @mila)
node benchmarks/compare.js --requests 10000

# Scaling test
node benchmarks/scale.js
```

## License

[MIT](LICENSE)

Based on [Express](https://github.com/expressjs/express) by the Express.js community.