Isaac.

web

GraphQL Subscriptions

Implement real-time data streaming with GraphQL subscriptions.

By Emem IsaacApril 19, 20233 min read
#graphql#subscriptions#real-time#websockets
Share:

A Simple Analogy

GraphQL subscriptions are like a news feed. Instead of constantly asking for updates, you subscribe and get notifications when new content arrives.


Why Subscriptions?

  • Real-time: Push data instantly
  • Efficient: Only send changed data
  • Bidirectional: Client and server communicate
  • Scalable: WebSocket-based
  • Reactive: Respond to events

Schema Definition

type Subscription {
  orderCreated: Order!
  orderUpdated(id: ID!): Order!
  messageReceived(chatId: ID!): Message!
  stockPriceChanged(symbol: String!): StockPrice!
}

type Order {
  id: ID!
  customerId: String!
  total: Float!
  status: OrderStatus!
  createdAt: String!
}

enum OrderStatus {
  PENDING
  CONFIRMED
  SHIPPED
  DELIVERED
}

Server Implementation

using HotChocolate;
using HotChocolate.Execution.Configuration;
using HotChocolate.Subscriptions;

public class Subscription
{
    [Subscribe]
    [Topic("OrderCreated")]
    public Order OnOrderCreated(
        [EventMessage] Order order) => order;
    
    [Subscribe(With = nameof(SubscribeToOrderUpdates))]
    public Order OnOrderUpdated(
        string id,
        [EventMessage] Order order) => order;
    
    public IAsyncEnumerable<Order> SubscribeToOrderUpdates(
        string id,
        [Service] ITopicEventReceiver receiver) =>
        receiver.ReceiveAsync<Order>($"orderUpdated_{id}");
}

public class OrderMutations
{
    public async Task<Order> CreateOrder(
        CreateOrderInput input,
        [Service] ITopicEventSender eventSender)
    {
        var order = new Order { /* ... */ };
        
        // Publish to subscribers
        await eventSender.SendAsync("OrderCreated", order);
        
        return order;
    }
}

Client Subscription

import { useSubscription, gql } from "@apollo/client";

const ORDER_CREATED_SUBSCRIPTION = gql`
  subscription OnOrderCreated {
    orderCreated {
      id
      customerId
      total
      status
      createdAt
    }
  }
`;

function OrderNotifications() {
  const { data, loading, error } = useSubscription(ORDER_CREATED_SUBSCRIPTION);
  
  if (loading) return <div>Waiting for orders...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <div>
      <h3>New Order</h3>
      <p>Order #{data.orderCreated.id}</p>
      <p>Total: ${data.orderCreated.total}</p>
      <p>Status: {data.orderCreated.status}</p>
    </div>
  );
}

WebSocket Configuration

builder.Services
    .AddGraphQLServer()
    .AddQueryType<Query>()
    .AddMutationType<Mutation>()
    .AddSubscriptionType<Subscription>()
    .AddInMemorySubscriptions()
    .AddWebSocketProtocol();

app.UseWebSockets();
app.MapGraphQL("/graphql");

Broadcasting Events

public class OrderService
{
    private readonly ITopicEventSender _eventSender;
    
    public OrderService(ITopicEventSender eventSender)
    {
        _eventSender = eventSender;
    }
    
    public async Task<Order> CreateOrderAsync(CreateOrderInput input)
    {
        var order = new Order { /* ... */ };
        
        // Broadcast to all subscribers of "OrderCreated"
        await _eventSender.SendAsync("OrderCreated", order);
        
        return order;
    }
    
    public async Task<Order> UpdateOrderAsync(string id, UpdateOrderInput input)
    {
        var order = new Order { /* ... */ };
        
        // Broadcast to specific order subscribers
        await _eventSender.SendAsync($"orderUpdated_{id}", order);
        
        return order;
    }
}

Best Practices

  1. Filter subscriptions: Only needed data
  2. Scalability: Use Redis for distributed systems
  3. Connection limits: Manage active subscriptions
  4. Error handling: Graceful disconnection
  5. Security: Authenticate subscription requests

Related Concepts

  • WebSocket protocols
  • Server-sent events (SSE)
  • Redis pub/sub
  • Message queues

Summary

GraphQL subscriptions provide real-time, bidirectional communication between client and server. Use them for notifications, live updates, and collaborative features.

Share:

Written by Emem Isaac

Expert Software Engineer with 15+ years of experience building scalable enterprise applications. Specialized in ASP.NET Core, Azure, Docker, and modern web development. Passionate about sharing knowledge and helping developers grow.

Ready to Build Something Amazing?

Let's discuss your project and explore how my expertise can help you achieve your goals. Free consultation available.

💼 Trusted by 50+ companies worldwide | ⚡ Average response time: 24 hours