This repository contains my submission for the Senior Backend Engineer coding challenge. The primary objective was to analyze an existing NestJS codebase, identify architectural weaknesses and performance bottlenecks, and refactor it into a production-ready, scalable, and secure application.
Upon reviewing the initial codebase, I identified several key areas needing immediate attention, as outlined in the evaluation guide:
- Potential N+1 query problems
- Inefficient filtering logic relying on in-memory processing
- Poor separation of concerns between application logic and data access
- Multi-step operations lacked proper transaction management
- Missing robust error handling for distributed systems (e.g., job queueing)
- External service connections (e.g., Redis) were inconsistently managed
- Authorization logic was not scalable
- Some modules bypassed centralized configuration, leading to potential security and performance issues
To address these challenges, I applied several architectural improvements and patterns:
- Interfaces for DI: Defined contracts such as
ITaskRepositoryandIUserRepository - Infrastructure Layer: TypeORM implementations are placed under an
infrastructure/directory (e.g.,TypeOrmTaskRepository) - Benefits:
- Decouples business logic from the ORM
- Improves testability and maintainability
- Future-proofing (e.g., ability to swap ORM)
- Scalable Filtering: All listing methods (e.g.,
TasksService.findAll) usecreateQueryBuilderto push filtering, sorting, and pagination to the database - Atomic Transactions: Critical multi-step operations (e.g., creating a task + enqueueing a job) use manual transactions with
queryRunnerto maintain data integrity
- BullMQ for Background Jobs:
- Used for non-critical operations (e.g., task status updates)
- Jobs configured with exponential backoff retries for fault tolerance
- Scheduled Tasks:
OverdueTasksServiceuses@Cronvia@nestjs/schedule- Periodically checks for overdue tasks and processes them via background jobs
- Config Management:
- All environment variables and service configs handled via
@nestjs/configand.env
- All environment variables and service configs handled via
- Async Module Initialization:
- Used
forRootAsyncforTypeOrmModuleandBullModuleto avoid race conditions during service startup
- Used
- Base URL:
http://localhost:3000 - Swagger Documentation: Available at
http://localhost:3000/api
- RateLimitGuard:
- Could be replaced or refactored to integrate with
@nestjs/throttlerusing Redis-backed storage
- Could be replaced or refactored to integrate with
- CacheService:
- Current custom implementation created Redis clients too early (before env loading, which was causing issue with docker container)
- Thinking of replacing with
@nestjs/cache-manager+cache-manager-redis-store
- Expand test coverage:
- Add more E2E tests to cover request/response cycles
- Increase unit tests at controller level
This refactor transforms the original codebase into a robust, maintainable, and scalable production-grade application. The improvements ensure efficient database usage, clear architectural boundaries, and enhanced operational resilience.
Thank you for reviewing this submission!