Interview questionsNestJS
NestJS interview questions and answers
30 NestJS questions picked from Codejump's quizzes, from the basics a junior is expected to know to the details that trip up senior candidates. Each one comes with its answer and an explanation — try to answer before you open it.
Junior level NestJS questions
1.What does the value returned from a strategy's
validate()method become?javascriptimport { Injectable } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-jwt'; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { async validate(payload: { sub: string; email: string }): Promise<{ id: string; email: string }> { return { id: payload.sub, email: payload.email }; // -> req.user } }- A.The HTTP response body
- B.The object Passport assigns to req.user
- C.The JWT signing secret
- D.The next middleware
Show answer
Answer: B. The object Passport assigns to req.user
Whatevervalidate()returns becomesrequest.user, available to downstream guards, interceptors, and the route handler. ForJwtStrategy,validate(payload)typically returns a minimal user object derived from the token claims; forLocalStrategy, it returns the authenticated user after checking the password. Returningnull/false(or throwing) signals failed authentication.From the quiz Passport & JWT Basics
2.By default, where does
ConfigModule.forRoot()look for the.envfile?javascriptConfigModule.forRoot({ // Default looks for ./.env relative to process.cwd() envFilePath: '.env', // explicit, same as default });- A.The node_modules/@nestjs/config directory
- B.The user's home directory
- C.The directory set by process.cwd() (the project root from which you start the app)
- D.The compiled dist/ output folder only
Show answer
Answer: C. The directory set by process.cwd() (the project root from which you start the app)
By defaultConfigModuleresolves.envrelative to the current working directory (process.cwd()), which is typically the project root where you runnpm run start. You can override this with theenvFilePathoption. It does not read fromnode_modulesor the home directory, and the working directory is what matters, not where the compiled files live.From the quiz ConfigModule Basics
3.A request comes in as
GET /products?category=books&sort=asc. Which decorator readscategory?javascriptimport { Controller, Get, Query } from '@nestjs/common'; @Controller('products') export class ProductsController { @Get() list(@Query('category') category: string, @Query('sort') sort: string): string { return `category=${category} sort=${sort}`; } }- A.@Query('category')
- B.@Param('category')
- C.@Body('category')
- D.@Req('category')
Show answer
Answer: A. @Query('category')
@Query('category')extracts a single named value from the URL query string. Without an argument,@Query()returns the entire parsed query object (e.g.{ category: 'books', sort: 'asc' }).@Paramis for path segments,@Bodyfor request payloads, and@Reqinjects the raw request object and does not accept a field name like that.From the quiz Routes & Decorators
4.Which decorator maps a normal entity property to a regular database column?
javascriptimport { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity() export class Article { @PrimaryGeneratedColumn() id: number; @Column({ length: 200 }) title: string; @Column({ type: 'text', nullable: true }) body: string | null; }- A.@Field()
- B.@Property()
- C.@ColumnDef()
- D.@Column()
Show answer
Answer: D. @Column()
@Column()maps a property to a table column and accepts options such astype,length,nullable,defaultandunique. Without@Column()(or another column-producing decorator), TypeORM ignores the property entirely.@Field()belongs to GraphQL, and@Property()/@ColumnDef()are not TypeORM decorators.From the quiz TypeORM Basics
5.Which properties does the
@Module()decorator metadata object accept?javascriptimport { Module } from '@nestjs/common'; import { CatsController } from './cats.controller'; import { CatsService } from './cats.service'; @Module({ imports: [], controllers: [CatsController], providers: [CatsService], exports: [CatsService], }) export class CatsModule {}- A.routes, middleware, pipes, filters
- B.dependencies, services, endpoints, globals
- C.imports, controllers, providers, exports
- D.components, directives, pipes, bootstrap
Show answer
Answer: C. imports, controllers, providers, exports
The@Module()decorator takes a metadata object with four main properties:imports(other modules whose exports you need),controllers(request handlers),providers(injectable services), andexports(the subset of this module's providers made available to importing modules). This metadata is what Nest uses to assemble the application graph.From the quiz NestJS Basics
6.Which decorator handles a fire-and-forget event (no response expected)?
javascriptimport { Controller } from '@nestjs/common'; import { EventPattern, Payload } from '@nestjs/microservices'; @Controller() export class UserEventsController { @EventPattern('user.created') handleUserCreated(@Payload() data: { id: string }) { // process asynchronously; nothing returned to producer } }- A.@MessagePattern()
- B.@OnEvent()
- C.@EventPattern()
- D.@Post()
Show answer
Answer: C. @EventPattern()
@EventPattern(pattern)handles events emitted withClientProxy.emit(); the producer does not wait for a reply.@MessagePattern()is request-response.@OnEvent()belongs to the in-process@nestjs/event-emitterpackage, not microservice transports, and@Post()is HTTP. Correct answer: CFrom the quiz Transport & Patterns
7.What does
consumer.apply(LoggerMiddleware).forRoutes('users')do?javascriptconfigure(consumer: MiddlewareConsumer): void { consumer .apply(LoggerMiddleware) .forRoutes('users'); // only /users and its sub-paths }- A.Applies the middleware globally to every route in the app
- B.Applies the middleware to all routes except users
- C.Applies the middleware only to routes whose path starts with users
- D.Registers users as a provider token
Show answer
Answer: C. Applies the middleware only to routes whose path starts with users
forRoutesscopes the middleware to specific paths or controllers. Passing the string'users'binds the middleware to routes under that path. To make it global you would use'*'(or a wildcard pattern depending on the version). To skip routes you useexclude, notforRoutes.From the quiz Middleware & Filters
8.What is a guard's responsibility, and what must its
canActivatereturn?javascriptimport { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class AuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const req = context.switchToHttp().getRequest(); return Boolean(req.headers.authorization); } }- A.Decide whether a request may proceed; return a boolean (or Promise/Observable of one)
- B.Transform input; return the transformed value
- C.Format errors; return an HTTP response
- D.Cache responses; return cached data
Show answer
Answer: A. Decide whether a request may proceed; return a boolean (or Promise/Observable of one)
Guards determine whether the current request is allowed to reach the handler, typically for authentication/authorization. ThecanActivatemethod returnstrueto allow andfalse(or throws) to deny; it may return aboolean,Promise<boolean>, orObservable<boolean>. Returningfalsecauses Nest to throw aForbiddenExceptionby default. Transformation, error formatting, and caching are handled by pipes, filters, and interceptors respectively.From the quiz Pipes, Guards & Interceptors
9.In NestJS terminology, what is a "provider"?
javascript@Module({ providers: [ CatsService, // class provider { provide: 'API_KEY', useValue: 'abc' }, // value provider ], }) export class CatsModule {}- A.Any value (service, factory, repository, constant) that can be injected as a dependency through the DI container
- B.Only a class decorated with @Controller()
- C.A frontend component
- D.An environment variable
Show answer
Answer: A. Any value (service, factory, repository, constant) that can be injected as a dependency through the DI container
A provider is anything that the DI container can create and inject. While the most common provider is an@Injectable()service class, providers also include factory-produced values, plain constants (viauseValue), and aliased implementations. The unifying idea is that a provider is registered under a token and supplied to dependents on request.From the quiz Injectable & DI Basics
10.What does
jest.fn()provide when mocking a dependency's method?javascriptconst repo = { findById: jest.fn().mockResolvedValue({ id: '1' }) }; await service.load('1'); expect(repo.findById).toHaveBeenCalledWith('1');- A.A real implementation copied from the original method
- B.A network stub server
- C.A TypeScript type guard
- D.A mock function that records calls and lets you define return values and assertions
Show answer
Answer: D. A mock function that records calls and lets you define return values and assertions
jest.fn()creates a mock function that tracks how it was called (arguments, call count) and can be configured with return/resolved values, making it ideal for stubbing a collaborator's methods. It carries no real implementation unless you give it one, and it is unrelated to type guards or network servers. You then assert with matchers liketoHaveBeenCalledWith.From the quiz Unit Testing Basics
Mid level NestJS questions
11.What is the idiomatic way to mark certain routes as not requiring authentication when a JWT guard is global?
javascriptimport { SetMetadata } from '@nestjs/common'; export const IS_PUBLIC_KEY = 'isPublic'; export const Public = (): MethodDecorator & ClassDecorator => SetMetadata(IS_PUBLIC_KEY, true); // usage @Public() @Get('health') health(): string { return 'ok'; }- A.Remove the global guard entirely
- B.Wrap the route in middleware
- C.Add @UseFilters(PublicFilter)
- D.Create a @Public() decorator using SetMetadata and have the guard skip routes carrying that metadata
Show answer
Answer: D. Create a @Public() decorator using SetMetadata and have the guard skip routes carrying that metadata
With a globally applied JWT guard, you opt specific routes out by attaching metadata via a custom@Public()decorator built onSetMetadata. The guard reads this metadata withReflectorand returnstrueearly for public routes, skipping token checks. This is cleaner than toggling the guard per controller and keeps the default secure-by-default posture.From the quiz JWT Strategies & RBAC
12.What is the purpose of
ConfigModule.forFeature(myConfig)?javascriptimport databaseConfig from './database.config'; // registerAs('database', ...) @Module({ imports: [ConfigModule.forFeature(databaseConfig)], }) export class DatabaseModule {}- A.It re-initializes the global config and reloads the .env file
- B.It marks the feature module as the only one allowed to read config
- C.It registers a partial/namespaced config (typically a registerAs factory) scoped for injection within a specific feature module
- D.It disables global config for that module
Show answer
Answer: C. It registers a partial/namespaced config (typically a registerAs factory) scoped for injection within a specific feature module
forFeature()registers additional namespaced configuration (usually created withregisterAs) so a feature module can inject its slice of config in a strongly typed way, without re-runningforRoot(). It composes with the global config rather than replacing or disabling it. This keeps feature-specific config close to the feature while still benefiting from the loaded global setup.From the quiz Namespaced Config & Hooks
13.A handler returns a
Promise<User>. What does NestJS do?javascriptimport { Controller, Get, Param } from '@nestjs/common'; import { UsersService } from './users.service'; @Controller('users') export class UsersController { constructor(private readonly users: UsersService) {} @Get(':id') async findOne(@Param('id') id: string) { return await this.users.findOne(id); // resolved value is serialized } }- A.It awaits the promise and serializes the resolved value automatically
- B.It rejects because handlers must be synchronous
- C.It returns the unresolved Promise object to the client
- D.It only works if you also add @Async()
Show answer
Answer: A. It awaits the promise and serializes the resolved value automatically
NestJS handlers natively supportasync/awaitand any thenable. When a handler returns a Promise (or an RxJS Observable), Nest waits for it to resolve and then serializes the resolved value as the response. There is no@Async()decorator. This is why service calls returning promises can be returned directly from controllers.From the quiz Advanced Routing
14.How do you load the
postsrelation when callingfind()without making the relation eager?javascriptawait userRepo.find({ relations: ['posts'] }); // nested object form, also supports deep relations await userRepo.find({ relations: { posts: { comments: true } }, });- A.find({ join: ['posts'] })
- B.find({ with: 'posts' })
- C.find({ include: { posts: true } })
- D.find({ relations: ['posts'] }) (or relations: { posts: true })
Show answer
Answer: D. find({ relations: ['posts'] }) (or relations: { posts: true })
Therelationsoption inFindOptionstells TypeORM which relations to join and hydrate for that particular query, available as an array of paths or as a nested object form.includeis Prisma syntax, not TypeORM, andwith/joinare not validFindOptionskeys for this purpose. Usingrelationsper-query keeps relations off by default while loading them where needed.From the quiz Relations & QueryBuilder
15.What is the effect of marking a module with
@Global()?javascript@Global() @Module({ providers: [ConfigService], exports: [ConfigService], }) export class ConfigModule {}- A.Its providers run in a global server worker thread
- B.Its exported providers become available everywhere without each consumer importing the module, after it is registered once
- C.It disables module encapsulation for the entire application
- D.It makes the module load before main.ts
Show answer
Answer: B. Its exported providers become available everywhere without each consumer importing the module, after it is registered once
@Global()registers a module's exported providers in a global scope so any other module can inject them without importing the module explicitly. The global module must still be imported once (typically in the root module) so Nest registers it. Overusing@Global()is discouraged because it hides dependencies and harms modularity.From the quiz Modules & Sharing
16.What do
@Payload()and@Ctx()extract in a message handler?javascript@EventPattern('user.created') handle(@Payload() data: { id: string }, @Ctx() context: KafkaContext) { const topic = context.getTopic(); // data = message body, context = transport metadata }- A.@Payload() extracts transport metadata; @Ctx() extracts the message body
- B.Both extract the same thing
- C.@Payload() extracts the message data/body; @Ctx() extracts the transport-specific context object (e.g. RmqContext, KafkaContext)
- D.@Ctx() is only for HTTP
Show answer
Answer: C. @Payload() extracts the message data/body; @Ctx() extracts the transport-specific context object (e.g. RmqContext, KafkaContext)
@Payload()gives you the deserialized message data sent by the producer, while@Ctx()gives the transport-specific context (channel, original message, topic/partition, etc.) used for things like manual acknowledgment. They are complementary, not identical, and@Ctx()is a microservices decorator, not HTTP. You can also pass a property key to@Payload('field')to pick a sub-field. Correct answer: CFrom the quiz Redis, RabbitMQ & More
17.When you pass an object to
forRoutes, which shape does theRouteInfouse?javascriptimport { RequestMethod } from '@nestjs/common'; consumer .apply(LoggerMiddleware) .forRoutes({ path: 'cats', method: RequestMethod.POST }); // only POST /cats- A.{ path: string, method: RequestMethod }
- B.{ url: string, verb: string }
- C.{ route: string, type: HttpMethod }
- D.{ pattern: string, http: string }
Show answer
Answer: A. { path: string, method: RequestMethod }
ARouteInfoobject has apath(the route string) and amethodfrom theRequestMethodenum (GET,POST,ALL, etc.). This lets you bind a middleware to a single HTTP verb on a path rather than every verb. The same shape is accepted by bothforRoutesandexclude.From the quiz Custom Middleware
18.A custom guard implements
CanActivate. How does it access the incoming HTTP request?javascriptimport { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; @Injectable() export class TokenGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); return typeof request.headers['x-token'] === 'string'; } }- A.By injecting Request directly into the constructor
- B.By reading process.domain.request
- C.Via context.getRequest() without switching
- D.Via context.switchToHttp().getRequest()
Show answer
Answer: D. Via context.switchToHttp().getRequest()
A guard receives anExecutionContext, which is transport-agnostic. To get the HTTP request you must narrow it withswitchToHttp()and then callgetRequest(). You cant inject the request into a singleton guards constructor (its per-request), and `getRequest()` doesnt exist directly onExecutionContextwithout switching. This pattern keeps guards reusable across transports.From the quiz Custom Pipeline Elements
19.What does
useExistingcreate?javascript@Module({ providers: [ LoggerService, { provide: 'AppLogger', useExisting: LoggerService }, // alias, same instance ], }) export class AppModule {}- A.A brand-new second instance of a provider
- B.An alias token that points to an already-registered provider, so both tokens resolve to the same single instance
- C.A request-scoped copy of a provider
- D.A circular dependency
Show answer
Answer: B. An alias token that points to an already-registered provider, so both tokens resolve to the same single instance
useExistingdefines an alias: a new token that resolves to the same instance as an existing provider. No additional instance is created. It's useful for exposing one provider under multiple tokens — for example offering a stable public token while the implementation is registered under a class.From the quiz Custom Providers
20.In an e2e test, how do you send HTTP requests to the Nest app with supertest?
javascriptimport * as request from 'supertest'; const res = await request(app.getHttpServer()).get('/users').expect(200); expect(res.body).toEqual([]);- A.request(app.listen())
- B.request(app.getHttpServer()).get('/users')
- C.request('http://localhost:3000') always
- D.app.inject({ method: 'GET' }) only works in Nest
Show answer
Answer: B. request(app.getHttpServer()).get('/users')
Afterapp.init(), you passapp.getHttpServer()(the underlying Node HTTP server) to supertest'srequest(), then chain HTTP verbs and assertions without binding a real port.app.listen()returns a promise to a listening app, not a server for supertest, and hardcoding a URL requires the app to actually listen on that port. (app.injectexists for the Fastify adapter, but the supertest pattern is the common Express path.)From the quiz Mocking & E2E Tests
Senior level NestJS questions
21.How does a
jtiblacklist in Redis support refresh token revocation?javascriptasync revoke(jti: string, expSeconds: number): Promise<void> { await redis.set(`bl:${jti}`, '1', 'EX', expSeconds); } async assertNotRevoked(jti: string): Promise<void> { if (await redis.exists(`bl:${jti}`)) throw new UnauthorizedException('Token revoked'); }- A.It stores every valid access token
- B.On rotation/logout, the old refresh token's jti is added to a denylist with a TTL matching its expiry; future use of that jti is rejected
- C.It encrypts the JWT
- D.It rotates the signing secret per request
Show answer
Answer: B. On rotation/logout, the old refresh token's jti is added to a denylist with a TTL matching its expiry; future use of that jti is rejected
Each refresh token carries a uniquejti. When it is rotated or the user logs out, you record thatjtiin a Redis denylist with a TTL equal to the token's remaining lifetime, so it self-cleans. On every refresh you check the denylist first; a hit means the token was revoked or reused, so you reject it (and optionally revoke the whole token family). This adds revocation to otherwise stateless tokens at low cost.From the quiz Advanced Auth Patterns
22.You load
envFilePath: ['.env.local', '.env']AND the variable is also already set in the real shell environment. Which value wins?javascript// Precedence (highest first): // 1) existing process.env (shell/CI) // 2) .env.local (first in array) // 3) .env (later in array)- A..env always wins because it is the base file
- B.The existing real environment variable wins; dotenv does not override variables already present in process.env
- C..env.local wins over the shell environment
- D.A random one of the three is chosen
Show answer
Answer: B. The existing real environment variable wins; dotenv does not override variables already present in process.env
dotenv (used under the hood) never overwrites variables that already exist inprocess.env, so a value injected by the real shell/CI environment takes precedence over any.envfile. Among the files, earlier array entries (.env.local) win over later ones (.env), but none of them override an existing process env var. This is why containerized/12-factor deployments rely on real env vars overriding committed defaults.From the quiz Validation & Shutdown
23.In a module's
configure(consumer), how do you scope middleware to onlyGET /users?javascriptimport { MiddlewareConsumer, NestModule, RequestMethod, Module } from '@nestjs/common'; import { LoggerMiddleware } from './logger.middleware'; @Module({}) export class UsersModule implements NestModule { configure(consumer: MiddlewareConsumer): void { consumer .apply(LoggerMiddleware) .forRoutes({ path: 'users', method: RequestMethod.GET }); } }- A.consumer.apply(LoggerMiddleware).forRoutes('users')
- B.consumer.apply(LoggerMiddleware).forRoutes({ path: 'users', method: RequestMethod.GET })
- C.consumer.use(LoggerMiddleware, '/users')
- D.@UseMiddleware(LoggerMiddleware) on the handler
Show answer
Answer: B. consumer.apply(LoggerMiddleware).forRoutes({ path: 'users', method: RequestMethod.GET })
Middleware is configured in a module implementingNestModuleviaconsumer.apply(...).forRoutes(...). Passing a route object{ path, method }scopes it to a specific path and HTTP method. Passing just'users'(option A) would apply it to all methods on that path. There is noconsumer.use()signature like C, and no@UseMiddlewaredecorator — middleware can't be attached with a method decorator.From the quiz Versioning & Streaming
24.How do you configure and target a second, independently-named database connection?
javascriptTypeOrmModule.forRoot({ name: 'reporting', type: 'postgres', /* ... */ }); @Module({ imports: [TypeOrmModule.forFeature([Stat], 'reporting')] }) export class ReportingModule {} @Injectable() class StatsService { constructor( @InjectRepository(Stat, 'reporting') private stats: Repository<Stat>, ) {} }- A.Call forRoot() once and pass an array of databases
- B.Multiple connections are not supported
- C.Call forRoot({ name: 'reporting', ... }) for the second connection, then use forFeature([X], 'reporting') and @InjectRepository(X, 'reporting')
- D.Use two AppModules
Show answer
Answer: C. Call forRoot({ name: 'reporting', ... }) for the second connection, then use forFeature([X], 'reporting') and @InjectRepository(X, 'reporting')
TypeORM supports multiple connections by giving each a uniquenamein itsforRoot()(the default connection omitsname). To use a non-default connection you must pass that name toforFeature([Entity], 'reporting')and to@InjectRepository(Entity, 'reporting'), otherwise NestJS resolves the default connection's repository. A singleforRoot()does not accept an array of databases, and you never duplicateAppModule.From the quiz Transactions & Advanced
25.What is the lifetime of a default-scoped provider declared in a statically-imported module?
javascript@Injectable() // default DEFAULT scope → one instance app-wide export class CounterService { private count = 0; // shared across all consumers — beware request state inc(): number { return ++this.count; } }- A.One instance per HTTP request
- B.A single instance per application (singleton), instantiated once during bootstrap and reused
- C.A new instance every time it is injected
- D.One instance per controller method call
Show answer
Answer: B. A single instance per application (singleton), instantiated once during bootstrap and reused
Default-scoped (singleton) providers are instantiated once when Nest initializes the module graph at bootstrap, and the same instance is shared for the application's lifetime. This is why singleton providers must avoid storing per-request state. Only non-default scopes (REQUEST,TRANSIENT) change this behavior.From the quiz Dynamic Modules
26.What is the key difference between core NATS and NATS JetStream in a NestJS microservice?
javascript// JetStream-style options enable persistence/acks ClientsModule.register([{ name: 'NATS', transport: Transport.NATS, options: { servers: ['nats://localhost:4222'], jetstream: true }, }]);- A.They are identical
- B.Core NATS persists messages; JetStream does not
- C.Core NATS is at-most-once with no persistence; JetStream adds persistence, replay, and stronger delivery guarantees (acks, durable consumers)
- D.JetStream only supports request-response
Show answer
Answer: C. Core NATS is at-most-once with no persistence; JetStream adds persistence, replay, and stronger delivery guarantees (acks, durable consumers)
Core NATS is a lightweight, in-memory pub/sub with at-most-once delivery — if no subscriber is online, the message is lost. JetStream layers a persistence and streaming engine on top, providing message storage, replay, acknowledgments, and durable consumers for at-least-once semantics. They are not identical, and JetStream supports both pub/sub and request-response patterns. Choose JetStream when you need durability and redelivery. Correct answer: CFrom the quiz gRPC & Kafka
27.A single shared filter must behave differently for HTTP and WebSocket requests. Which call tells you the current transport?
javascriptcatch(exception: unknown, host: ArgumentsHost): void { if (host.getType() === 'http') { const res = host.switchToHttp().getResponse(); // build HTTP response } else if (host.getType() === 'ws') { const client = host.switchToWs().getClient(); // emit WS error } }- A.host.getRequest().protocol
- B.host.switchToHttp().getType()
- C.host.contextName
- D.host.getType() returning 'http', 'ws', or 'rpc'
Show answer
Answer: D. host.getType() returning 'http', 'ws', or 'rpc'
ArgumentsHost.getType()returns the current execution context type as'http','ws', or'rpc'(custom strings are possible for custom transports). You branch on it before narrowing withswitchToHttp/switchToWs/switchToRpc, allowing one filter to support multiple transports safely.From the quiz Filter Hierarchy
28.A
@Roles()decorator is applied at both class and method level. You want the union of all roles. Which Reflector method do you use?javascriptconst roles = this.reflector.getAllAndMerge<string[]>('roles', [ context.getHandler(), context.getClass(), ]); // e.g. class ['user'] + method ['admin'] => ['admin','user']- A.getAllAndMerge([handler, class])
- B.getAllAndOverride([handler, class])
- C.get('roles', handler)
- D.getAll('roles')
Show answer
Answer: A. getAllAndMerge([handler, class])
getAllAndMerge(key, targets)collects the metadata from every target and merges them — concatenating arrays / combining objects — producing the union of class and method roles.getAllAndOverridereturns only the first defined value (the more specific one), discarding the others. Use merge when you want cumulative metadata and override when the most specific should win.From the quiz Execution Order & Scopes
29.What problem do "durable" providers solve?
javascriptimport { Injectable, Scope } from '@nestjs/common'; @Injectable({ scope: Scope.REQUEST, durable: true }) export class TenantConnection {} // Combined with a custom ContextIdStrategy keyed on tenant id, // instances are reused per tenant rather than per request.- A.They allow scoped instances to be shared across requests that belong to the same logical sub-tree (e.g., per tenant) instead of being recreated for every single request
- B.They persist provider instances to disk
- C.They make providers immune to garbage collection
- D.They disable dependency injection caching
Show answer
Answer: A. They allow scoped instances to be shared across requests that belong to the same logical sub-tree (e.g., per tenant) instead of being recreated for every single request
Durable providers optimize the scope-bubbling cost in multi-tenant scenarios. Using aContextIdStrategy, you can key DI sub-trees by something stable (like a tenant ID) so the framework reuses the same scoped instances across many requests sharing that key, rather than rebuilding the request sub-tree every time. The provider is markeddurable: true.From the quiz Scopes & Advanced DI
30.How do you retrieve a
Scope.REQUESTprovider from aTestingModule?javascriptconst service = await moduleRef.resolve(RequestScopedService); expect(service).toBeDefined();- A.moduleRef.get(Service) like any singleton
- B.await moduleRef.resolve(Service), because request/transient-scoped providers aren't singletons and require async resolution per context
- C.You cannot test scoped providers
- D.moduleRef.getRequestScoped(Service)
Show answer
Answer: B. await moduleRef.resolve(Service), because request/transient-scoped providers aren't singletons and require async resolution per context
get()only works for singleton (default-scoped) providers; request- and transient-scoped providers are created per DI context, so you must use the asyncresolve(), optionally with a context id, to obtain an instance. Eachresolve()for transient scope can yield a different instance. Scoped providers are testable; there is nogetRequestScopedmethod.From the quiz Advanced Testing
Practise 1150+ more NestJS questions
Timed quizzes with instant feedback, the questions you miss coming back until they stick, coding challenges and AI mock interviews — free to start.