GraphQL Subscriptions with WebSocket

fullstack
TypeScript
architecture
corporate_pm
Remix

Implement real-time GraphQL subscriptions using WebSocket for live data updates.

12/8/2025

Prompt

Generate a production-ready GraphQL API with real-time subscriptions using WebSocket for live data updates with the following requirements:

Application Overview

Platform Details

  • GraphQL Server: [Apollo Server / GraphQL Yoga / Mercurius / Hasura / Custom]
  • WebSocket Library: [graphql-ws / subscriptions-transport-ws / Socket.io]
  • PubSub: [In-memory / Redis / Google PubSub / AWS SNS / Kafka]
  • Frontend Framework: [React / Next.js / Vue / Svelte / React Native]
  • Database: [PostgreSQL / MongoDB / MySQL / Supabase / Prisma]
  • Authentication: [JWT / Session / OAuth / Custom]

Real-Time Features

  • Subscription Types: [Chat messages / Notifications / Live updates / Data changes]
  • Filtering: [User-specific / Room-based / Custom filters]
  • Scalability: [Single server / Distributed / Serverless]

GraphQL Schema Design

Types

Type 1: [TypeName, e.g., Message]

type Message {
  id: ID!
  userId: ID!
  user: User!
  text: String!
  roomId: ID!
  createdAt: DateTime!
  updatedAt: DateTime
}

Type 2: [TypeName, e.g., User]

type User {
  id: ID!
  username: String!
  email: String!
  avatar: String
  status: UserStatus!
  lastSeen: DateTime
}

Type 3: [TypeName, e.g., Notification]

type Notification {
  id: ID!
  userId: ID!
  type: NotificationType!
  title: String!
  message: String!
  read: Boolean!
  createdAt: DateTime!
}

[Define 3-8 types]

Queries

Query 1: [QueryName, e.g., messages]

messages(roomId: ID!, limit: Int, offset: Int): [Message!]!
  • Purpose: [Fetch message history for a room]
  • Arguments: [roomId, limit, offset]
  • Returns: [Array of messages]
  • Authentication: [Required / Optional]

Query 2: [QueryName, e.g., user]

user(id: ID!): User
  • Purpose: [Fetch user by ID]
  • Arguments: [id]
  • Returns: [User or null]
  • Authentication: [Required / Optional]

[Define 5-15 queries]

Mutations

Mutation 1: [MutationName, e.g., sendMessage]

sendMessage(roomId: ID!, text: String!): Message!
  • Purpose: [Send a new message to a room]
  • Arguments: [roomId, text]
  • Returns: [Created message]
  • Side Effects: [Publish to MESSAGE_ADDED subscription]
  • Authentication: [Required]
  • Validation: [Text length, room access]

Mutation 2: [MutationName, e.g., updateUserStatus]

updateUserStatus(status: UserStatus!): User!
  • Purpose: [Update user online status]
  • Arguments: [status]
  • Returns: [Updated user]
  • Side Effects: [Publish to USER_STATUS_CHANGED]
  • Authentication: [Required]

[Define 5-15 mutations]

Subscriptions

Subscription 1: [SubscriptionName, e.g., messageAdded]

messageAdded(roomId: ID!): Message!
  • Purpose: [Subscribe to new messages in a room]
  • Arguments: [roomId]
  • Returns: [New message when published]
  • Trigger: [When sendMessage mutation is called]
  • Filtering: [Only messages for specified roomId]
  • Authentication: [Required]

Subscription 2: [SubscriptionName, e.g., userStatusChanged]

userStatusChanged(userId: ID): User!
  • Purpose: [Subscribe to user status changes]
  • Arguments: [userId (optional, all users if not specified)]
  • Returns: [Updated user]
  • Trigger: [When updateUserStatus mutation is called]
  • Filtering: [By userId if provided]
  • Authentication: [Required]

Subscription 3: [SubscriptionName, e.g., notificationReceived]

notificationReceived: Notification!
  • Purpose: [Subscribe to user-specific notifications]
  • Arguments: [None (uses authenticated user)]
  • Returns: [New notification]
  • Trigger: [When notification is created for user]
  • Filtering: [Only for authenticated user]
  • Authentication: [Required]

[Define 3-10 subscriptions]

PubSub Events

Event 1: [EventName, e.g., MESSAGE_ADDED]

  • Trigger: [sendMessage mutation]
  • Payload: [{ messageAdded: Message }]
  • Subscribers: [messageAdded subscription]
  • Filtering: [By roomId]

Event 2: [EventName, e.g., USER_STATUS_CHANGED]

  • Trigger: [updateUserStatus mutation]
  • Payload: [{ userStatusChanged: User }]
  • Subscribers: [userStatusChanged subscription]
  • Filtering: [By userId (optional)]

Event 3: [EventName, e.g., NOTIFICATION_CREATED]

  • Trigger: [createNotification mutation or system event]
  • Payload: [{ notificationReceived: Notification }]
  • Subscribers: [notificationReceived subscription]
  • Filtering: [By userId (authenticated user)]

[Define 3-10 events]

Server Implementation

GraphQL Server Setup

Apollo Server Configuration

  • Port: [4000 / 3000 / Custom]
  • Path: [/graphql / /api/graphql]
  • CORS: [Allowed origins]
  • Introspection: [Enabled in dev / Disabled in prod]
  • Playground: [Enabled in dev / Disabled in prod]

WebSocket Server

  • Path: [/graphql / /subscriptions]
  • Protocol: [graphql-ws / subscriptions-transport-ws]
  • Connection Params: [Authentication token]
  • Keep Alive: [Ping interval]

PubSub Implementation

PubSub Type

  • In-Memory: [For development / single server]
  • Redis: [For production / distributed]
  • Google Cloud PubSub: [For GCP deployments]
  • AWS SNS/SQS: [For AWS deployments]
  • Kafka: [For high-throughput systems]

Redis PubSub (if Redis)

import { RedisPubSub } from "graphql-redis-subscriptions"
import Redis from "ioredis"

const options = {
  host: process.env.REDIS_HOST,
  port: process.env.REDIS_PORT,
  retryStrategy: times => Math.min(times * 50, 2000)
}

const pubsub = new RedisPubSub({
  publisher: new Redis(options),
  subscriber: new Redis(options)
})

Resolvers

Query Resolvers

  • Data Fetching: [From database / cache / external API]
  • Authentication: [Check auth context]
  • Authorization: [Check permissions]
  • Error Handling: [GraphQL errors with codes]

Mutation Resolvers

  • Input Validation: [Validate arguments]
  • Business Logic: [Perform operation]
  • Database Update: [Save to database]
  • PubSub Publish: [Publish event for subscriptions]
  • Return Value: [Return created/updated entity]

Subscription Resolvers

  • Subscribe Function: [Return AsyncIterator from PubSub]
  • Filtering: [withFilter for conditional delivery]
  • Authentication: [Check auth in context]
  • Cleanup: [Unsubscribe on disconnect]

Authentication

Connection Authentication

  • Method: [JWT in connection params / Cookie / Custom]
  • Validation: [Verify token on WebSocket connection]
  • Context: [Add user to context for resolvers]

Resolver Authentication

  • Query/Mutation: [Check context.user in resolver]
  • Subscription: [Check context.user in subscribe function]
  • Error: [Throw AuthenticationError if not authenticated]

Filtering and Authorization

Subscription Filtering

{
  subscribe: withFilter(
    () => pubsub.asyncIterator(["MESSAGE_ADDED"]),
    (payload, variables, context) => {
      // Filter by roomId
      if (payload.messageAdded.roomId !== variables.roomId) {
        return false
      }
      
      // Check if user has access to room
      return hasRoomAccess(context.user.id, variables.roomId)
    }
  )
}

Authorization Checks

  • Room Access: [Check if user is member of room]
  • User Permissions: [Check user role/permissions]
  • Data Ownership: [Check if user owns the data]

Client Implementation

Apollo Client Setup

HTTP Link

  • URI: [http://localhost:4000/graphql]
  • Headers: [Authorization, custom headers]
  • Credentials: [include / same-origin]

WebSocket Link

  • URI: [ws://localhost:4000/graphql]
  • Connection Params: [{ authToken: token }]
  • Reconnect: [Automatic reconnection]
  • Lazy: [Connect only when subscription is active]

Split Link

  • Logic: [Route subscriptions to WebSocket, queries/mutations to HTTP]
  • Implementation: [Use split from @apollo/client]

React Hooks

useSubscription Hook

const { data, loading, error } = useSubscription(MESSAGE_SUBSCRIPTION, {
  variables: { roomId },
  onSubscriptionData: ({ subscriptionData }) => {
    // Handle new data
  }
})

useQuery with Subscription Updates

const { data, subscribeToMore } = useQuery(MESSAGES_QUERY, {
  variables: { roomId }
})

useEffect(() => {
  const unsubscribe = subscribeToMore({
    document: MESSAGE_SUBSCRIPTION,
    variables: { roomId },
    updateQuery: (prev, { subscriptionData }) => {
      if (!subscriptionData.data) return prev
      const newMessage = subscriptionData.data.messageAdded
      return {
        messages: [...prev.messages, newMessage]
      }
    }
  })
  
  return () => unsubscribe()
}, [roomId])

UI Components

Component 1: [ComponentName, e.g., ChatRoom]

  • Subscriptions: [messageAdded]
  • Queries: [messages]
  • Mutations: [sendMessage]
  • Features: [Real-time message updates, send messages]

Component 2: [ComponentName, e.g., UserStatus]

  • Subscriptions: [userStatusChanged]
  • Queries: [user]
  • Features: [Show real-time user status]

Component 3: [ComponentName, e.g., NotificationBell]

  • Subscriptions: [notificationReceived]
  • Queries: [notifications]
  • Mutations: [markAsRead]
  • Features: [Real-time notification badge, notification list]

Advanced Features

Subscription Batching

  • Purpose: [Reduce number of events sent]
  • Implementation: [Batch multiple events into one]
  • Interval: [100ms / 500ms / Custom]

Subscription Throttling

  • Purpose: [Limit event frequency]
  • Implementation: [Throttle events per subscriber]
  • Rate: [Max X events per second]

Optimistic Updates

  • Purpose: [Instant UI feedback]
  • Implementation: [Update cache optimistically before mutation completes]
  • Rollback: [Revert on error]

Cache Updates

  • Subscription Data: [Update Apollo cache with subscription data]
  • Normalization: [Ensure proper cache normalization]
  • Eviction: [Remove stale data from cache]

Performance & Scalability

Connection Management

  • Max Connections: [Per server / Per user]
  • Connection Pooling: [Reuse connections]
  • Idle Timeout: [Close inactive connections]

Horizontal Scaling

  • Load Balancer: [Distribute WebSocket connections]
  • Sticky Sessions: [Route user to same server]
  • Redis PubSub: [Share events across servers]

Monitoring

  • Metrics:
    • Active subscriptions count
    • Events published per second
    • WebSocket connections
    • Subscription errors
  • Logging: [Log subscription lifecycle events]
  • Alerts: [Alert on high error rate or connection issues]

Code Generation Requirements

Generate a complete GraphQL API with subscriptions including:

  1. GraphQL Schema:

    • Type definitions for all entities
    • Query definitions
    • Mutation definitions
    • Subscription definitions
    • Input types and enums
  2. GraphQL Server:

    • Apollo Server setup with Express
    • WebSocket server configuration
    • Schema creation with makeExecutableSchema
    • Server startup and configuration
  3. PubSub Setup:

    • PubSub instance (in-memory or Redis)
    • Event constants
    • Publish helper functions
  4. Resolvers:

    • Query resolvers with data fetching
    • Mutation resolvers with PubSub publish
    • Subscription resolvers with filtering
    • Authentication checks
    • Error handling
  5. Authentication:

    • WebSocket connection authentication
    • Context creation with user
    • Auth middleware for resolvers
    • Token validation
  6. Client Setup:

    • Apollo Client configuration
    • HTTP Link setup
    • WebSocket Link setup
    • Split Link implementation
    • Cache configuration
  7. React Hooks & Components:

    • useSubscription examples
    • useQuery with subscribeToMore
    • UI components using subscriptions
    • Optimistic updates
  8. Database Integration:

    • Database models/schema
    • CRUD operations
    • Query optimization
    • Migrations
  9. Testing:

    • Subscription tests
    • Mutation tests with PubSub
    • WebSocket connection tests
    • Integration tests
  10. Documentation:

    • GraphQL schema documentation
    • Subscription event catalog
    • Client integration guide
    • Deployment guide

Output production-ready GraphQL API with subscriptions following best practices with:

  • Complete GraphQL schema with types, queries, mutations, subscriptions
  • WebSocket server for real-time subscriptions
  • PubSub pattern for event distribution
  • Subscription filtering and authorization
  • Authentication for WebSocket connections
  • Redis PubSub for horizontal scaling
  • Apollo Client setup with split link
  • React hooks for subscriptions
  • Optimistic updates and cache management
  • Error handling and logging
  • Performance monitoring
  • Scalable architecture
  • Type-safe TypeScript implementation
  • Comprehensive documentation

Tags

graphql
subscriptions
websocket
realtime

Tested Models

gpt-4-turbo
claude-3-5-sonnet

Comments (0)

Sign in to leave a comment

Sign In