RideMe is a ride-hailing platform backend I built with NestJS and TypeScript. It supports 5,000 concurrent users with sub-200ms latency, real-time driver matching, and a modular architecture. The Challenge The goal was a backend that could: Handle 5,000 concurrent active riders Maintain P95 latency under 200ms Support real-time driver matching and location tracking Process payments securely Scale horizontally without major refactoring Remain cost-effective and self-hostable Architecture & Technology Stack The system uses a monolithic-but-modular NestJS architecture with clear module boundaries. Core Technologies: NestJS 10+ : TypeScript framework with dependency injection and modular design PostgreSQL 15+ with PostGIS : Geospatial queries for driver location and route calculations Prisma ORM : Type-safe database access with strong migration tooling Redis 7+ : Caching and session management with geohash support for nearby driver queries BullMQ : Background job processing for trip matching and notifications WebSocket Gateway : Real-time updates using Socket.io with Redis adapter for horizontal scaling Why This Stack? PostgreSQL with PostGIS provides native geospatial operations (distance calculations, contains queries) without external services. Prisma offers type safety and solid migration workflows. Redis handles caching, sessions, and geohash indexes for driver locations. BullMQ provides retry logic and priority queues for critical operations like trip matching. Modular Architecture The backend is organized into focused modules: Auth Module : OTP-based registration, JWT authentication with access/refresh tokens, password reset flows, and role-based access control (user, driver, admin). Trip Module : Trip lifecycle management from creation to completion, multi-stop trip support, driver matching algorithm, trip cancellation with retry logic, and rating/review system. Geolocation Module : Geo data storage and retrieval, driver location tracking with debounced updates, nearby driver queries using geohash, address geocoding via Google Maps, and route calculation with polyline generation. Payment Module : Integration with Paystack and Stripe, payment status tracking, refund processing, driver payout management, and transaction history. Driver Module : Profile management, vehicle registration, license management, availability status tracking, and earnings/payout tracking. Notification Module : Push notifications via Firebase Cloud Messaging, notification templates, delivery status tracking, and bulk notifications. Admin Module : Dashboard analytics, user/driver management, trip oversight, and system configuration. Performance Optimizations Database Optimizations: Composite indexes on common query patterns ( [status, createdAt] for trips, [driverId, status] for driver queries) N+1 query prevention using Prisma's include and batch queries Query result caching with appropriate TTLs (1 hour for profiles, 5 minutes for trip estimates) Caching Strategy: Redis cache-aside pattern with 80%+ hit rate target Geohash-based driver location caching (30-second TTL) Static data caching (vehicle makes/models: 24-hour TTL) Dashboard analytics caching (5-minute TTL) Response Optimizations: Gzip compression reducing response sizes by 60-80% Data minimization using Prisma select to return only needed fields Pagination for all list endpoints Performance interceptor logging slow requests (>1000ms) Load Testing: Comprehensive k6 load tests validate: 500 RPS sustained load 1000 RPS peak load 5000 concurrent users All scenarios maintain P95 latency < 200ms Real-Time Driver Matching The matching system uses: Geohash Indexing : Driver locations stored in Redis using geohash for efficient nearby queries Debounced Updates : Location updates debounced (30 seconds or >100m movement) to reduce database writes Priority Queue : Trip matching jobs processed with high priority in BullMQ WebSocket Broadcasting : Real-time trip assignments broadcast to nearby drivers Fallback Mechanisms : Retry logic if no drivers accept within timeout Security Architecture Authentication & Authorization: JWT tokens with 15-minute access tokens and 7-day refresh tokens Separate admin authentication system Role-based guards (JwtAuthGuard, AdminAuthGuard, AdminRoleGuard) Password hashing with bcrypt (cost factor 10) API Security: Input validation using class-validator on all DTOs SQL injection prevention via Prisma's parameterized queries Rate limiting (configurable per endpoint) CORS configuration for production domains Security headers (X-Frame-Options, CSP, HSTS) Data Protection: Passwords never stored in plain text or returned in responses Sensitive data excluded from queries using Prisma select GDPR compliance with user deletion request tracking PCI DSS compliance via secure payment providers (no card storage) Migration from PHP/Laravel The backend was rebuilt from a PHP/Laravel implementation with: API Compatibility : Maintained endpoint compatibility for seamless frontend integration Dual-Write Strategy : Parallel writes during migration phase for data consistency Gradual Rollout : Incremental traffic shifting with easy rollback capability Zero Downtime : Users experienced no service interruption during migration Developer Experience Type Safety : Full TypeScript coverage with Prisma-generated types ensuring compile-time safety. Testing : Comprehensive test suite with Jest for unit tests and Supertest for E2E tests, achieving high coverage. Documentation : Swagger UI at /api-docs , comprehensive architecture docs, API mapping guides, and deployment documentation. Code Quality : ESLint + Prettier, Husky pre-commit hooks, and structured logging with Pino. Scalability Considerations Horizontal Scaling: Stateless API instances sharing Redis for sessions/cache WebSocket scaling via Redis adapter enabling multi-instance support Separate worker processes for background jobs Database read replicas for analytics queries Future Microservices Path: The modular architecture allows extraction into microservices if needed: Trip Service (trip module + matching logic) Driver Service (driver module + location tracking) Payment Service (payment module + provider integrations) Notification Service (notification module + FCM) Results & Impact The new backend delivers: Performance : P95 latency consistently under 200ms under load Scalability : Handles 5,000+ concurrent users with room to grow Reliability : Comprehensive error handling, retry logic, and failure-safe flows Maintainability : Clean module boundaries, type safety, and comprehensive documentation Cost Efficiency : Self-hostable stack using free/open-source technologies Lessons Learned Geospatial Queries : PostGIS is essential for location-based applications—native distance calculations outperform application-level solutions. Caching Strategy : Appropriate TTLs and cache invalidation are critical—80%+ hit rates significantly reduce database load. Type Safety : TypeScript + Prisma catches errors at compile time, reducing production bugs. Modular Design : Clear module boundaries make the codebase maintainable and enable future microservices extraction. Load Testing Early : Identifying bottlenecks before production prevents performance issues. Conclusion The RideMe backend demonstrates that modern TypeScript frameworks like NestJS can deliver high-performance, scalable systems. By combining PostgreSQL's geospatial capabilities, Redis for caching, and a modular architecture, we built a system that handles thousands of concurrent users while maintaining sub-200ms latency. The architecture prioritizes developer experience, maintainability, and cost-effectiveness—proving that you don't need expensive cloud services to build production-grade ride-hailing infrastructure. The modular design ensures the system can evolve as requirements grow, whether that means adding features or extracting microservices. For developers building similar real-time, location-based applications, the key takeaways are: invest in proper geospatial database support, implement aggressive caching strategies, prioritize type safety, and design for horizontal scaling from day one. Built with NestJS, PostgreSQL, Redis, and TypeScript. Open to questions and discussions about architecture decisions, performance optimizations, or implementation details.