A production-ready Node.js/TypeScript web service backend template featuring user management, authentication, and session handling.
- Fastify - High-performance web framework
- TypeScript - Type-safe development
- Prisma - Database ORM with PostgreSQL
- Redis - Session management with ephemeral tokens
- BetterAuth - Authentication configuration
- Joi - Request validation
- Pino - High-performance logging
- Jest - Testing framework with integration tests
- Docker Compose - Development and test environments
| Component | Technology |
|---|---|
| Web Framework | Fastify |
| Language | TypeScript |
| Database | PostgreSQL |
| ORM | Prisma |
| Cache/Sessions | Redis |
| Authentication | BetterAuth + Custom Session |
| Validation | Joi |
| Logging | Pino |
| Testing | Jest |
| Containerization | Docker |
- Node.js 20.x or higher
- Docker and Docker Compose
- npm or yarn
git clone <repository-url>
cd web-service-template
npm installCopy the example environment file and configure it:
cp .env.example .envEdit .env with your settings:
NODE_ENV=development
PORT=3000
HOST=0.0.0.0
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/webservice? schema=public
REDIS_URL=redis://localhost:6379
AUTH_SECRET=your-super-secret-key-change-in-production
SESSION_TTL_MINUTES=60
LOG_LEVEL=infonpm run start: devThis command will:
- Start PostgreSQL and Redis containers
- Run database migrations
- Start the development server with hot reload
npm run stop:devproject-root/
├── compose/
│ ├── docker-compose.dev.yml # Development services
│ └── docker-compose.test.yml # Test services + runner
├── src/
│ ├── config/
│ │ ├── index.ts # Configuration loader
│ │ ├── database.ts # Prisma client setup
│ │ ├── redis.ts # Redis client setup
│ │ └── auth.ts # BetterAuth configuration
│ ├── middleware/
│ │ └── auth.ts # Authentication middleware
│ ├── routes/
│ │ ├── index.ts # Route registration
│ │ ├── auth.routes.ts # Auth routes
│ │ ├── user.routes.ts # User management routes
│ │ └── health.routes.ts # Health check routes
│ ├── schemas/
│ │ ├── auth.schema.ts # Auth validation schemas
│ │ └── user.schema.ts # User validation schemas
│ ├── services/
│ │ ├── auth.service.ts # Authentication logic
│ │ ├── user.service.ts # User management logic
│ │ └── session.service.ts # Session management
│ ├── types/
│ │ └── index.ts # TypeScript definitions
│ ├── utils/
│ │ └── logger.ts # Pino logger setup
│ ├── app.ts # Fastify app setup
│ └── server. ts # Server entry point
├── prisma/
│ └── schema.prisma # Database schema
├── tests/
│ ├── setup.ts # Jest setup
│ ├── helpers/
│ │ └── test-utils.ts # Test utilities
│ └── integration/
│ ├── auth.test.ts # Auth tests
│ ├── user. test.ts # User tests
│ └── health.test.ts # Health tests
├── .env.example # Environment template
├── .env.test # Test environment
├── Dockerfile # Multi-stage Dockerfile
├── package.json
├── tsconfig.json
└── README.md
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Basic health check |
| GET | /health/ready |
Readiness probe (checks DB & Redis) |
| GET | /health/live |
Liveness probe |
| Method | Endpoint | Auth Required | Description |
|---|---|---|---|
| POST | /auth/register |
No | Register new user |
| POST | /auth/login |
No | Login user |
| POST | /auth/logout |
Yes | Logout current session |
| POST | /auth/logout-all |
Yes | Logout all sessions |
| POST | /auth/change-password |
Yes | Change password |
| GET | /auth/me |
Yes | Get current user |
| Method | Endpoint | Auth Required | Admin Only | Description |
|---|---|---|---|---|
| GET | /users/profile |
Yes | No | Get user profile |
| PUT | /users/profile |
Yes | No | Update user profile |
| DELETE | /users/profile |
Yes | No | Delete user account |
| GET | /users |
Yes | Yes | List all users (paginated) |
| GET | /users/:id |
Yes | Yes | Get user by ID |
| DELETE | /users/:id |
Yes | Yes | Delete user by ID |
- Sessions are stored in Redis with a 60-minute TTL
- Tokens are renewed automatically on each authenticated request
- Pass the token in the
Authorizationheader:
Authorization: Bearer <session-token>
curl -X POST http://localhost:3000/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123",
"name": "John Doe"
}'Response:
{
"success": true,
"data": {
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "John Doe",
"role": "USER"
},
"token": "session-token"
},
"message": "User registered successfully"
}curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'curl -X GET http://localhost:3000/users/profile \
-H "Authorization: Bearer <session-token>"curl -X PUT http://localhost:3000/users/profile \
-H "Authorization: Bearer <session-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane Doe"
}'| Script | Description |
|---|---|
npm run start:dev |
Start development environment |
npm run stop:dev |
Stop development services |
npm run build |
Build TypeScript to JavaScript |
npm start |
Run production server |
npm test |
Run tests in Docker |
npm run test:local |
Run tests locally |
npm run prisma:generate |
Generate Prisma client |
npm run prisma:migrate |
Run database migrations |
npm run lint |
Run ESLint |
npm run clean |
Remove build artifacts |
npm testThis will:
- Start test PostgreSQL and Redis containers
- Run database migrations
- Execute Jest integration tests
- Clean up containers
If you have services running locally:
npm run test:localTests cover:
- All authentication routes (register, login, logout, password change)
- All user management routes (profile CRUD, admin operations)
- All health check endpoints
- Authorization middleware
- Input validation
- Error handling
The database includes a User model with:
| Field | Type | Description |
|---|---|---|
| id | UUID | Primary key |
| String | Unique email address | |
| emailVerified | Boolean | Email verification status |
| passwordHash | String | Hashed password |
| name | String? | Optional display name |
| image | String? | Optional profile image URL |
| role | Enum | USER or ADMIN |
| createdAt | DateTime | Creation timestamp |
| updatedAt | DateTime | Last update timestamp |
Create a new migration:
npm run prisma:migrate -- --name <migration-name>Apply migrations:
npm run prisma:migrate:deploy| Variable | Description | Default |
|---|---|---|
NODE_ENV |
Environment mode | development |
PORT |
Server port | 3000 |
HOST |
Server host | 0.0.0.0 |
DATABASE_URL |
PostgreSQL connection string | - |
REDIS_URL |
Redis connection string | redis://localhost:6379 |
AUTH_SECRET |
Secret key for authentication | - |
SESSION_TTL_MINUTES |
Session timeout in minutes | 60 |
LOG_LEVEL |
Pino log level | info |
npm run builddocker build --target production -t web-service: latest .docker run -p 3000:3000 \
-e DATABASE_URL=<your-database-url> \
-e REDIS_URL=<your-redis-url> \
-e AUTH_SECRET=<your-secret> \
web-service:latest- Password Hashing: Passwords are hashed using SHA-256 with a random salt
- Timing-Safe Comparison: Password verification uses timing-safe comparison
- Session Management: Ephemeral sessions with automatic expiration
- Input Validation: All inputs validated with Joi schemas
- CORS: Configurable CORS settings
- Error Handling: Sanitized error messages in production
- Change
AUTH_SECRETto a strong, unique value - Configure proper CORS origins
- Enable HTTPS/TLS
- Set
NODE_ENV=production - Configure rate limiting
- Set up monitoring and alerting
- Enable email verification for registration
- Review and adjust session TTL
- Create route file in
src/routes/ - Create validation schema in
src/schemas/ - Create service in
src/services/ - Register routes in
src/routes/index.ts - Add tests in
tests/integration/
- Update
prisma/schema.prisma - Run
npm run prisma:migrate - Create corresponding service and routes
MIT License