Bird
Raised Fist0
NestJSframework~8 mins

Subscriptions in NestJS - Performance & Optimization

Choose your learning style10 modes available
Performance: Subscriptions
MEDIUM IMPACT
Subscriptions impact the real-time data flow and responsiveness of the application, affecting interaction speed and server-client communication efficiency.
Managing real-time data updates with subscriptions
NestJS
import { Resolver, Subscription, Args } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';

const pubSub = new PubSub();

@Resolver()
export class MessageResolver {
  @Subscription(() => String, {
    filter: (payload, variables) => payload.channelId === variables.channelId,
  })
  messageAdded(@Args('channelId') channelId: string) {
    return pubSub.asyncIterator('messageAdded');
  }
}
Filtering subscription events on the server reduces unnecessary data sent to clients, lowering CPU and network usage.
📈 Performance GainReduces network traffic and CPU load, improving INP and server scalability.
Managing real-time data updates with subscriptions
NestJS
import { Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';

const pubSub = new PubSub();

@Resolver()
export class MessageResolver {
  @Subscription(() => String)
  messageAdded() {
    return pubSub.asyncIterator('messageAdded');
  }
}
Using a single global PubSub instance without filtering causes all clients to receive all events, increasing unnecessary data processing and network traffic.
📉 Performance CostTriggers excessive network traffic and CPU usage on server and clients, increasing INP and server load.
Performance Comparison
PatternDOM OperationsReflowsPaint CostVerdict
Unfiltered global subscriptionN/A0Minimal paint but high JS and network load[X] Bad
Filtered subscription with argsN/A0Minimal paint and reduced JS/network load[OK] Good
Rendering Pipeline
Subscriptions maintain an open connection for real-time updates, affecting the interaction responsiveness stage by pushing data asynchronously without blocking rendering.
→Interaction
→Network
→JavaScript Execution
⚠️ BottleneckNetwork and JavaScript Execution due to continuous event handling
Core Web Vital Affected
INP
Subscriptions impact the real-time data flow and responsiveness of the application, affecting interaction speed and server-client communication efficiency.
Optimization Tips
1Filter subscription events to send only relevant data to clients.
2Unsubscribe clients when they no longer need updates to save resources.
3Avoid heavy processing inside subscription resolvers to keep interaction responsive.
Performance Quiz - 3 Questions
Test your performance knowledge
What is a main performance risk of using unfiltered subscriptions in NestJS?
ASubscriptions increase initial page load time significantly
BClients receive all events, causing unnecessary network and CPU load
CSubscriptions block the main thread during data fetch
DSubscriptions cause layout shifts on the page
DevTools: Network
How to check: Open DevTools, go to Network tab, filter by WebSocket or SSE connections, observe message frequency and size during subscription events.
What to look for: Look for excessive or unnecessary messages sent to clients indicating unfiltered subscriptions causing performance issues.

Practice

(1/5)
1. What is the main purpose of subscriptions in NestJS GraphQL?
easy
A. To perform database migrations
B. To send live updates automatically to clients
C. To handle HTTP GET requests
D. To serve static files

Solution

  1. Step 1: Understand the role of subscriptions

    Subscriptions are designed to push live data updates to clients without the client needing to request repeatedly.
  2. Step 2: Compare with other options

    HTTP GET requests, database migrations, and serving static files are unrelated to live data updates.
  3. Final Answer:

    To send live updates automatically to clients -> Option B
  4. Quick Check:

    Subscriptions = live updates [OK]
Hint: Subscriptions push live data updates automatically [OK]
Common Mistakes:
  • Confusing subscriptions with HTTP request handling
  • Thinking subscriptions manage database tasks
  • Assuming subscriptions serve static content
2. Which decorator is used in NestJS to define a GraphQL subscription method?
easy
A. @Query
B. @Mutation
C. @Subscription
D. @Injectable

Solution

  1. Step 1: Identify the decorator for subscriptions

    The @Subscription decorator marks a method as a GraphQL subscription resolver in NestJS.
  2. Step 2: Differentiate from other decorators

    @Query is for queries, @Mutation for mutations, and @Injectable for services, not subscriptions.
  3. Final Answer:

    @Subscription -> Option C
  4. Quick Check:

    @Subscription decorator = subscriptions [OK]
Hint: Use @Subscription decorator for live data methods [OK]
Common Mistakes:
  • Using @Query or @Mutation instead of @Subscription
  • Confusing @Injectable with subscription decorators
  • Omitting the decorator entirely
3. Given this subscription resolver snippet, what will be the output when a new message is published?
import { Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';

const pubSub = new PubSub();

@Resolver()
export class ChatResolver {
  @Subscription(() => String, {
    resolve: (payload) => `New message: ${payload.text}`,
  })
  messageAdded() {
    return pubSub.asyncIterator('messageAdded');
  }
}

// Somewhere else: pubSub.publish('messageAdded', { text: 'Hello!' });
medium
A. New message: Hello!
B. Hello!
C. messageAdded
D. Error: asyncIterator not found

Solution

  1. Step 1: Understand the subscription resolver

    The resolver listens to 'messageAdded' events and uses the resolve function to format the payload text.
  2. Step 2: Analyze the published payload

    The payload has { text: 'Hello!' }, so the resolve function returns 'New message: Hello!'.
  3. Final Answer:

    New message: Hello! -> Option A
  4. Quick Check:

    Resolve formats payload = 'New message: Hello!' [OK]
Hint: Resolve function formats payload text in subscription [OK]
Common Mistakes:
  • Expecting raw payload without resolve formatting
  • Confusing event name with output
  • Assuming asyncIterator causes error
4. Identify the error in this subscription setup:
import { Resolver, Subscription } from '@nestjs/graphql';
import { PubSub } from 'graphql-subscriptions';

const pubSub = new PubSub();

@Resolver()
export class NotificationResolver {
  @Subscription(() => String)
  newNotification() {
    return pubSub.asyncIterator('newNotification');
  }
}

// Missing pubSub.publish call elsewhere
medium
A. pubSub.asyncIterator called with wrong event name
B. Subscription method missing return statement
C. Incorrect decorator used for subscription
D. No events are published, so no updates sent

Solution

  1. Step 1: Check subscription method correctness

    The method correctly returns pubSub.asyncIterator with the event name.
  2. Step 2: Identify missing event publishing

    No call to pubSub.publish('newNotification', ...) means no events are emitted, so clients receive no updates.
  3. Final Answer:

    No events are published, so no updates sent -> Option D
  4. Quick Check:

    Missing publish call = no updates sent [OK]
Hint: Always publish events to trigger subscription updates [OK]
Common Mistakes:
  • Forgetting to call pubSub.publish
  • Using wrong event name in asyncIterator
  • Omitting return in subscription method
5. You want to create a subscription that only sends updates to clients when the message's author matches their user ID. Which approach correctly implements this filter in NestJS subscriptions? A) Use pubSub.asyncIterator('messageAdded') directly without filtering. B) Use the filter option in the @Subscription decorator to compare payload author and user ID. C) Filter messages inside the resolver method after returning the async iterator. D) Use a separate query instead of subscription to filter messages.
hard
A. Use filter option in @Subscription to send only matching messages
B. Subscribe directly without filtering; client filters messages
C. Filter messages inside resolver after asyncIterator returns
D. Use query instead of subscription for filtering

Solution

  1. Step 1: Understand subscription filtering

    NestJS supports a filter option in the @Subscription decorator to send events selectively based on payload and context.
  2. Step 2: Evaluate options

    The filter option in the @Subscription decorator compares the message author with the client's user ID from context, sending only relevant updates. Subscribing directly without filtering sends all events to clients, filtering after the asyncIterator returns is not the standard approach, and using a query provides no live updates.
  3. Final Answer:

    Use filter option in @Subscription to send only matching messages -> Option A
  4. Quick Check:

    Filter option = selective subscription updates [OK]
Hint: Use @Subscription filter option to send selective updates [OK]
Common Mistakes:
  • Not using filter option and sending all events
  • Trying to filter after asyncIterator returns
  • Using queries instead of subscriptions for live updates
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard