Building the backend — Node.js and Python FastAPI
A fast frontend needs a solid backend behind it. Here's how I build REST APIs with Node.js and Python's FastAPI, and how I pick between them.
A polished frontend is only half a real product. The moment a project needs to store data, talk to other services, process payments or run logic you can’t trust to the browser, it needs a backend. I build those with Node.js and with Python’s FastAPI — and choosing between them is a big part of getting it right.
My two go-to backends
Node.js (with Express or Fastify) — my default when the backend lives close to a web app:
- Same language as the frontend (TypeScript), so I share types and validation between client and server.
- Great for API routes, webhooks (Midtrans, Stripe), and talking to the same services the frontend uses.
- Pairs naturally with Next.js API routes and serverless functions.
Python + FastAPI — my go-to when the backend is data- or AI-heavy:
- Automatic, typed request/response validation with Pydantic — fewer bugs, less boilerplate.
- Auto-generated OpenAPI/Swagger docs out of the box, so the API is documented and testable from day one.
- Async support for fast, concurrent endpoints, and direct access to Python’s data and ML ecosystem.
A typical FastAPI endpoint
The thing I like most about FastAPI is how little ceremony it takes to get a typed, validated, documented endpoint:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Booking(BaseModel):
name: str
tour: str
guests: int
@app.post("/bookings")
async def create_booking(booking: Booking):
# validated automatically; persist to the database here
return {"status": "received", "tour": booking.tour}
That’s a fully validated POST endpoint with interactive docs at /docs — no extra
wiring.
How I choose
- Close to the web app, sharing types, handling webhooks? → Node.js.
- Data processing, analytics, AI, or a service other teams will call? → FastAPI.
Either way, the frontend stays fast and the heavy lifting happens in a backend that’s built for the job. That’s what full-stack actually means in practice: not one favourite tool, but the right one for each part of the system.