SYP Start Your Path

Module 3: Backend Frameworks & REST APIs

Express, Fastify, NestJS & Hono

Writing raw http servers (previous chapter) gets tedious fast — backend frameworks handle routing, request parsing, and middleware for you:

// Express — the most widely used Node.js backend framework
const express = require("express");
const app = express();
app.use(express.json()); // parse JSON request bodies

app.get("/users", (req, res) => {
  res.json([{ id: 1, name: "Chiru" }]);
});

app.listen(3000);

Fastify is a newer, performance-focused alternative to Express with a similar feel. NestJS is a full, opinionated framework (built on Express or Fastify underneath) using TypeScript and classes, closer in structure to something like Spring or .NET, for larger enterprise-style backends. Hono is a very lightweight, modern framework designed to run anywhere — Node, Bun, Cloudflare Workers, and more.

HTTP & REST Fundamentals

REST is a convention for designing APIs around HTTP methods and URLs representing resources:

GET    /users        → list users
GET    /users/5      → get user 5
POST   /users        → create a new user
PUT    /users/5      → replace user 5 entirely
PATCH  /users/5      → update part of user 5
DELETE /users/5      → delete user 5

Common status codes: 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 500 Internal Server Error.

Middleware & Validation

Middleware is a function that runs between the request arriving and the final handler responding — used for logging, authentication checks, and more:

function logger(req, res, next) {
  console.log(`${req.method} ${req.url}`);
  next(); // pass control to the next middleware/handler
}
app.use(logger);

// Validation — never trust incoming data as-is
app.post("/users", (req, res) => {
  const { name, email } = req.body;
  if (!name || !email) {
    return res.status(400).json({ error: "name and email are required" });
  }
  // proceed to create the user...
});

Authentication: JWT, Sessions & OAuth

// JWT (JSON Web Token) — a signed token proving who a user is, sent with each request
const jwt = require("jsonwebtoken");

let token = jwt.sign({ userId: 5 }, "secret-key", { expiresIn: "1h" });
// client sends this back in a header: Authorization: Bearer <token>

let payload = jwt.verify(token, "secret-key"); // throws if invalid/expired
console.log(payload.userId);

Sessions are the older, server-stored alternative — the server keeps track of logged-in users itself, and the browser holds only a session ID in a cookie. OAuth is the standard for "Sign in with Google/GitHub" style login — a user grants your app permission through the provider, without ever handing your app their password.

CORS, Rate Limiting & Logging

// CORS — allow a frontend on a different origin to call this API (see Module 2's CORS chapter)
const cors = require("cors");
app.use(cors({ origin: "https://mysite.com" }));

// Rate limiting — protect against abuse by capping requests per IP
const rateLimit = require("express-rate-limit");
app.use(rateLimit({ windowMs: 15 * 60 * 1000, max: 100 })); // 100 requests / 15 min

// Logging — record what's happening in production
const morgan = require("morgan");
app.use(morgan("combined"));