Model relationships: users.orders (1:N), orders.products (N:M)
Version from start: Start with /api/v1 (easier to add v2 later)
Red Flags:
Non-RESTful URLs: /api/getUserById?id=123 (use GET /api/v1/users/123)
Verbs in URLs: /api/deleteUser (use DELETE /api/v1/users/:id)
No versioning: /api/users (add /v1 from start)
✅ REQUIRED: Data Persistence Strategy
Decision Tree:
Choosing database?
→ Structured data + relations? → PostgreSQL (RECOMMENDED)
→ Document-oriented + flexible schema? → MongoDB
→ Key-value cache? → Redis
→ Time-series data? → TimescaleDB, InfluxDB
ORM vs Query Builder?
→ TypeScript + type safety? → Prisma (RECOMMENDED)
→ Need raw SQL flexibility? → Knex, Drizzle
→ Existing project with TypeORM? → TypeORM (maintain consistency)
Implementation: Delegate to nodejs for database patterns
✅ REQUIRED: Performance Optimization
When to optimize:
Measure FIRST (APM tools, profiling, load testing)
Identify bottlenecks (slow queries, N+1 problems, large payloads)
Apply targeted fixes (NOT premature optimization)
Common Optimizations:
Database queries: Add indexes, use EXPLAIN ANALYZE, fix N+1 queries
Caching: Redis for frequently accessed data (user sessions, product catalog)
Pagination: Limit list endpoints to 50-100 items per page
Compression: gzip middleware for response bodies
Rate limiting: Prevent abuse, protect from DDoS
Red Flags (Premature Optimization):
Caching everything "just in case"
Denormalizing database before profiling queries
Optimizing endpoints with <100 requests/day
Decision Tree
New endpoint?
→ Define contract/schema first, then document
Data model change?
→ Migrate safely, validate with staging data
Deployment?
→ Automate with CI/CD pipeline
Bug found?
→ Add/expand test coverage before fixing
Example
Building a POST /api/v1/orders endpoint end-to-end: validation → service → repository → response.
Patterns applied: /api/v1 versioning, zod boundary validation, service owns business rules, repository abstracts DB, centralized error format.
Edge Cases
Data migration failures: Always implement rollback strategy. Use transactions for multi-step migrations. Test migrations on staging data first.
API versioning and backward compatibility: Maintain old versions until all clients migrate. Document deprecation timeline (e.g., "v1 deprecated 2026-06-01, removed 2026-09-01").
Security edge cases: Validate all inputs to prevent injection attacks. Implement rate limiting per endpoint. Use parameterized queries for SQL. Sanitize user input before logging.
Race conditions: Use database transactions for operations that must be atomic. Implement optimistic locking for concurrent updates. Consider distributed locks for multi-instance deployments.
Large response payloads: Implement pagination for list endpoints. Use streaming for large files. Consider compression (gzip) for response bodies.
Checklist
API endpoints versioned (/api/v1, /api/v2)
Input validation at all boundaries (zod, yup, joi)
Centralized error handling middleware
Environment variables for all configuration
Database migrations tested with rollback
Authentication and authorization on protected routes
Rate limiting implemented on public endpoints
Logging with context (request ID, user ID, timestamp)
API documentation up-to-date (OpenAPI, Swagger)
Unit tests for business logic (>=80% coverage)
Integration tests for critical flows
CI/CD pipeline configured (build, test, deploy)
Health check endpoint (/health, /ping)
Monitoring and alerting configured (errors, performance)