| name | backend |
| description | NestJS backend development patterns for the RedisInsight API: module structure, services, controllers, DTOs, dependency injection, and error handling. Use when editing any file under redisinsight/api/**, writing or modifying NestJS modules, controllers, services, DTOs, providers, or when the user mentions the backend, API, or NestJS. |
Backend Development (NestJS/API)
Module Structure
NestJS Architecture
- Follow modular architecture (feature-based modules)
- Use dependency injection throughout
- Separate concerns: Controllers, Services, Repositories
- Use DTOs for validation and data transfer
- Apply proper error handling with NestJS exceptions
Module Folder Structure
Each feature module in its own directory under api/src/:
feature/
āāā feature.module.ts # Module definition
āāā feature.controller.ts # REST endpoints
āāā feature.service.ts # Business logic
āāā feature.service.spec.ts # Service tests
āāā feature.controller.spec.ts # Controller tests
āāā feature.types.ts # Interfaces and types related to the feature
āāā dto/ # Data transfer objects
ā āāā create-feature.dto.ts
ā āāā update-feature.dto.ts
ā āāā feature.dto.ts
āāā entities/ # TypeORM entities
āāā repositories/ # Custom repositories
āāā exceptions/ # Custom exceptions
āāā guards/ # Feature-specific guards
āāā decorators/ # Custom decorators
āāā constants/ # Feature constants
File Naming
- Modules:
feature.module.ts
- Controllers:
feature.controller.ts
- Services:
feature.service.ts
- DTOs:
create-feature.dto.ts, update-feature.dto.ts
- Entities:
feature.entity.ts
- Interfaces and types:
feature.types.ts
- Tests:
feature.service.spec.ts
- Constants:
feature.constants.ts
- Exceptions:
feature-not-found.exception.ts
Constants Organization
Store feature-specific constants in dedicated constants file:
export const FEATURE_CONSTANTS = {
MAX_NAME_LENGTH: 100,
DEFAULT_PAGE_SIZE: 20,
} as const;
export const FEATURE_ERROR_MESSAGES = {
NOT_FOUND: 'Feature not found',
INVALID_INPUT: 'Invalid feature data',
} as const;
Imports Order
- Node.js built-in modules
- External dependencies (
@nestjs/*, etc.)
- Internal modules (using
src/* alias ā the backend's self-reference into redisinsight/api/src/*)
- Local relative imports
Service Layer
Service Pattern
- Inject dependencies via constructor
- Use TypeORM repositories
- Handle errors with NestJS exceptions
- Use Logger for important operations
- Keep business logic in services (not controllers)
Dependency Injection
Always inject dependencies via constructor with proper decorators:
@Injectable()
export class UserService {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
private readonly emailService: EmailService,
) {}
}
Controller Layer
Controller Pattern
- Keep controllers thin (delegate to services)
- Use proper HTTP decorators (
@Get, @Post, etc.)
- Use
@Body, @Param, @Query for inputs
- Apply guards with
@UseGuards()
- Document with Swagger decorators
HTTP Status Codes
- Use
@HttpCode() decorator for non-standard codes
- Return appropriate status codes (200, 201, 204, 400, 404, etc.)
Data Transfer Objects (DTOs)
Validation
Use class-validator decorators for validation:
@IsString(), @IsNumber(), @IsEmail()
@IsNotEmpty(), @IsOptional()
@MinLength(), @MaxLength()
@Min(), @Max()
Swagger Documentation
Use @ApiProperty() and @ApiPropertyOptional() for Swagger docs.
Error Handling
NestJS Exceptions
Use appropriate exception types:
NotFoundException - 404
BadRequestException - 400
UnauthorizedException - 401
ForbiddenException - 403
ConflictException - 409
InternalServerErrorException - 500
Custom Exceptions
Prefer custom exceptions over generic ones when you need:
- Consistent error codes for frontend handling
- Specific error messages from constants
- Consistent error structure across the codebase
Create custom exceptions following existing patterns:
import {
HttpException,
HttpExceptionOptions,
HttpStatus,
} from '@nestjs/common';
import ERROR_MESSAGES from 'src/constants/error-messages';
import { CustomErrorCodes } from 'src/constants';
export class FeatureInvalidException extends HttpException {
constructor(
message = ERROR_MESSAGES.FEATURE_INVALID,
options?: HttpExceptionOptions,
) {
const response = {
message,
statusCode: HttpStatus.BAD_REQUEST,
error: 'FeatureInvalid',
errorCode: CustomErrorCodes.FeatureInvalid,
};
super(response, response.statusCode, options);
}
}
Error Logging
private readonly logger = new Logger(ServiceName.name)
this.logger.error('Error message', error.stack, { context })
Redis Integration
Redis Service Pattern
- Use RedisClient from
src/modules/redis
- Handle errors gracefully
- Log Redis operations
- Use try-catch for error handling
Code Quality
Cognitive Complexity (⤠15)
- Use early returns to reduce nesting
- Extract complex logic to separate functions
- Avoid deeply nested conditions
No Duplicate Strings
Extract repeated strings to constants in constants file.
API Documentation (Swagger)
Required Decorators
@ApiTags() - Group endpoints
@ApiOperation() - Describe operation
@ApiResponse() - Document responses
@ApiParam() - Document params
@ApiQuery() - Document query params
@ApiBearerAuth() - Auth requirement
Checklist