fastify-best-practise logo

fastify-best-practise

fastify best practise

thecodepace/fastify-skills142installs9stars

SKILL.md

Full skill instructions

Fastify Best Practices

A curated set of rules and patterns for building production-ready Fastify applications. Each rule includes incorrect and correct examples with explanations.

How It Works

  1. The agent identifies that the user is working with Fastify or asking about Fastify patterns
  2. The relevant rule file is loaded based on the topic (routes, validation, encapsulation, etc.)
  3. The agent applies the best practices from the rule when generating or reviewing code

Rules

The rules are organized by topic in the rules/ directory. Each rule follows a consistent format with impact rating, incorrect/correct examples, and references to official docs.

RuleFileImpactDescription
Configurationconfiguration.mdHIGHEnvironment config, logger setup, security options, and graceful shutdown
Create Servercreate-server.mdLOW-MEDIUMUse a buildServer() factory function for reusable, testable server setup
Create Plugincreate-plugin.mdLOW-MEDIUMEncapsulate reusable functionality in plugins with fastify-plugin
Autoloadautoload.mdHIGHAutomatically load plugins and routes from the filesystem with @fastify/autoload
Route Best Practicesroute-best-practices.mdMEDIUMOrganize routes with plugins/prefixes, use async handlers, full route options
Schema Validation (Zod)schema-validation-zod.mdHIGHType-safe validation with Zod + fastify-type-provider-zod
Encapsulationencapsulation.mdHIGHProper scope isolation and when to use fastify-plugin
Error Handlingerror-handling.mdHIGHCustom error handlers, @fastify/error, 404 handling, structured responses
Hooks & Lifecyclehooks-lifecycle.mdMEDIUMAll request/reply and application hooks: onRequest, preParsing, preValidation, preHandler, preSerialization, onError, onSend, onResponse, onReady, onClose
Logginglogging.mdHIGHBuilt-in Pino logger, request correlation, redaction, child loggers
Authenticationauthentication.mdHIGHJWT auth with @fastify/jwt, multi-strategy with @fastify/auth
Testingtesting.mdHIGHTest with inject(), buildServer pattern, vitest/node:test
TypeScripttypescript-integration.mdMEDIUMType providers, module augmentation, typed decorators
Decoratorsdecorators.mdMEDIUMExtend the Fastify instance, request, and reply with decorate / decorateRequest / decorateReply
Content Type Parsercontent-type-parser.mdHIGHCustom content type parsers, body limits, multipart uploads, catch-all and regex matching
Database Integrationdatabase-integration.mdHIGHRegister a pg pool as a Fastify plugin; use @nearform/sql for safe queries
Database Migrationsdatabase-migrations.mdHIGHRun Postgrator SQL migrations at startup; never modify applied files
Test Containerstest-containers.mdHIGHSpin up real Postgres containers with Testcontainers for integration tests
Clean Architectureclean-architecture.mdHIGHPure service-layer functions + thin route handlers; explicit dependency injection
Unit Testingunit-testing.mdHIGHUnit-test service functions in isolation with mock database stubs
Performanceperformance.mdHIGHSchema pre-compilation, serialization, load shedding, streaming, benchmarking

Usage

When generating Fastify code, read the relevant rule file(s) for the topic and apply the patterns shown. For a new project, all rules are relevant. For specific tasks, load only what's needed:

  • New project setup: create-server.md, configuration.md, autoload.md, encapsulation.md, typescript-integration.md
  • Adding routes: route-best-practices.md, autoload.md, schema-validation-zod.md
  • Adding shared services: create-plugin.md, autoload.md, encapsulation.md
  • Configuration/environment: configuration.md
  • Error handling: error-handling.md
  • Auth/middleware: authentication.md, hooks-lifecycle.md, encapsulation.md
  • Custom decorators: decorators.md, typescript-integration.md
  • Logging: logging.md
  • Body parsing/file uploads: content-type-parser.md
  • Performance tuning: performance.md, schema-validation-zod.md
  • Writing tests: testing.md, create-server.md
  • Database setup: database-integration.md, database-migrations.md
  • Integration tests with a real DB: test-containers.md, testing.md
  • Clean separation of concerns: clean-architecture.md, unit-testing.md
  • Unit testing business logic: unit-testing.md, clean-architecture.md

Recommended Project Structure

Using @fastify/autoload, plugins and routes are loaded automatically from their directories:

src/
  plugins/          # Autoloaded — shared plugins (use fastify-plugin)
    db.ts           # Database client (pg/Drizzle/Prisma) + lifecycle
    auth.ts
    config.ts
  routes/           # Autoloaded — encapsulated route plugins (NO fastify-plugin)
    _hooks.ts       # Global route hooks (with autoHooks: true)
    users/
      index.ts      # → /users  (thin handler — calls services/users.ts)
      _hooks.ts     # Hooks for /users scope only
      schema.ts     # Zod schemas
    posts/
      index.ts      # → /posts
      schema.ts
  services/         # Pure business logic — no Fastify imports, injectable deps
    users.ts
    posts.ts
  db/
    migrate.ts      # runMigrations() helper (uses Postgrator)
  server.ts         # buildServer() with autoload registration
  app.ts            # Entry point — runMigrations() then server.listen()
migrations/         # Raw SQL files (committed to git): 001.do.*.sql, 001.undo.*.sql
test/
  services/
    users.test.ts   # Unit tests — pure functions, mock db
  routes/
    users.test.ts   # Integration tests — inject() + real schema
  helpers/
    server.ts       # createTestServer() / createIntegrationServer()
    db.ts           # startTestDatabase() via Testcontainers

Present Results to User

When applying these best practices, mention which rule(s) you followed:

Applied Fastify best practices:

  • Route organization: Routes grouped by resource with prefixes
  • Zod validation: Request/response schemas with type inference
  • Encapsulation: Shared plugins use fastify-plugin, routes stay scoped
  • Error handling: Custom error handler with @fastify/error
  • Performance: Response schemas, shared schema references, load shedding, streaming, and benchmark guidance
  • Database: Client registered as a plugin with fastify-plugin for shared pool and lifecycle management
  • Migrations: Applied via Postgrator (runMigrations()) before server starts; raw SQL files tracked in git
  • Clean architecture: Business logic in pure service functions; route handlers stay thin
  • Unit tests: Service functions tested in isolation with mock db stubs
  • Integration tests: Real Postgres container via Testcontainers

Reference