Configuration
The ServerConfig object is passed as the second argument to createServer (for Node/Bun) or as part of ServerlessConfig (for Vercel/Netlify).
Top-level options
Section titled “Top-level options”| Option | Type | Default | Description |
|---|---|---|---|
port | number | 3000 | Port to listen on |
platform | 'node' | 'bun' | 'vercel' | 'netlify' | 'cloudflare' | 'node' | Target platform |
isDev | boolean | NODE_ENV === 'development' | Enables dev mode (verbose errors, monitoring) |
timeout | number | 30000 | Request timeout in milliseconds |
maxBodySize | number | 10485760 (10 MB) | Max request body in bytes; larger requests get 413. Applies to all adapters. |
defaultHeaders | Record<string, string> | — | Headers added to every response (node, bun, cloudflare) |
httpsOptions
Section titled “httpsOptions”TLS configuration for HTTPS (Node.js only).
httpsOptions: { cert: readFileSync('./certs/cert.pem'), key: readFileSync('./certs/key.pem'),}See the CORS page for all options.
cors: { origin: 'https://myapp.com', credentials: true, maxAge: 86400,}middleware
Section titled “middleware”Global middleware applied to every request.
middleware: { beforeRequest: async (req, res) => { /* ... */ }, afterRequest: async (req, res) => { /* ... */ }, onError: async (req, res, ctx) => { /* ... */ },}Each property accepts a single handler or an array of handlers.
Server lifecycle hooks.
hooks: { onNotFound: async (req, res) => { res.status(404).json({ error: 'Not found' }) }, onShutdown: async () => { await db.end() },}| Hook | When it runs |
|---|---|
onNotFound | No route matched the request |
onShutdown | SIGINT, SIGTERM, or SIGHUP received |
cluster
Section titled “cluster”Multi-process clustering (Node.js and Bun).
cluster: { enabled: false, // default workers: undefined, // defaults to os.cpus().length}monitoring
Section titled “monitoring”Development performance monitoring (Node.js only, requires isDev: true).
monitoring: { enabled: false, // default sampleInterval: 5000, // ms between samples reportInterval: 60000, // ms between console reports thresholds: { cpu: 80, // % — triggers alert memory: 512, // MB responseTime: 500, // ms errorRate: 5, // % },}When enabled, a /health endpoint returns live metrics as JSON.
routes
Section titled “routes”Pre-compiled routes manifest (serverless platforms only). Generated by lacis build.
import { routes, middlewares } from './routes/_manifest.js'
// Passed to vercelAdapter or netlifyAdaptervercelAdapter.createHandler({ routes, middlewares })openapi
Section titled “openapi”OpenAPI spec generation.
openapi: { path: '/openapi.json', info: { title: 'My API', version: '1.0.0', description: 'Optional description.', }, servers: [ { url: 'https://api.example.com', description: 'production' }, ],}Runtime behavior by platform
Section titled “Runtime behavior by platform”A few behaviors differ by runtime, by necessity. These are stable and intentional.
| Behavior | node | bun | cloudflare | vercel | netlify |
|---|---|---|---|---|---|
Streaming (res.stream / SSE) | live | live | live | buffered | buffered |
initSSE() before first await | not required | required | required | not required | not required |
defaultHeaders | ✓ | ✓ | ✓ | — | — |
req.platform | {} | {} | { env, ctx, cf } | {} | {} |
405 Allow header | ✓ | ✓ | ✓ | ✓ | ✓ |
Node cluster mode distributes requests via the OS (round-robin SCHED_RR); Lacis does no application-level load balancing.