develop-typebox-fastify
TypeBox + Fastify Development
Scope
- Fastify v5+ with TypeBox schemas and
@fastify/type-provider-typebox - Type-safe route definitions with automatic request/response type inference
- OpenAPI 3.0 generation from TypeBox schemas via
@fastify/swagger - Plugin architecture, hooks lifecycle, decorators
- Testing with
inject(), database integration, auth, deployment
Does NOT cover: Frontend frameworks, GraphQL, Express migration (beyond basic guidance), non-TypeBox schema libraries as primary.
When to use
- Building or modifying Fastify REST APIs
- Defining TypeBox schemas for validation or serialization
- Configuring Fastify plugins, hooks, or decorators
- Writing tests for Fastify routes
- Setting up OpenAPI/Swagger documentation
- Integrating databases (Drizzle, Prisma) with Fastify
- Implementing authentication (JWT, OAuth, API keys) in Fastify
- Optimizing Fastify performance
When NOT to use
- General TypeScript questions without Fastify context
- Frontend development or React/Vue/Angular work
- Express.js applications (different middleware model)
- GraphQL servers (use dedicated GraphQL tools)
- Edge/serverless with strict bundle size constraints
Critical rules
- Always use TypeBoxTypeProvider:
fastify.withTypeProvider<TypeBoxTypeProvider>() - Always define response schemas: enables fast-json-stringify (2-3x faster) AND prevents data leaks
- Wrap shared plugins with fastify-plugin: exposes decorators to parent scope
- Never use reference types as decorator initial values: shared across ALL requests (security risk)
- Use
typeboxpackage (not@sinclair/typeboxwhich is deprecated — though many existing projects still use it)
Quick start
import Fastify from 'fastify'
import { Type, TypeBoxTypeProvider } from '@fastify/type-provider-typebox'
const app = Fastify({ logger: true }).withTypeProvider<TypeBoxTypeProvider>()
const UserSchema = Type.Object({
id: Type.String({ format: 'uuid' }),
name: Type.String({ minLength: 1 }),
email: Type.String({ format: 'email' }),
})
app.get('/:id', {
schema: {
params: Type.Object({ id: Type.String({ format: 'uuid' }) }),
response: { 200: UserSchema },
},
}, async (request) => {
// request.params.id is typed as string
return { id: request.params.id, name: 'User', email: 'user@example.com' }
})
Decision tree
What are you building?
New Fastify project → Read: references/project-structure/recommended-layout.md, references/fastify/server-setup.md, references/integration/type-provider-setup.md
Adding routes → Read: references/integration/route-schemas.md, references/patterns/crud-routes.md
TypeBox schemas → Read: references/typebox/schema-basics.md, then schema-composition.md or schema-advanced.md as needed
Plugin development → Read: references/fastify/plugins.md, references/fastify/decorators.md
Authentication → Read: references/fastify/authentication.md
Database integration → Read: references/database/drizzle-integration.md or references/database/prisma-integration.md
OpenAPI/Swagger → Read: references/openapi/swagger-setup.md, references/openapi/schema-to-openapi.md
Testing → Read: references/fastify/testing.md
Performance → Read: references/fastify/performance.md, references/typebox/performance-tips.md
Error handling → Read: references/fastify/error-handling.md, references/patterns/error-responses.md
WebSockets → Read: references/fastify/websockets.md
Going to production → Read: references/deployment/production-checklist.md, references/patterns/graceful-shutdown.md
Hook lifecycle (reference)
Incoming Request
→ onRequest (auth, timing, request ID)
→ preParsing (transform request stream)
→ preValidation (normalize data before schema validation)
→ preHandler (authorization, load related data)
→ Handler (business logic)
→ preSerialization (transform response object)
→ onSend (modify serialized payload, add headers)
→ onResponse (metrics, logging — cannot modify response)
→ onError (error logging, cleanup — on error only)
Critical gotchas (from research)
- Transform types do NOT work with Ajv — TypeBox Transform (encode/decode) schemas are incompatible with Fastify's Ajv validator. Use
TypeBoxValidatorCompileror applyValue.Decode/Value.Encodemanually. - Value.Parse pipeline — The recommended safe parsing order is: Clone → Default → Convert → Clean → Decode. Use this for environment variables and untrusted input.
- Response schemas strip extra properties — This is a security feature of fast-json-stringify, not a bug. It prevents leaking database fields like passwords.
- Registration order is critical — Register shared schemas before routes, infrastructure plugins before feature plugins, CORS/helmet before everything else.
- TypeBox outputs standard JSON Schema (Draft 7) — This is why it integrates seamlessly with Fastify, unlike Zod which requires adapters.
Red flags to watch for
| Red flag | Why it matters | Fix |
|---|---|---|
No withTypeProvider<TypeBoxTypeProvider>() |
No compile-time type safety | Add to server setup |
| Missing response schemas | Loses 2-3x serialization perf, risks data leaks | Define for all status codes |
Shared plugin without fastify-plugin |
Decorators invisible to other plugins | Wrap with fp() |
Reference type in decorateRequest() |
Shared mutable state across requests | Use null, set in hook |
| No error handler configured | Stack traces exposed to clients | Add setErrorHandler |
Missing await server.ready() in tests |
Plugins may not be loaded | Always await before inject() |
| Mixing async/await with done callback | Double-completion bugs | Pick one pattern per hook |
| Rate limiting without Redis backend | Bypassed in distributed deployments | Use Redis store |
Reference routing
Core references
| File | Read when |
|---|---|
references/core/quick-reference.md |
Need a cheat sheet for TypeBox + Fastify patterns |
references/core/package-ecosystem.md |
Setting up dependencies, choosing packages |
TypeBox schemas
| File | Read when |
|---|---|
references/typebox/schema-basics.md |
Defining basic TypeBox schemas |
references/typebox/schema-composition.md |
Composing, extending, picking, omitting schemas |
references/typebox/schema-advanced.md |
Recursive types, transforms, discriminated unions |
references/typebox/schema-formats.md |
Custom formats, format validators |
references/typebox/value-operations.md |
Value.Check, Value.Cast, Value.Clean, etc. |
references/typebox/value-decode-encode.md |
Type transformations (wire → domain) |
references/typebox/type-compiler.md |
High-performance compiled validation |
references/typebox/typemap-standard-schema.md |
Standard Schema support via TypeMap |
references/typebox/json-schema-mapping.md |
TypeBox ↔ JSON Schema, $id/$ref |
references/typebox/schema-patterns.md |
Pagination, error, CRUD schema patterns |
references/typebox/nullable-optional.md |
Optional vs nullable patterns |
references/typebox/type-inference.md |
Static type extraction |
references/typebox/schema-organization.md |
File organization for schemas |
references/typebox/migration-guide.md |
Migrating from @sinclair/typebox, Zod |
references/typebox/validation-patterns.md |
Custom and cross-field validation |
references/typebox/coercion-defaults.md |
Type coercion, default values |
references/typebox/enum-patterns.md |
Enums, literals, discriminated unions |
references/typebox/date-handling.md |
Date schemas and transforms |
references/typebox/common-mistakes.md |
Top TypeBox mistakes to avoid |
references/typebox/performance-tips.md |
Compilation, caching, benchmarks |
Fastify core
| File | Read when |
|---|---|
references/fastify/server-setup.md |
Creating Fastify instance |
references/fastify/routes.md |
Defining routes, params, query, body |
references/fastify/plugins.md |
Plugin system and encapsulation |
references/fastify/hooks-lifecycle.md |
Request lifecycle hooks |
references/fastify/error-handling.md |
Error handlers and custom errors |
references/fastify/decorators.md |
Extending Fastify/Request/Reply |
references/fastify/serialization.md |
Response serialization |
references/fastify/authentication.md |
JWT, OAuth, API keys, sessions |
references/fastify/testing.md |
inject() testing patterns |
references/fastify/performance.md |
Performance optimization |
references/fastify/logging.md |
Pino logging |
references/fastify/cors-security.md |
CORS, helmet, CSRF, rate limiting |
references/fastify/websockets.md |
WebSocket support |
references/fastify/database.md |
Database adapters |
references/fastify/file-uploads.md |
Multipart uploads |
references/fastify/configuration.md |
@fastify/env, config validation |
references/fastify/deployment.md |
Graceful shutdown, Docker, cluster |
references/fastify/content-type.md |
Content type parsing |
references/fastify/http-proxy.md |
HTTP proxy patterns |
references/fastify/typescript-setup.md |
TypeScript configuration |
Integration (TypeBox + Fastify together)
| File | Read when |
|---|---|
references/integration/type-provider-setup.md |
Setting up type provider |
references/integration/route-schemas.md |
TypeBox schemas in route definitions |
references/integration/schema-registration.md |
addSchema() with $id/$ref |
references/integration/request-type-inference.md |
How request types are inferred |
references/integration/response-serialization.md |
TypeBox + fast-json-stringify |
OpenAPI
| File | Read when |
|---|---|
references/openapi/swagger-setup.md |
Setting up Swagger/OpenAPI |
references/openapi/schema-to-openapi.md |
TypeBox → OpenAPI mapping |
references/openapi/openapi-codegen.md |
Client SDK generation |
Database
| File | Read when |
|---|---|
references/database/drizzle-integration.md |
Drizzle ORM + Fastify |
references/database/prisma-integration.md |
Prisma + Fastify |
references/database/repository-pattern.md |
Repository abstraction |
references/database/migration-patterns.md |
Schema migrations |
Middleware
| File | Read when |
|---|---|
references/middleware/rate-limiting.md |
@fastify/rate-limit |
references/middleware/cors-setup.md |
@fastify/cors |
references/middleware/compression.md |
@fastify/compress |
references/middleware/helmet-security.md |
@fastify/helmet |
Patterns
| File | Read when |
|---|---|
references/patterns/crud-routes.md |
Full CRUD with TypeBox |
references/patterns/pagination.md |
Cursor/offset pagination |
references/patterns/error-responses.md |
Standardized errors |
references/patterns/request-context.md |
Correlation IDs, context |
references/patterns/graceful-shutdown.md |
Shutdown handling |
references/patterns/health-checks.md |
Liveness/readiness probes |
references/patterns/api-versioning.md |
API version strategies |
references/patterns/batch-operations.md |
Bulk operations |
Project structure
| File | Read when |
|---|---|
references/project-structure/recommended-layout.md |
Directory organization |
references/project-structure/module-patterns.md |
ESM, imports, barrel files |
references/project-structure/environment-config.md |
Env config with TypeBox |
references/project-structure/docker-setup.md |
Docker for Fastify |
Deployment
| File | Read when |
|---|---|
references/deployment/production-checklist.md |
Pre-production audit |
references/deployment/monitoring-setup.md |
Logging, metrics, tracing |
Guardrails
- Always import Type from
@fastify/type-provider-typeboxortypebox(not@sinclair/typeboxin new projects) - Always define response schemas for every route in production
- Never skip
fastify-pluginwrapping for plugins that expose decorators - Never use
express.Router()patterns — use Fastify's plugin system instead - Never configure rate limiting with in-memory store for production (use Redis)
- Test with
inject()— never start an actual HTTP server in tests
More from yigitkonur/skills-by-yigitkonur
run-research
>-
38run-agent-browser
Use skill if you are driving the agent-browser CLI for browser navigation, DOM-grounded interaction, session/tab management, screenshots, data extraction, or repeatable web app workflows.
34build-skills
Use skill if you are creating or substantially revising a Claude skill and need workspace-first evidence, remote comparison, and repo-fit synthesis before writing SKILL.md.
32publish-npm-package
Use skill if you are automating npm publishing via GitHub Actions and need auth, versioning, provenance, or workflow-template choices.
31build-mcp-use-server
Use skill if you are building or extending TypeScript MCP servers with the mcp-use library — tools, Zod schemas, resources, prompts, transports, OAuth, sessions, testing, and deployment.
30init-agent-config
Use skill if you are creating, auditing, or migrating AGENTS.md-first repo instructions, REVIEW.md standards, folder-scoped guidance, and companion agent entrypoints for multi-agent coding workflows.
30