Skip to content
express-to-fastify-migration logo

Express to Fastify Migration

express-to-fastify-migration

Migrate Express.js REST APIs to Fastify with automated testing, performance benchmarking, and schema generation. Use when migrating Express applications to Fastify, modernizing Node.js APIs, improving API performance, or when users mention Express to Fastify migration, Fastify conversion, API mod...

SKILL.md

Full skill instructions

Express to Fastify Migration

MANDATORY WORKFLOW

You MUST complete each phase IN ORDER. Do NOT proceed to the next phase until the current phase is complete. Report your progress after each phase.


Phase 1: Assessment & Baseline Capture (REQUIRED before any code changes)

Before writing ANY code, you MUST:

1.1 Document the existing codebase:

  1. Routes: List ALL Express routes in the codebase (method, path, handler)
  2. Middleware: List ALL middleware (global and route-specific)
  3. Dependencies: List ALL Express-related dependencies from package.json
  4. Custom patterns: Note any authentication, error handling, or custom middleware

1.2 Capture Express API responses (CRITICAL):

You MUST save the actual API responses BEFORE making any code changes. These are required to verify output compatibility in Phase 6.

For EACH endpoint identified in 1.1, capture the response:

# Example: save responses to files for later comparison
curl -s "http://localhost:PORT/​endpoint" | jq . > /​tmp/​express_endpoint.json
curl -s "http://localhost:PORT/​endpoint?query=test" | jq . > /​tmp/​express_endpoint_query.json

Save responses for:

  • Success cases (200 responses)
  • Error cases (400/​404 responses)
  • Response headers (especially Cache-Control, Content-Type)

1.3 Capture Express baseline performance (CRITICAL):

You MUST benchmark the Express server BEFORE making any code changes. This baseline is required for performance comparison in Phase 6.

  1. Install autocannon: npm install autocannon --save-dev
  2. Start the Express server
  3. Run benchmarks on key endpoints and record the results:
npx autocannon -c 10 -d 10 http://localhost:PORT/​endpoint
  1. Save these metrics - you will compare against them in Phase 6:
    • Requests/​second
    • Average latency
    • Throughput (bytes/​sec)

STOP: You MUST report your assessment findings, saved API responses, AND Express baseline metrics before proceeding to Phase 2.


Phase 2: Dependencies

Install Fastify and equivalents for EACH Express plugin identified in Phase 1.

REQUIRED plugins (ALWAYS install these):

  • fastify - Core framework
  • @fastify/​helmet - Security headers (REQUIRED)
  • @fastify/​rate-limit - Rate limiting (REQUIRED)

Conditional plugins (install if Express equivalent was used):

  • compression → @fastify/​compress
  • cors → @fastify/​cors
  • cookie-parser → @fastify/​cookie
  • express-session → @fastify/​session
  • body-parser → Built-in (no plugin needed)

IMPORTANT: Do NOT uninstall Express yet!

Keep Express installed until Phase 6 (Performance Verification) is complete. This allows you to run both servers simultaneously for benchmarking comparison.

STOP: Confirm all Fastify dependencies installed before Phase 3. Express stays installed for now.


Phase 3: Route Migration

For EACH route identified in Phase 1, you MUST:

  1. Convert syntax using these patterns:

    • app.get() → fastify.get()
    • req/​res → request/​reply
    • res.json(data) → return data
    • res.status(code).json(data) → reply.code(code); return data
    • res.header() → reply.header()
  2. Add JSON schema for validation (REQUIRED for every route):

fastify.get('/​example', {
  schema: {
    querystring: {
      type: 'object',
      properties: {
        query: { type: 'string' }
      }
    },
    response: {
      200: {
        type: 'object',
        properties: {
          data: { type: 'array' }
        }
      }
    }
  }
}, async (request, reply) => {
  // handler
});
  1. Convert middleware to hooks:
    • Global middleware → fastify.addHook('onRequest', ...)
    • Route middleware → preHandler option
    • Error middleware → fastify.setErrorHandler(...)

Consult references/​migration_patterns.md for detailed examples.

STOP: Confirm all routes migrated with schemas before Phase 4.


Phase 4: Server Setup

Update the server entry point:

  1. Configure Fastify with logging:
const app = Fastify({ logger: true });
  1. Register REQUIRED security plugins:
app.register(helmet);
app.register(rateLimit, { max: 100, timeWindow: '1 minute' });
  1. Register error handler:
app.setErrorHandler((error, request, reply) => {
  request.log.error(error);
  reply.status(error.statusCode || 500).send({ error: error.message });
});
  1. Update server startup to use Fastify's listen():
await app.listen({ port: PORT, host: '0.0.0.0' });

STOP: Confirm server setup complete before Phase 5.


Phase 5: Validation (REQUIRED before completion)

You MUST complete ALL of these checks:

Build & Test

  • Run npm run build - MUST succeed with no errors
  • Run npm test - ALL tests MUST pass
  • Run linting - MUST pass or only have unrelated warnings

Code Quality Verification

  • ALL routes have JSON schemas
  • Security plugins registered (@fastify/​helmet, @fastify/​rate-limit)
  • Error handler configured
  • Logging enabled

Documentation

  • Update package.json description (Express → Fastify)
  • Update README.md to reference Fastify
  • Update any API documentation

Do NOT report completion until ALL boxes are checked.


Phase 6: Output & Performance Comparison (REQUIRED)

6.1 Verify API output compatibility (CRITICAL):

Compare Fastify responses against the Express responses saved in Phase 1.

For EACH endpoint, verify the output matches:

# Capture Fastify response
curl -s "http://localhost:PORT/​endpoint" | jq . > /​tmp/​fastify_endpoint.json

# Compare against Express baseline from Phase 1
diff /​tmp/​express_endpoint.json /​tmp/​fastify_endpoint.json

You MUST verify:

  • Response body structure is identical
  • Status codes match for success and error cases
  • Response headers match (Content-Type, Cache-Control, etc.)

If outputs differ, fix the Fastify implementation before proceeding.

6.2 Compare performance against baseline:

  1. Start the Fastify server on the same port used for baseline
  2. Run the same benchmarks used in Phase 1:
npx autocannon -c 10 -d 10 http://localhost:PORT/​endpoint
  1. Compare results against the Express baseline from Phase 1:
MetricExpress (Phase 1)Fastify (Phase 6)Improvement
Req/​secbaselinenewX%
LatencybaselinenewX%
ThroughputbaselinenewX%

Expected improvements:

  • 2-3x more requests/​second
  • 30-40% lower latency

STOP: You MUST report BOTH the output compatibility verification AND the performance comparison table before Phase 7.


Phase 7: Cleanup (REQUIRED - Final Step)

After performance verification is complete:

  1. Uninstall Express dependencies:
npm uninstall express morgan compression cors cookie-parser express-session
npm uninstall @types/​express @types/​morgan @types/​compression @types/​cors
  1. Remove any Express-specific code that was kept for benchmarking

  2. Final verification:

  • Run npm run build - MUST succeed
  • Run npm test - ALL tests MUST pass
  • Confirm no Express imports remain in production code

Do NOT report migration complete until Express is fully removed.


Reference Documentation

Consult these files for detailed patterns:

  • references/​migration_patterns.md - Route and middleware conversion examples
  • references/​plugin_ecosystem.md - Complete Express → Fastify plugin mapping
  • scripts/​benchmark.js - Performance benchmarking
  • scripts/​schema_generator.js - Generate JSON schemas from examples
  • assets/​server_template.js - Production-ready Fastify boilerplate

Common Pitfalls to AVOID

  1. Skipping Phase 1 baselines: You MUST capture Express API responses AND performance metrics BEFORE any code changes - you cannot verify compatibility or compare performance without baselines
  2. Forgetting schemas: EVERY route MUST have a JSON schema
  3. Skipping security plugins: helmet and rate-limit are REQUIRED
  4. Using callbacks: Fastify expects async/​await, not callbacks
  5. Manual JSON serialization: Use return, not reply.send(JSON.stringify())
  6. Forgetting to close app in tests: Add afterAll(() => app.close())
  7. Not verifying output compatibility: API responses must be identical after migration - always diff the before/​after outputs

TypeScript Patterns

For typed routes:

interface QueryParams {
  query?: string;
}

fastify.get<{ Querystring: QueryParams }>(
  '/​search',
  { schema: { querystring: { type: 'object', properties: { query: { type: 'string' } } } } },
  async (request, reply) => {
    const { query } = request.query; // Typed!
    return { results: [] };
  }
);

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View