UXDL Docs

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 · ExpressPython · FastAPI
LanguageTypeScript 5.xPython 3.12+
FrameworkExpress 4.xFastAPI
Runtime / serverNode.js 20 LTSUvicorn (ASGI)
ValidationZodPydantic v2
ORMSequelize · DrizzleSQLAlchemy 2.0
Package managerpnpmuv
GuidesSetup · Structure · AuthSetup · Structure · Auth

When to use which

Use Node.js when…Use Python when…
The service is primarily CRUD / REST APIsThe service does data, ML, or scientific work
You share types/code with a TypeScript frontendYou need the Python data/AI ecosystem (pandas, numpy, ML SDKs)
Realtime via Socket.io is centralHeavy async I/O fan-out fits FastAPI's model
The team owning it is TypeScript-firstThe team owning it is Python-first

Shared platform

These layers are identical across both languages — only the SDK/client differs:

LayerTechnologyPurpose
AuthAWS Cognito + Bearer JWTToken validation, scopes, rate limits
RealtimeSocket.io (Node)WebSocket events, rooms, live updates
StorageAWS S3 + CloudFrontFile uploads, exports, static assets
PushFirebase Cloud MessagingWeb, iOS, and Android push notifications
EmailAWS SES · SendGrid · BrevoTransactional email (provider per env)
DeployDocker → 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:

DatabaseNodePythonUse when
PostgreSQLSequelize · DrizzleSQLAlchemyRelational data, transactions, JOINs
MongoDBMongooseBeanie / MotorDocument data, flexible schemas, high write volume
Supabase@supabase/supabase-jssupabase-pyManaged Postgres + auth + storage + realtime

Architecture at a glance

Documentation flow

  1. Pick your language: Node.js Setup or Python Setup.

  2. Learn the layout — Node Folder Structure or Python Folder Structure.

  3. Wire auth — Node API Authentication or Python API Authentication.

  4. Pick your database guide under Data Layer in the sidebar.
  5. Socket.io — if the service needs realtime events.
  6. AWS S3 — file uploads and presigned URLs.
  7. FCM / Email — push and transactional email.

  8. DockerAWS ECS — build and deploy.

Shared API conventions

These hold for every service, in either language:

  • REST routes prefixed with /v1/
  • Consistent JSON error shape on every endpoint
  • requestId on 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

json
// 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"
  }
}
toml
# Python (pyproject.toml)
[project]
dependencies = [
    "fastapi[standard]",
    "uvicorn",
    "pydantic-settings",
    "sqlalchemy[asyncio]",
    "asyncpg",
    "alembic",
    "beanie",
    "python-jose[cryptography]",
    "boto3",
    "slowapi",
]

Official documentation