API
Express.js REST API with authentication, rate limiting, security headers, and database integration
API Application
The API application is a secure, production-ready Express.js backend that provides RESTful endpoints for the Web application. It integrates with Better Auth for authentication, Prisma for database access, and Upstash Redis for rate limiting.
Overview
- Framework: Express.js with TypeScript
- Location:
apps/api - Authentication: Better Auth with session management
- Database: PostgreSQL via Prisma (shared db package)
- Rate Limiting: Upstash Redis
- Port:
http://localhost:4000
Architecture
The API uses shared packages from the monorepo:
- @workspace/auth - Session verification and authentication middleware
- @workspace/db - Prisma ORM and database client
- @workspace/rate-limit - Rate limiting with Upstash Redis
- @workspace/utils - Shared utilities and type definitions
Features
Security
- Helmet - Sets secure HTTP headers (XSS, CSRF, etc.)
- CORS - Configurable cross-origin resource sharing with origin whitelist
- Rate Limiting - Global and per-user rate limits via Upstash Redis
- Authentication - Better Auth session verification on protected routes
- Input Validation - Type-safe request validation with TypeScript
Performance & Observability
- Morgan - HTTP request logging for debugging
- Health Checks - Readiness and liveness endpoints
- Error Handling - Centralized error handling with proper HTTP status codes
Database Integration
- Prisma ORM - Type-safe database queries
- Connection Pooling - Efficient database connection management
- Migrations - Version-controlled schema changes
Project Structure
apps/api/
├── src/
│ ├── middleware/ # Express middleware
│ │ ├── auth.ts # Authentication/session verification
│ │ ├── errorHandler.ts # Centralized error handling
│ │ └── ...
│ ├── routes/ # API route handlers
│ │ ├── health.ts # Health check endpoints
│ │ ├── users.ts # User endpoints
│ │ └── ...
│ ├── controllers/ # Business logic
│ ├── services/ # Complex operations
│ ├── config/
│ │ ├── corsOptions.ts # CORS configuration
│ │ ├── allowedOrigins.ts # Allowed origins list
│ │ └── ...
│ ├── types/ # TypeScript type definitions
│ ├── index.ts # Server entry point
│ └── env.ts # Environment variables parsing
├── .env.example # Environment variables template
├── tsconfig.json # TypeScript configuration
├── package.json # Dependencies and scripts
└── Dockerfile.prod # Production Docker imageEnvironment Variables
For detailed environment variable setup and configuration, see the Environment Variables Guide.
Copy .env.example to .env.local and fill in the required values following the configuration guide.
Setup & Installation
Follow the Getting Started Guide for complete setup instructions.
Quick summary for the API:
# 1. Install dependencies
pnpm install
# 2. Configure environment variables
cp .env.example .env.local
# 3. Set up database
pnpm db:generate && pnpm db:migrate
# 4. Start development server
pnpm devThe API server will start at http://localhost:4000.
The development server uses tsx for hot reload, so changes to your code are reflected instantly.
Key Scripts
| Command | Purpose |
|---|---|
pnpm dev | Start development server with hot reload |
pnpm build | Build for production |
pnpm start | Start production server |
pnpm lint | Check code quality with ESLint |
pnpm format | Format code with Prettier |
pnpm type-check | Check TypeScript types |
See Development Workflow for more commands and options.
Key Files
| File | Purpose |
|---|---|
src/index.ts | Server entry point and middleware setup |
src/middleware/auth.ts | Authentication and session verification |
src/middleware/errorHandler.ts | Centralized error handling |
src/config/corsOptions.ts | CORS configuration |
src/routes/ | All API endpoint handlers |
Dockerfile.prod | Production Docker image |
API Endpoints
Health & Status
GET /api/health- Health check (always accessible)
Users
GET /api/users/session- Get current user session (requires authentication)
For a complete list of endpoints, check the route handlers in src/routes/ or
use an API testing tool like Postman or Insomnia.
Security Configuration
CORS
Allowed origins are configured via the ALLOWED_ORIGINS environment variable:
ALLOWED_ORIGINS=http://localhost:3000,https://your-production-domain.comThis is enforced by:
src/config/corsOptions.ts- CORS middleware configurationsrc/config/allowedOrigins.ts- Origin whitelist parsing
Rate Limiting
The API uses Upstash Redis for distributed rate limiting:
# Global rate limit: 100 requests per minute
# User rate limit: 30 requests per minute per userSee @workspace/rate-limit for configuration details.
Authentication Middleware
Protected routes require valid Better Auth session:
router.get("/api/users/session", requireAuth, getUserHandler);The requireAuth middleware:
- Ensures the request has a valid Better Auth session
- Loads the session using
getSessionif it has not already been resolved - Verifies that the user is authenticated before allowing access
After successful authentication, the following properties are available on the request:
req.user; // Authenticated user object
req.session; // Active session informationIf authentication fails, the request is rejected with:
401 UnauthorizedUse this middleware on any route that requires an authenticated user.
Development Tips
Hot Reload
Code changes automatically reload the server during development - no manual restart needed.
Database Changes
After modifying schema.prisma, run:
pnpm db:generate
pnpm db:migrateTesting Endpoints
Use an API client to test endpoints:
# Test health check
curl http://localhost:4000/api/health
# Test with authentication
curl http://localhost:4000/api/users/session \
--cookie "better-auth.session_token=YOUR_SESSION_COOKIE"Middleware Order
Middleware is applied in this order:
- Security headers (Helmet)
- Logging (Morgan)
- Body parsing
- CORS
- Rate limiting
- Authentication
- Route handlers
- Error handling (last)
Type Safety
Always use TypeScript types for:
- Request/response bodies
- Database models (from Prisma)
- Shared utilities (from
@workspace/utils)
Building for Production
# Build the application
pnpm build
# Start production server
pnpm start
# Or use Docker
docker-compose -f docker-compose.prod.yml up apiThe build process:
- Compiles TypeScript to JavaScript
- Bundles dependencies
- Optimizes for production
Ensure all environment variables (especially BETTER_AUTH_SECRET and
UPSTASH_REDIS_REST_TOKEN) are set correctly in production before building.
Troubleshooting
Port Already in Use
See Port Already in Use in the main troubleshooting guide for platform-specific solutions.
Database Connection Errors
See Database Connection Errors in the main troubleshooting guide.
Authentication Middleware Errors
If authentication middleware is failing:
- Verify
BETTER_AUTH_SECRETmatches the Web app (see Authentication Not Working) - Check
ALLOWED_ORIGINSincludes the Web app URL - Ensure cookies are sent with requests (
credentials: 'include') - Check
src/middleware/auth.tsfor implementation details
Rate Limiting Not Working
# Verify Upstash Redis credentials
# Check UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN
# Test Redis connection:
curl -H "Authorization: Bearer $UPSTASH_REDIS_REST_TOKEN" \
https://YOUR_REDIS_ENDPOINT.upstash.io/get/testCORS Errors
# Verify ALLOWED_ORIGINS includes the Web app domain
# Example: ALLOWED_ORIGINS=http://localhost:3000
# Check browser console for specific error
# Ensure credentials are sent: fetch(url, { credentials: 'include' })Build Fails
# Clear build cache
rm -rf dist
# Rebuild
pnpm build
# Check for TypeScript errors
pnpm type-checkRelated Documentation
- Authentication Package - Session and OAuth setup
- Database Package - Prisma schema and migrations
- Rate Limiting Package - Rate limiting configuration
- Environment Variables - Detailed config guide
- Code Quality - Linting and formatting
For deployment information, see the Deployment Guide.