Introductie
Het landschap van backend-ontwikkeling heeft de afgelopen twee jaar een tektonische verschuiving ondergaan. Bijna tien jaar lang was Express 4.x de industriestandaard, waarbij ontwikkelaars afhankelijk waren van externe libraries voor basistaken zoals het afhandelen van asynchrone fouten of het maken van HTTP-verzoeken. Met de komst van Express 5.0 en Node.js 22/23 LTS is het ecosysteem echter uitgegroeid tot een meer gestroomlijnde, performante en veilige omgeving.
Het bouwen van een REST API in 2025 gaat niet langer alleen over routing; het gaat over type-veiligheid, contract-first design en het benutten van native runtime-mogelijkheden die voorheen niet beschikbaar waren. Deze gids verkent hoe je professionele REST API's bouwt met de nieuwste functies van Node.js en Express, van de basisinstallatie tot geavanceerde architecturale patronen.
De moderne basis: Node.js 22 en Express 5.0
Voordat we een enkele regel code schrijven, is het essentieel om de moderne omgeving te begrijpen. Node.js 22 heeft functies geïntroduceerd die de "dependency-moeheid" aanzienlijk verminderen.
ES Modules (ESM) omarmen
CommonJS (require) is in feite een verouderd formaat in het moderne Node.js-ecosysteem. Door "type": "module" in je package.json in te stellen, krijg je toegang tot top-level await en betere statische analyse voor bundling-tools.
{
"name": "modern-express-api",
"version": "1.0.0",
"type": "module",
"dependencies": {
"express": "^5.0.0",
"zod": "^3.23.0"
}
}Express 5.0: Native Async-ondersteuning
De belangrijkste update in Express 5.0 is de native afhandeling van Promises. In Express 4 zou een niet-afgehandelde rejection in een async route het verzoek laten hangen of het proces laten crashen, tenzij het verpakt was in een try-catch blok of een helper zoals express-async-handler. Express 5.0 vangt deze fouten automatisch op en geeft ze door aan je globale error-handling middleware.
Native Fetch en WebSockets
Node.js 22 stabiliseert de native fetch API. Dit betekent dat je REST API nu kan communiceren met andere microservices zonder de overhead van axios of node-fetch. Daarnaast biedt de toevoeging van node:ws een native pad voor het toevoegen van real-time mogelijkheden aan je RESTful endpoints.
Architecturale uitmuntendheid: Het drielagenmodel
Een veelgemaakte fout in Express-ontwikkeling is het "Fat Controller"-syndroom, waarbij alle business-logica, database-queries en validatie zich binnen de route-handler bevinden. Om een schaalbare API te bouwen, implementeren we een Modulaire Drielagenarchitectuur.
1. De Controller-laag
De enige verantwoordelijkheid van de controller is het afhandelen van de HTTP-"interface". Het analyseert het verzoek, roept de juiste service aan en retourneert een geformatteerd antwoord. Het mag nooit rechtstreeks met de database communiceren.
2. De Service-laag
Dit is het hart van je applicatie. De service-laag bevat de kern van de business-logica. Als je een korting moet berekenen, een e-mail moet verzenden of de geschiktheid van een gebruiker moet controleren, gebeurt dat hier. Deze laag is framework-agnostisch, waardoor het eenvoudig is om te testen of later over te stappen naar een ander framework.
3. De Data Access Layer (DAL)
De DAL communiceert met je database. Met een ORM zoals Prisma of een ODM zoals Mongoose abstraheert deze laag de queries. Door de datatoegang te isoleren, kun je overstappen van PostgreSQL naar MongoDB met minimale impact op je business-logica.

CRUD implementeren met type-veiligheid en validatie
In 2025 is het vertrouwen op input van de client een kritiek beveiligingsrisico. We gebruiken Zod voor runtime-validatie en TypeScript voor veiligheid tijdens het compileren.
Het schema definiëren
Zod stelt je in staat om een schema te definiëren dat de req.body valideert en tegelijkertijd een TypeScript-type genereert.
import { z } from 'zod';
export const CreateUserSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
role: z.enum(['USER', 'ADMIN']).default('USER'),
});
type CreateUserDto = z.infer<typeof CreateUserSchema>;De Express 5.0 Route Handler
Merk op hoe schoon de route wordt wanneer we gebruikmaken van de native promise-afhandeling van Express 5.0 en een gecentraliseerde validatie-middleware.
import express from 'express';
import { userService } from '../services/user.service.js';
import { validate } from '../middleware/validate.js';
import { CreateUserSchema } from '../schemas/user.schema.js';
const router = express.Router();
router.post('/', validate(CreateUserSchema), async (req, res) => {
// Logica wordt alleen uitgevoerd als de validatie slaagt
const newUser = await userService.createUser(req.body);
res.status(201).json(newUser);
});
export default router;Gecentraliseerde foutafhandeling
In plaats van verspreide res.status(500) aanroepen, gebruiken we een globale error handler. Express 5.0 maakt dit krachtiger door fouten die uit async-functies worden gegooid automatisch op te vangen.
// middleware/errorHandler.js
export const errorHandler = (err, req, res, next) => {
const statusCode = err.statusCode || 500;
const message = err.message || 'Interne Serverfout';
console.error(`[Fout] ${req.method} ${req.url}:`, err);
res.status(statusCode).json({
status: 'error',
code: err.code || 'INTERNAL_ERROR',
message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
};Geavanceerde technieken: Beveiliging en prestaties
Een productie-klare API vereist meer dan alleen CRUD-operaties. Het vereist een robuuste beveiligingshouding en inzicht in de Node.js event loop.
Het Node.js permissiemodel
Een van de meest opwindende toevoegingen in Node.js 22 is het experimentele permissiemodel. Je kunt nu de toegang van je API tot de omgeving beperken. Bijvoorbeeld:
node --experimental-permission --allow-fs-read=/tmp/ --allow-net=api.stripe.com server.js
Dit zorgt ervoor dat zelfs als een dependency gecompromitteerd is, de aanvaller je /etc/passwd bestand niet kan lezen of gegevens naar een kwaadaardig domein kan sturen.
Zware berekeningen afhandelen
Node.js is single-threaded. Als je API grote afbeeldingen moet verwerken of complexe PDF's moet genereren, zal dit de event loop blokkeren, waardoor andere verzoeken niet kunnen worden afgehandeld.
- Oplossing: Gebruik Worker Threads voor CPU-intensieve taken of verplaats ze naar een background worker zoals BullMQ met behulp van Redis. Dit houdt je REST API responsief.
Security Headers en opschoning (sanitization)
Gebruik altijd Helmet.js om veilige HTTP-headers in te stellen. Het beschermt standaard tegen veelvoorkomende kwetsbaarheden zoals Cross-Site Scripting (XSS) en clickjacking.
import helmet from 'helmet';
const app = express();
app.use(helmet()); // Stelt 15+ security headers in
Real-world scenario: Geavanceerde filtering implementeren
Moderne API's moeten vaak complexe zoekopdrachten ondersteunen. In plaats van aangepaste logica voor elke route te schrijven, kunnen we een herbruikbare "Query Features" utility bouwen.
class APIFeatures {
constructor(query, queryString) {
this.query = query; // De Prisma of Mongoose query
this.queryString = queryString; // req.query
}
filter() {
const queryObj = { ...this.queryString };
const excludedFields = ['page', 'sort', 'limit', 'fields'];
excludedFields.forEach(el => delete queryObj[el]);
// Geavanceerde filtering (bijv. price[gte]=500)
let queryStr = JSON.stringify(queryObj);
queryStr = queryStr.replace(/\b(gte|gt|lte|lt)\b/g, match => `$${match}`);
this.query = this.query.find(JSON.parse(queryStr));
return this;
}
paginate() {
const page = this.queryString.page * 1 || 1;
const limit = this.queryString.limit * 1 || 100;
const skip = (page - 1) * limit;
this.query = this.query.skip(skip).limit(limit);
return this;
}
}Hiermee kun je verzoeken zoals GET /api/products?price[gte]=100&page=2&limit=20 afhandelen met slechts een paar regels code in je service-laag.
Essentiële tools voor 2025
| Tool | Doel | Waarom het essentieel is |
|---|---|---|
| Prisma | ORM | Biedt volledige type-veiligheid voor je database-schema. |
| PM2 | Procesbeheer | Regelt clustering om alle CPU-cores te benutten en zorgt voor zero-downtime herstarts. |
| Swagger UI | Documentatie | Genereert automatisch interactieve API-docs vanuit je OpenAPI 3.1 specificatie. |
| Winston | Logging | Gestructureerde JSON-logging is vereist voor moderne observability tools zoals Datadog. |
Veelgestelde vragen
Hoe bouw ik vanaf nul een RESTful API met Node.js en Express?
Om vanaf nul een API te bouwen, initialiseer je een Node.js-project met npm init, installeer je Express en maak je een entry point-bestand aan. Vervolgens definieer je routes met app.get(), app.post(), enz., en gebruik je middleware om JSON te parsen en fouten af te handelen.
Wat is het verschil tussen Node.js en Express.js bij API-ontwikkeling?
Node.js is de JavaScript runtime-omgeving waarmee je code op de server kunt draaien, terwijl Express.js een minimaal webframework is dat bovenop Node.js is gebouwd. Node.js biedt de kernmogelijkheden voor netwerken, terwijl Express routing, middleware-integratie en verzoekafhandeling vereenvoudigt.
Hoe ga ik om met authenticatie en autorisatie in een Node.js REST API?
Authenticatie wordt meestal afgehandeld met JSON Web Tokens (JWT) of sessie-cookies via middleware zoals Passport.js of aangepaste logica. Autorisatie wordt geïmplementeerd door de rol of permissies van de gebruiker (geëxtraheerd uit het token) te controleren tegen de vereisten van de specifieke route.
Wat zijn de best practices voor het structureren van een Node.js Express-project?
Een best-practice structuur maakt gebruik van een gelaagde architectuur, waarbij code wordt gescheiden in mappen voor Controllers, Services, Models (DAL) en Middleware. Deze scheiding van belangen zorgt ervoor dat de business-logica geïsoleerd is van de HTTP-transportlaag, waardoor de codebase gemakkelijker te testen en te onderhouden is.
Hoe verbind je een Node.js REST API met een MongoDB-database?
Je maakt verbinding met MongoDB met de officiële MongoDB-driver of een ODM zoals Mongoose. Je stelt een verbindingsstring in je omgevingsvariabelen in en gebruikt een singleton-patroon om ervoor te zorgen dat de databaseverbinding wordt gedeeld over de service-laag van je applicatie.
Conclusie
Het bouwen van REST API's met Node.js en Express is uitgegroeid tot een geavanceerde discipline. De release van Express 5.0 markeert een keerpunt waar asynchrone patronen eindelijk volwaardig worden ondersteund, wat boilerplate en foutgevoelige code aanzienlijk vermindert. Door dit te combineren met de native functies van Node.js 22 — zoals het permissiemodel en de fetch API — en een strikte drielagenarchitectuur, kunnen ontwikkelaars systemen bouwen die niet alleen performant zijn, maar ook veerkrachtig en veilig.
Geef bij het verder ontwikkelen prioriteit aan contract-first design met OpenAPI en runtime-validatie met Zod. Deze tools zorgen ervoor dat naarmate je API groeit, deze een betrouwbaar contract blijft voor je frontend- en mobiele consumenten. De "Express-manier" in 2025 draait om meer doen met minder: minder dependencies, meer native functies en schonere, type-veilige code.