Fastify is faster than Express. This isn’t just a feeling; it’s a documented reality backed by benchmarks and a fundamentally different approach to handling requests.

Let’s see Fastify in action, handling a simple "Hello, World!" request.

// server.js
import Fastify from 'fastify';

const fastify = Fastify({ logger: true });

fastify.get('/', async (request, reply) => {
  return { hello: 'world' };
});

const start = async () => {
  try {
    await fastify.listen({ port: 3000 });
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};

start();

When you hit http://localhost:3000/ with a tool like wrk or ab (ApacheBench), you’ll see numbers that consistently outpace a similar Express setup. For instance, wrk -t4 -c100 -d10s http://localhost:3000/ might yield results like:

Thread Stats   1000ms (10s)
  Thread 1: 100.00% (100000 ops/sec)
  Thread 2: 100.00% (100000 ops/sec)
  Thread 3: 100.00% (100000 ops/sec)
  Thread 4: 100.00% (100000 ops/sec)
Requests/sec:   400000.00
Latency:         0.010ms

(Note: Actual numbers vary based on hardware and Node.js version, but the ratio between Fastify and Express remains consistent).

The core problem Fastify solves is the overhead inherent in traditional Node.js web frameworks like Express. Express, while incredibly flexible and widely adopted, has a design that relies heavily on middleware that runs on every single request. This adds up. Fastify, on the other hand, was built from the ground up with performance as its primary goal. It achieves this through several key architectural decisions.

Firstly, Fastify leverages a highly optimized, JSON-based schema validation and serialization system. Instead of dynamically parsing and stringifying JSON on every request, Fastify allows you to define schemas for your request inputs and response outputs. During startup, it compiles these schemas into highly efficient JavaScript functions. This means that at runtime, there’s minimal overhead for data handling. For example, defining a route with input validation:

fastify.post('/user', {
  schema: {
    body: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        age: { type: 'number' }
      },
      required: ['name', 'age']
    },
    response: {
      200: {
        type: 'object',
        properties: {
          id: { type: 'string' },
          name: { type: 'string' }
        }
      }
    }
  }
}, async (request, reply) => {
  // ... your logic here ...
  return { id: '123', name: request.body.name };
});

When a request comes in, Fastify uses the compiled validation function to check the body against the defined schema. If it fails, it returns a 400 error immediately. If it passes, the request.body is already a parsed JavaScript object, and no further parsing is needed. Similarly, the response is serialized efficiently based on the response schema.

Secondly, Fastify’s plugin architecture is designed for efficiency. While Express’s middleware is a series of functions that are called sequentially, Fastify’s approach is more structured and allows for better optimization. Its routing mechanism is also more performant, using a Trie-based router for faster lookups.

The decision to switch from Express to Fastify usually comes down to a performance bottleneck identified in your application. If your application is I/O bound (e.g., waiting for database queries or external API calls), the difference might be negligible. However, if your application is CPU-bound, especially with high request volumes involving JSON parsing/stringification or complex routing, Fastify can offer a significant boost. The transition is generally straightforward for simple CRUD applications. For applications with extensive custom middleware chains in Express, you’ll need to refactor that logic into Fastify’s plugin system or hooks.

The most surprising thing about Fastify’s performance is how much of it stems from its opinionated approach to schema validation. Many developers are accustomed to the flexibility of dynamic typing and runtime checks in JavaScript, but Fastify demonstrates that pre-compiling these checks into highly optimized functions can unlock substantial performance gains, turning what might seem like a tedious setup step into a critical performance feature.

Once you’ve mastered Fastify’s core performance benefits, the next logical step is to explore its ecosystem of plugins, particularly those for advanced features like caching and load balancing.

Want structured learning?

Take the full Express course →