Backend Overview
Languages, when to use Node vs Python, databases, ORMs, and shared conventions.
UXDL backend services are built in one of two languages: Node.js (Express + TypeScript) or Python (FastAPI). Both follow the same API contract — /v1/ routing, AWS Cognito auth, a consistent JSON error shape, and the same cloud services — so services stay interchangeable regardless of language.
Languages
| Node.js · Express | Python · FastAPI | |
|---|---|---|
| Language | TypeScript 5.x | Python 3.12+ |
| Framework | Express 4.x | FastAPI |
| Runtime / server | Node.js 20 LTS | Uvicorn (ASGI) |
| Validation | Zod | Pydantic v2 |
| ORM | Sequelize · Drizzle | SQLAlchemy 2.0 |
| Package manager | pnpm | uv |
| Guides | Setup · Structure · Auth | Setup · Structure · Auth |
When to use which
| Use Node.js when… | Use Python when… |
|---|---|
| The service is primarily CRUD / REST APIs | The service does data, ML, or scientific work |
| You share types/code with a TypeScript frontend | You need the Python data/AI ecosystem (pandas, numpy, ML SDKs) |
| Realtime via Socket.io is central | Heavy async I/O fan-out fits FastAPI's model |
| The team owning it is TypeScript-first | The team owning it is Python-first |
Shared platform
These layers are identical across both languages — only the SDK/client differs:
| Layer | Technology | Purpose |
|---|---|---|
| Auth | AWS Cognito + Bearer JWT | Token validation, scopes, rate limits |
| Realtime | Socket.io (Node) | WebSocket events, rooms, live updates |
| Storage | AWS S3 + CloudFront | File uploads, exports, static assets |
| Push | Firebase Cloud Messaging | Web, iOS, and Android push notifications |
| AWS SES · SendGrid · Brevo | Transactional email (provider per env) | |
| Deploy | Docker → AWS ECS (Fargate) | Container build and production runtime |
Databases & ORMs
Pick the data store per service, then the ORM/client that matches the service's language:
| Database | Node | Python | Use when |
|---|---|---|---|
| PostgreSQL | Sequelize · Drizzle | SQLAlchemy | Relational data, transactions, JOINs |
| MongoDB | Mongoose | Beanie / Motor | Document data, flexible schemas, high write volume |
| Supabase | @supabase/supabase-js | supabase-py | Managed Postgres + auth + storage + realtime |
Architecture at a glance
Documentation flow
Pick your language: Node.js Setup or Python Setup.
Learn the layout — Node Folder Structure or Python Folder Structure.
Wire auth — Node API Authentication or Python API Authentication.
- Pick your database guide under Data Layer in the sidebar.
- Socket.io — if the service needs realtime events.
- AWS S3 — file uploads and presigned URLs.
Shared API conventions
These hold for every service, in either language:
- REST routes prefixed with
/v1/ - Consistent JSON error shape on every endpoint
requestIdon all responses for tracing (see Observability)- OpenAPI spec maintained alongside routes (FastAPI generates it automatically)
- Route handlers stay thin — business logic lives in services
Key dependencies
// Node.js (package.json)
{
"dependencies": {
"express": "^4.21.0",
"socket.io": "^4.8.0",
"jsonwebtoken": "^9.0.0",
"jwks-rsa": "^3.1.0",
"sequelize": "^6.37.0",
"drizzle-orm": "^0.38.0",
"mongoose": "^8.9.0",
"@supabase/supabase-js": "^2.47.0",
"@aws-sdk/client-s3": "^3.700.0",
"@aws-sdk/client-ses": "^3.700.0",
"firebase-admin": "^13.0.0",
"zod": "^3.24.0"
}
}# Python (pyproject.toml)
[project]
dependencies = [
"fastapi[standard]",
"uvicorn",
"pydantic-settings",
"sqlalchemy[asyncio]",
"asyncpg",
"alembic",
"beanie",
"python-jose[cryptography]",
"boto3",
"slowapi",
]Official documentation
- Express.js · Node.js · TypeScript
- FastAPI · Pydantic · uv
- Socket.io