GraphQL Subscriptions with WebSocket
fullstack
TypeScript
architecture
corporate_pm
Implement real-time GraphQL subscriptions using WebSocket for live data updates.
By chris_d
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:
-
GraphQL Schema:
- Type definitions for all entities
- Query definitions
- Mutation definitions
- Subscription definitions
- Input types and enums
-
GraphQL Server:
- Apollo Server setup with Express
- WebSocket server configuration
- Schema creation with makeExecutableSchema
- Server startup and configuration
-
PubSub Setup:
- PubSub instance (in-memory or Redis)
- Event constants
- Publish helper functions
-
Resolvers:
- Query resolvers with data fetching
- Mutation resolvers with PubSub publish
- Subscription resolvers with filtering
- Authentication checks
- Error handling
-
Authentication:
- WebSocket connection authentication
- Context creation with user
- Auth middleware for resolvers
- Token validation
-
Client Setup:
- Apollo Client configuration
- HTTP Link setup
- WebSocket Link setup
- Split Link implementation
- Cache configuration
-
React Hooks & Components:
- useSubscription examples
- useQuery with subscribeToMore
- UI components using subscriptions
- Optimistic updates
-
Database Integration:
- Database models/schema
- CRUD operations
- Query optimization
- Migrations
-
Testing:
- Subscription tests
- Mutation tests with PubSub
- WebSocket connection tests
- Integration tests
-
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