Fastify API Design
Overview
Keep the Fastify app small, testable, and schema-first. Build on the exported
createApp() factory so tests can inject the server without binding a fixed port.
Process
- Register routes on the app returned by
createApp()insrc/app.js. - Define JSON schemas for request/response when the payload shape matters.
- Return correct status codes (200/201 success, 400 client error, 404 not found).
- Use Fastify's built-in error handler; do not leak stack traces in production.
- Add a
test/case that starts the app on port0and asserts responses.
Plugin Order
- Core plugins (cors, sensible) if needed
- Route registration
- Global error handler
Testing
- Integration tests:
app.listen({ port: 0 }),fetchagainst127.0.0.1. - Extract pure helpers for unit tests when logic grows beyond route handlers.
- Run
npm testbefore every commit.
Guidelines
- Prefer route-level schemas over ad-hoc validation in handlers.
- Keep handlers thin; move business logic to testable functions.
- Read secrets from environment variables at startup, not from requests.
- Prefer explicit routes over catch-all handlers.
Anti-patterns
- Bypassing Fastify validation with unvalidated
request.bodyaccess. - Starting the server inside
createApp()— keep listen inserver.jsonly. - Global mutable state shared across requests.


