03/06/24

The Node Frameworks to know for 2024

Which Node.js framework suits your project best?

9 Min Read

Node.js remains a key choice for many teams building Web Applications and SaaS services. When choosing a backend framework for Node.js, developers now have a range of options, each with its unique strengths and ideal use cases.

However, making the right choice can be challenging. So in this article we take a look at the leading frameworks and compare them, including:

  • Express.js
  • Nest.js
  • Koa.js
  • Encore

Encore

Encore Interface

Encore is a modern alternative, aimed at teams looking for an integrated and developer-experience focused approach to backend development. Encore is purposefully designed to make it less complex to build event-driven and distributed systems, and solves for both the local dev experience and assists with deployment using robust and scalable services from AWS and GCP.

It works by providing an API Framework and an Infrastructure SDK that lets developers declare infrastructure semantics as part of the application code. Encore then parses the code and creates a fully type-safe model of your application's microservices, APIs, and infrastructure requirements. Encore then automatically runs your local environment, deploys to temporary preview environments for testing, and provisions infrastructure and deploys to your cloud (AWS/GCP).

Code Examples

Defining a service

With Encore you define a service by creating a folder and inside that folder defining an API within a regular TypeScript file. Encore recognizes this as a service, and uses the folder name as the service name. When deploying, Encore will automatically provision the required infrastructure for each service.

On disk it might look like this:

/my-app ├── encore.app // ... and other top-level project files ├── package.json │ ├── hello // hello service (a folder) │   ├── hello.ts // hello service code │   └── hello_test.ts // tests for hello service │ └── world // world service (a folder) └── world.ts // world service code

This means building a microservices architecture is as simple as creating multiple directories within your application.

Defining APIs

Encore lets you easily define type-safe, idiomatic TypeScript API endpoints.

It's simple to accept both the URL path parameters, as well as JSON request body data, HTTP headers, and query strings.

It's done in a way that is fully declarative, enabling Encore to automatically parse and validate the incoming request and ensure it matches the schema, with zero boilerplate.

To define an API, use the api function from the encore.dev/api module to wrap a regular TypeScript async function that receives the request data as input and returns response data. This tells Encore that the function is an API endpoint. Encore will then automatically generate the necessary boilerplate at compile-time.

In the example below, we define the API endpoint ping which accepts POST requests and is exposed as hello.ping (because our service name is hello).

// inside the hello.ts file import { api } from "encore.dev/api" export const ping = api( { method: "POST" }, async (p: PingParams): Promise<PingResponse> => { return { message: `Hello ${p.name}!` }; } );

Creating a Pub/Sub topic

Publishers & Subscribers (Pub/Sub) let you build systems that communicate by broadcasting events asynchronously. This is a great way to decouple services for better reliability and responsiveness.

Encore's Infrastructure SDK lets you use Pub/Sub in a cloud-agnostic declarative fashion. At deployment, Encore automatically provisions the required infrastructure.

The core of Pub/Sub is the Topic, a named channel on which you publish events.

Encore makes it very simple to create Topics. For example, here's how you create a topic with events about user signups:

import { Topic } "encore.dev/pubsub" export interface SignupEvent { userID: string; } export const signups = new Topic<SignupEvent>("signups", { deliveryGuarantee: "at-least-once", });

To publish an Event, call publish on the topic passing in the event object (which is the type specified in the new Topic<Type> constructor):

const messageID = await signups.publish({userID: id}); // If we get here the event has been successfully published, // and all registered subscribers will receive the event. // The messageID variable contains the unique id of the message, // which is also provided to the subscribers when processing the event.

Key Features

  • No boilerplate: Create APIs and microservices without any overhead.
  • Built-in Distributed Tracing: Easily trace the path and performance of requests.
  • Automating API Documentation & Architecture Diagrams: Automatically keep documentation and diagrams up-to-date.
  • Built-in Secrets Management: Handle sensitive data securely.
  • Cloud Infrastructure Automation: Automatically provision infrastructure in local, preview, and your cloud environment in GCP and AWS.
  • Backend Primitives: Use primitives like microservices, SQL databases, Pub/Sub message queues, and Redis caches all without manual infrastructure configuration.
  • Push to Deploy: Get a Vercel-like workflow for your backend application, and integrate with Vercel for full-stack preview environments.

Benefits

  • Production-Ready: Comes with built-in support for automated deployment to AWS/GCP, scaling, and monitoring, which is ideal for production environments.
  • Type-Safety: Offers end-to-end type safety, including infrastructure, reducing runtime errors and bugs.
  • Simplicity and Speed: Encore abstracts away the complexities of infrastructure management, allowing developers to concentrate on coding.
  • Standardization: Provides a uniform way of building microservices and APIs, and provisioning infrastructure, that follows best practices.
  • Built-in Tools: Encore offers built-in distributed tracing, automated API documentation, preview environments, metrics, and more.

Limitations

  • To get the most value from Encore you need to use both the API Framework and the Infrastructure SDK, which depending on your current situation may involve making some changes to your codebase. See the migration guide for advice.

Suitable for

  • Encore is most suitable for teams looking to develop production-ready applications that require robust scalability and maintainability out of the box.
  • It's particularly relevant for those who want to streamline their development workflow with built-in tools for common tasks, ensuring that developers can focus on building features rather than configuring the environment.

When to consider Encore

  • When you want to build event-driven systems using scalable infrastructure like Pub/Sub.
  • When you want to build a scalable system deployed to battle-tested infrastructure on AWS/GCP like Kubernetes or Cloud Run.
  • When you want to automate API documentation and Architecture Diagrams, and remove most microservies boilerplate.
  • When you want built-in observability like Distributed Tracing, Metrics, and integrations with tools like Grafana and Datadog.

Try Encore

Express.js

Express.js

Express.js, is in essence the most common Node.js web framework. It offers a minimalistic and flexible approach, and has become for its speed and minimal overhead, providing just the core framework features needed to build web applications and APIs.

Key Features

  • Middleware: Utilizes middleware to respond to HTTP requests, making it incredibly versatile for a variety of web applications.
  • Routing: Offers a robust routing API that allows users to define routes based on HTTP methods and URLs.
  • Templating: Supports template engines to render HTML on the server-side which can then be sent as a response to client requests.

Benefits

  • Simplicity: Very minimal and straightforward, making it easy to learn and use.
  • Flexibility: Allows developers to structure their applications as they see fit, with no opinion on architecture.
  • Mature Ecosystem: Has a large community, comprehensive documentation, and a plethora of middleware.

Limitations

  • Callback Structure: Can lead to callback hell if not carefully managed, although this can be mitigated with modern JavaScript features.
  • Less Standardized: Might require more decisions to be made by the developer, potentially leading to inconsistency in project structure.
  • Few features: While fast, there are few features included which means you will likely need to adopt many different tools to solve for deployment, monitoring, and scaling.

Suitable for

  • Express.js is great for simple projects where you need to have full flexibility.

When to consider Express.js

  • When developing small to medium-sized projects and prototypes.

Nest.js

Nest.js

Nest.js brings a structured, Angular-inspired framework to the backend, embracing TypeScript as a first-class citizen. It offers a modular architecture that organizes code into separate modules, designed to make it easier to maintain and develop larger applications.

Key Features

  • WebSockets: Provides out-of-the-box support for WebSockets, enabling real-time communication capabilities.
  • Dependency Injection: Implements dependency injection which allows for more testable and maintainable code.

Benefits

  • Standardization: Provides a uniform way of building services.
  • TypeScript Support: First-class support for TypeScript for application reliability.
  • Scalability: Designed with scalability in mind, making it suitable for large applications.

Limitations

  • Steep Learning Curve: Its specific way of doing things might require an initial investment in time to learn.
  • Potential Overhead: For simpler projects, Nest.js might seem overkill.
  • Opinionated: Its structured approach may not be suitable for those looking for more freedom in design choices.

Suitable for

  • Nest.js is well-suited for teams that are familiar with TypeScript and Angular.

When to consider Nest.js

  • Its opinionated structure is advantageous for large-scale projects where scalability and long-term maintainability are more important than speed and simplicity.

Koa.js

Koa.js

Koa.js is created by the team behind Express.js and aims to be a more modern and flexible foundation for web applications and APIs. It uses a middleware stack that executes in a stack-like manner, allowing for more expressive and robust error handling.

Key Features

  • Context Object: Uses a context object encapsulating Node's request and response objects, providing a more intuitive API.
  • Error Handling: Promises and async/await based control flow allows for better error handling mechanisms.

Benefits

  • Modern Design: Built around ES6 features like async/await, which simplifies error handling and middleware composition.
  • Customizable: It provides a robust set of methods but leaves the architecture and choice of additional modules to the developer.

Limitations

  • Less Middleware: Compared to other frameworks, there are fewer middleware options readily available.
  • Smaller Community: Not as widely adopted as Express, meaning less community support and fewer resources.

Suitable for

  • Koa.js is appropriate for developers who prefer a modern syntax and are comfortable using async/await.

When to consider Koa.js

  • Koa.js is a good choice when you need a solid foundation for applications that require high customizability without the overhead of features you may not use.

Conclusion

Node developers are spoiled with many great frameworks to choose from. However, Encore stands out as the only framework that comes with a solution for automated deployment to production-ready infrastructure on AWS/GCP. This makes it a great choice for startups building with speed and scalability in mind.

Ready to escape the hamster wheel?

Encore is Backend Development Platform purpose-built for creating event-driven and distributed systems — from developing locally to scaling in your cloud on AWS/GCP.