| name | nodejs-patterns |
| description | Provides best practices for Node.js backend development including layered architecture, configuration management, error handling, and service patterns with Supabase integration. |
Node.js Patterns
Best practices for Node.js backend development. This guide provides high-level patterns and procedural guidance. See references/ for detailed implementation examples.
Quick Reference
| Pattern | Use For | Reference |
|---|
| Layered Architecture | Project structure, separation of concerns | references/layered-architecture.md |
| Configuration | Environment variables, type-safe config | references/configuration.md |
| Error Handling | Custom errors, middleware, typed errors | references/error-handling.md |
| Supabase Integration | Database operations, auth, storage | references/supabase-integration.md |
| Logging | Structured logging, request tracing | references/logging.md |
Layered Architecture
Pattern Overview
Separate your application into distinct layers with clear responsibilities:
- Controllers: Handle HTTP requests/responses, validate input, call services
- Services: Contain business logic, orchestrate operations
- Repositories: Data access layer, database queries
- Middleware: Cross-cutting concerns (auth, logging, validation)
- Routes: Define API endpoints, apply middleware
When to Use
- Building REST APIs
- Applications with complex business logic
- Multi-developer projects requiring clear boundaries
How to Implement
- Create layer-specific directories (
controllers/, services/, repositories/)
- Keep controllers thin (request/response only)
- Put business logic in services
- Isolate data access in repositories
- Use dependency injection for testability
See references/layered-architecture.md for complete implementation examples.
Configuration Management
Pattern Overview
Validate environment variables at startup using Zod for type safety. Export a structured config object throughout the app.
When to Use
- Any production Node.js application
- When type safety for config is needed
- To fail fast on misconfiguration
How to Implement
- Create
config/env.ts with Zod schema
- Validate
process.env on startup
- Exit with error if validation fails
- Export typed config object from
config/index.ts
- Import config throughout app instead of using
process.env directly
See references/configuration.md for complete validation schemas.
Error Handling
Pattern Overview
Use custom error classes with proper status codes. Handle all errors in central middleware. Log full details server-side, return safe messages to clients.
When to Use
- All production applications
- APIs that need consistent error responses
- When you need typed error handling
How to Implement
- Create custom error classes extending
AppError
- Throw specific errors in services (
NotFoundError, ValidationError)
- Use async handler wrapper for route handlers
- Implement central error handler middleware
- Log errors with request context
- Return consistent error format to clients
See references/error-handling.md for complete error class hierarchy and middleware.
Supabase Integration
Pattern Overview
Use service role key for admin operations (bypasses RLS). Use anon key + user token for user-scoped operations (respects RLS).
When to Use
- When using Supabase as your backend
- For applications with Row Level Security policies
- When you need both admin and user-scoped operations
How to Implement
- Create server-side client with service role key
- Create function to generate user-scoped clients
- Use service role client for admin operations
- Use user-scoped client for user operations
- Handle Supabase-specific errors
- Use database functions for transactions
See references/supabase-integration.md for client setup and common patterns.
Logging
Pattern Overview
Use structured logging with Pino. Add context to all log entries. Redact sensitive data automatically. Use appropriate log levels.
When to Use
- All production applications
- When you need request tracing
- For debugging and monitoring
How to Implement
- Configure Pino with proper log level and redaction
- Create child loggers with service context
- Log structured data (objects, not strings)
- Add request IDs for tracing
- Use appropriate log levels (debug/info/warn/error)
- Never log passwords, tokens, or PII
See references/logging.md for complete logger configuration and usage patterns.
Best Practices Summary
Application Structure
- Use layered architecture for separation of concerns
- Keep files under 300 lines
- One class/service per file
- Group related functionality in feature modules
Security
- Validate all input at API boundaries with Zod
- Use parameterized queries (Supabase handles this)
- Never expose service role key to clients
- Implement rate limiting on public endpoints
- Use helmet for security headers
- Enable CORS properly
Error Handling
- Use typed custom errors
- Handle async errors with wrapper or try-catch
- Log full errors server-side
- Return safe error messages to clients
- Include request IDs for tracing
Configuration
- Validate environment variables at startup
- Use type-safe config object
- Never commit secrets to version control
- Document required env vars in
.env.example
Logging
- Use structured logging (objects, not strings)
- Add context to all log entries
- Redact sensitive data automatically
- Use appropriate log levels
- Include request IDs for distributed tracing
Testing
- Test services independently with mocked repositories
- Test controllers with mocked services
- Mock Supabase client in tests
- Aim for 80%+ coverage on business logic
Performance
- Use pagination for large datasets
- Implement caching where appropriate
- Use connection pooling
- Monitor with health check endpoints
- Implement graceful shutdown
Common Patterns
Creating a New Resource
- Define Zod schema for validation
- Create service with CRUD methods
- Create controller handlers with validation
- Define routes with middleware
- Write unit tests for service
- Write integration tests for API
Adding Authentication
- Use Supabase Auth or implement JWT
- Create auth middleware to verify tokens
- Extract user from token and attach to request
- Protect routes by adding auth middleware
- Implement rate limiting on auth endpoints
Adding Authorization
- Define permission checks in middleware
- Check user roles/permissions
- Throw
ForbiddenError if unauthorized
- Use RLS policies in Supabase for data access control
Background Jobs
- Use service role client (admin access)
- Implement job runner (node-cron, Bull)
- Add proper error handling
- Log job execution
- Monitor job failures
File Uploads
- Use Supabase Storage API
- Validate file types and sizes
- Generate unique file names
- Store file paths in database
- Implement cleanup for orphaned files
Anti-Patterns to Avoid
- Fat Controllers: Keep business logic in services, not controllers
- No Validation: Always validate input at API boundaries
- Exposing Errors: Never return stack traces or internal details to clients
- Hardcoded Config: Use environment variables, not hardcoded values
- String Logging: Use structured objects, not string interpolation
- No Request IDs: Always include request IDs for tracing
- Ignoring Async Errors: Always handle promise rejections
- Service Role Everywhere: Use user-scoped clients for user operations
- No Rate Limiting: Protect public endpoints from abuse
- Missing Graceful Shutdown: Handle SIGTERM/SIGINT properly
For detailed implementation examples, see:
references/layered-architecture.md - Complete Express app setup
references/configuration.md - Environment variable validation
references/error-handling.md - Error classes and middleware
references/supabase-integration.md - Database operations
references/logging.md - Structured logging setup