NestJS Case Studies & Practical Application 3 — Questions and Answers
Question 1: A NestJS app under load shows high memory usage. Profiling reveals many request-scoped providers are never destroyed. What is the most likely cause?
- The REQUEST-scoped providers are injected into singleton-scoped providers, preventing their destruction (Correct answer)
- Request-scoped providers are always leaked in NestJS
- The DI container has a memory limit configuration that is too low
- Using @Injectable({ scope: Scope.REQUEST }) opts out of garbage collection
Correct answer: The REQUEST-scoped providers are injected into singleton-scoped providers, preventing their destruction
When a REQUEST-scoped provider is injected into a SINGLETON, NestJS keeps a singleton instance alive holding a reference, preventing cleanup.
Question 2: You need to validate nested objects in a DTO using class-validator. A CreateOrderDto has an items array of OrderItemDto. Which decorator combination ensures items are also validated?
- @ValidateNested({ each: true }) combined with @Type(() => OrderItemDto) (Correct answer)
- @IsArray() on the items field alone
- @Validate(OrderItemDto) on the class
- @ArrayMinSize(1) with @IsObject() on each element
Correct answer: @ValidateNested({ each: true }) combined with @Type(() => OrderItemDto)
@ValidateNested triggers recursive validation and @Type tells class-transformer which class to instantiate for nested objects.
Question 3: A NestJS GraphQL API must enforce field-level authorization so some fields are only visible to admins. What is the most scalable approach?
- Use a custom FieldMiddleware from @nestjs/graphql that checks the user role per field (Correct answer)
- Add if (user.role !== 'admin') throw inside every resolver method
- Create separate GraphQL schemas for admin and non-admin users
- Use @UseGuards on the Query resolver and filter inside the service
Correct answer: Use a custom FieldMiddleware from @nestjs/graphql that checks the user role per field
Field middleware in NestJS GraphQL runs per field with the execution context, enabling reusable declarative field-level access control.
Question 4: Your NestJS app connects to RabbitMQ via @nestjs/microservices. Under high load, messages accumulate faster than they are processed. What configuration change reduces back-pressure?
- Set prefetchCount on the RMQ transport options to limit in-flight messages per consumer (Correct answer)
- Increase the RabbitMQ queue TTL
- Scale the database connections instead
- Disable message acknowledgment to speed up throughput
Correct answer: Set prefetchCount on the RMQ transport options to limit in-flight messages per consumer
prefetchCount tells RabbitMQ how many unacknowledged messages to deliver per channel, preventing the consumer from being overwhelmed.
Question 5: A NestJS app using TypeORM needs to run a database migration before tests in a CI pipeline. What is the correct approach?
- Run typeorm migration:run against the test database connection before the test suite starts (Correct answer)
- Use synchronize: true in TypeORM config for CI to auto-apply schema
- Manually create tables in the test setup file with raw SQL
- Skip migrations in CI and rely on entity sync instead
Correct answer: Run typeorm migration:run against the test database connection before the test suite starts
Running actual migrations in CI ensures tests execute against a schema matching production, catching migration-related regressions early.
Question 6: You are building a real-time collaborative editing feature in NestJS. Which combination best handles presence (who is online) and document changes?
- WebSockets via @WebSocketGateway for document changes and Redis pub/sub for cross-instance presence (Correct answer)
- HTTP polling every 500ms for both presence and changes
- Server-Sent Events for document changes and REST for presence
- GraphQL subscriptions over HTTP/2 with no additional broker
Correct answer: WebSockets via @WebSocketGateway for document changes and Redis pub/sub for cross-instance presence
WebSockets provide low-latency bidirectional channels; Redis pub/sub synchronizes presence state across multiple NestJS instances.
Question 7: A developer adds app.useGlobalInterceptors(new LoggingInterceptor()) in main.ts. Later, a module also registers LoggingInterceptor via APP_INTERCEPTOR. What happens?
- Both registrations are active and the interceptor runs twice per request (Correct answer)
- The module registration overrides the global one
- The global registration takes precedence and the module one is ignored
- NestJS throws a DuplicateInterceptorException at startup
Correct answer: Both registrations are active and the interceptor runs twice per request
NestJS treats useGlobalInterceptors and APP_INTERCEPTOR as two independent lists, so both execute, doubling the interceptor invocations.
A NestJS app under load shows high memory usage.
Profiling reveals many request-scoped providers are never destroyed.
What is the most likely cause?