WPGraphQL Subscriptions
Subscriptions for WPGraphQL
by WPGraphQL · github.com/wp-graphql/wp-graphql-subscriptions
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/wp-graphql/wp-graphql-subscriptions/archive/refs/heads/master.zipReadme
WPGraphQL Subscriptions
[!WARNING] EXPERIMENTAL PLUGIN. This plugin is in active development and should be used with caution. It's not recommended for production environments without thorough testing.
An experimental WordPress plugin that adds GraphQL Subscriptions support to WPGraphQL, enabling real-time updates through Server-Sent Events (SSE).
Overview
This plugin extends WPGraphQL to support GraphQL Subscriptions, allowing clients to receive real-time updates when WordPress content changes. It provides a reference implementation for real-time messaging in WordPress using native WordPress technologies (no external services required).
Architecture: Universal Event Bus
The plugin is built around a universal WordPress event bus that can power multiple systems:
graph TD
subgraph "WordPress Core Events"
WP["WordPress Hooks<br/>post_updated, comment_post, etc."] --> Emitter["WPGraphQL_Event_Emitter<br/>✅ Generic & Reusable"]
end
subgraph "Multiple Consumers"
Emitter --> |"wpgraphql_generic_event"| GraphQL["GraphQL Subscription<br/>Channel Mapper<br/>→ SSE-2 Server"]
Emitter --> |"wpgraphql_generic_event"| Cache["WPGraphQL Smart Cache<br/>→ Varnish Purging"]
Emitter --> |"wpgraphql_generic_event"| Debug["Debug Webhook<br/>→ webhook.site"]
Emitter --> |"wpgraphql_generic_event"| Analytics["Analytics System<br/>→ Track Content Changes"]
Emitter --> |"wpgraphql_generic_event"| Custom["Custom Plugin<br/>→ Any Use Case"]
end
subgraph "Downstream Systems"
GraphQL --> SSE["SSE-2 Server<br/>Real-time Subscriptions"]
Cache --> Varnish["Varnish Cache<br/>Smart Purging"]
Debug --> WebhookSite["webhook.site<br/>Event Debugging"]
Analytics --> Dashboard["Analytics Dashboard<br/>Content Insights"]
Custom --> Integration["3rd Party Integration<br/>Zapier, etc."]
end
classDef core fill:#e3f2fd,stroke:#2196f3,color:#000
classDef consumers fill:#f3e5f5,stroke:#9c27b0,color:#000
classDef systems fill:#e8f5e8,stroke:#4caf50,color:#000
class WP,Emitter core
class GraphQL,Cache,Debug,Analytics,Custom consumers
class SSE,Varnish,WebhookSite,Dashboard,Integration systems
Key Benefits
- 🔄 Reusable Event System: The
WPGraphQL_Event_Emittercreates generic WordPress events that any plugin can consume - 🎯 Separation of Concerns: GraphQL subscriptions are just one consumer of the universal event bus
- 🔌 Plugin Ecosystem: Other plugins can hook into
wpgraphql_generic_eventfor cache invalidation, analytics, webhooks, etc. - ⚡ Schema-Agnostic SSE Server: The SSE-2 server has zero schema knowledge - it just publishes to whatever channels WordPress provides
🚀 Quick Demo
Want to see GraphQL subscriptions in action? After installing the plugin:
- Navigate to
/wp-content/plugins/wp-graphql-subscriptions/client/test-demos.html - Choose any of the 4 working demos
- Follow the on-screen instructions to connect and subscribe
- Update a post in WordPress admin and watch the real-time updates!
Note: This requires specific LocalWP configurations for multiple SSE connections. See Development Setup below for details.
Features
Server-Side (WordPress Plugin)
- ✅ GraphQL Subscriptions Schema - Adds
RootSubscriptiontype to WPGraphQL schema - ✅ Real-time Event System - Centralized event tracking and emission
- ✅ Server-Sent Events (SSE) - HTTP-based real-time transport
- ✅ Database Event Queue - Reliable multi-process event handling
- ✅ WordPress Native - No external dependencies or services required
- ✅ Multi-process Safe - Works with PHP-FPM and multiple concurrent connections
- ✅ Debug Tools - Admin interface and WP-CLI commands for monitoring
Client-Side (JavaScript Library)
- ✅ GraphQL-SSE Client Library - Ready-to-use JavaScript client (
/client/) - ✅ Apollo Client Integration - Drop-in support for React/Apollo apps
- ✅ Framework Agnostic - Works with React, Vue, Angular, or vanilla JS
- ✅ Automatic Reconnection - Exponential backoff with configurable retry
- ✅ Multiple Working Demos - 4 complete examples: Production Build (Vite+TypeScript), Apollo React, React Simple, and Vanilla JS
- ✅ Production Ready Examples - TypeScript, modern build tools, and real Apollo Client integration
Current Status
✅ Working Features
- GraphQL-SSE Protocol Compliance - Full implementation of the GraphQL-SSE specification
- Database Subscription Storage - Cross-process subscription document persistence
- Post Update Subscriptions -
postUpdated(id: "123")with argument filtering - Real-time SSE Streaming - Server-Sent Events with proper headers and connection management
- Event Emission System - WordPress hooks automatically trigger subscription events
- Database Event Queue - Reliable multi-process event storage and retrieval
- GraphQL Query Execution - Full WPGraphQL integration with proper field resolution
- Multiple Concurrent Connections - Supports many simultaneous SSE connections
- Connection Management - Token-based connections with automatic expiry
- Admin Monitoring Interface - Debug tools and queue management
- WP-CLI Management Commands - Command-line tools for testing and maintenance
🚧 In Development
register_graphql_subscription()API - Developer-friendly subscription registration- User authentication/authorization for subscriptions
- Additional subscription types (comments, users, taxonomies, etc.)
- WebSocket transport option
- Production optimization and scaling
📋 Planned Features
- Client-side subscription management libraries
- Rate limiting and connection throttling
- Redis/external cache support for high-scale deployments
- WebSocket transport alongside SSE
Installation
- Download or clone this repository to your
wp-content/plugins/directory - Ensure you have WPGraphQL installed and activated
- Activate the "WPGraphQL Subscriptions" plugin
- The plugin will automatically create the required database table
Basic Usage
1. GraphQL-SSE Protocol Usage
The plugin implements the GraphQL-SSE specification for real-time subscriptions.
Make a Reservation (PUT)
const response = await fetch('/graphql/stream', {
method: 'PUT'
});
const token = await response.text(); // Connection token
Execute GraphQL Operation (POST)
const response = await fetch('/graphql/stream', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-GraphQL-Event-Stream-Token': token
},
body: JSON.stringify({
query: `subscription {
postUpdated(id: "394") {
id
title
status
content
date
modified
author {
node {
id
name
}
}
}
}`,
extensions: {
operationId: 'my-subscription-001'
}
})
});
Establish SSE Connection (GET)
const eventSource = new EventSource(`/graphql/stream?token=${token}`);
eventSource.addEventListener('next', function(event) {
const data = JSON.parse(event.data);
console.log('GraphQL result:', data.payload);
/*
Example result:
{
"data": {
"postUpdated": {
"id": "cG9zdDozOTQ=",
"title": "My Updated Post",
"status": "publish",
"content": "<p>Updated content...</p>",
"date": "2025-08-07T20:26:32",
"modified": "2025-08-07T20:55:03",
"author": {
"node": {
"id": "dXNlcjox",
"name": "jasonbahl"
}
}
}
}
}
*/
});
eventSource.addEventListener('test', function(event) {
console.log('Connection test:', JSON.parse(event.data));
});
3. Test Events
Update any WordPress post and connected clients will receive real-time notifications.
Architecture
Event Flow
WordPress Hook → Event Emitter → Database Queue → SSE Streams → Clients
- WordPress Events - Standard WP hooks (
wp_insert_post, etc.) - Event Emitter - Standardizes and emits subscription events
- Database Queue - Stores events for reliable multi-process delivery
- SSE Streams - Long-running HTTP connections that poll for events
- Client Applications - Receive real-time GraphQL subscription results
Key Components
WPGraphQL_Event_Emitter- Central event emission systemWPGraphQL_Event_Queue- Database-backed event storageWPGraphQL_Subscriptions_Stream- SSE endpoint handlerWPGraphQL_Subscription_Manager- Plugin coordination and schema registration
Configuration
PHP-FPM Settings
For multiple concurrent SSE connections, ensure adequate PHP-FPM workers:
; In your PHP-FPM pool configuration
pm = dynamic
pm.max_children = 10 ; Increase from default
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
WordPress Settings
No special WordPress configuration required. The plugin works with standard WordPress installations.
Development
File Structure
wp-graphql-subscriptions/
├── wp-graphql-subscriptions.php # Main plugin file
├── README.md
├── docs/ # Documentation
├── includes/
│ ├── class-wpgraphql-event-emitter.php # Event emission
│ ├── class-wpgraphql-event-queue.php # Database queue
│ ├── class-wpgraphql-subscriptions-stream.php # SSE handler
│ ├── class-wpgraphql-subscription-manager.php # Plugin manager
│ ├── event-stream.php # SSE routing
│ ├── events.php # WordPress event hooks
│ ├── plugin-init.php # Plugin initialization
│ ├── schema.php # GraphQL schema additions
│ └── transport-webhook.php # Webhook transport (optional)
└── LICENSE
Client-Side Usage
JavaScript Client Library
The plugin includes a complete JavaScript client library for easy integration with any frontend application:
Apollo Client Integration
import { GraphQLSSELink } from './client/graphql-sse-client.js';
import { ApolloClient, InMemoryCache } from '@apollo/client';
const sseLink = new GraphQLSSELink({
baseUrl: '/graphql/stream'
});
const client = new ApolloClient({
link: sseLink,
cache: new InMemoryCache()
});
// Use with React hooks
const { data } = useSubscription(gql`
subscription {
postUpdated(id: "123") {
id
title
modified
}
}
`);
Vanilla JavaScript
import { GraphQLSSEClient } from './client/graphql-sse-client.js';
const client = new GraphQLSSEClient({
baseUrl: '/graphql/stream'
});
await client.makeReservation();
await client.connect();
const subscription = await client.subscribe(
'my-subscription',
'subscription { postUpdated(id: "123") { id title } }'
);
subscription.subscribe({
next: (data) => console.log('Update:', data),
error: (error) => console.error('Error:', error)
});
Live Demos
🎉 All 4 demos are fully working!
- 🏗️ Production Build Demo:
cd client/demo-build && npm install && npm run dev- Recommended: Full Vite + TypeScript + Real Apollo Client setup
- Production-ready with modern build tools and proper development workflow
- ⚛️ Apollo React Demo: Open
/client/demo-apollo-react.html- Browser-based Apollo-compatible client with React hooks
- ⚛️ React Simple Demo: Open
/client/demo-react-simple.html- React with direct GraphQL-SSE client integration (no Apollo)
- 🔧 Vanilla JS Demo: Open
/client/demo-vanilla-js.html- Pure JavaScript implementation for educational purposes
Demo Landing Page: Open /client/test-demos.html to access all demos with setup instructions.
See /client/README.md for complete documentation and examples.
WP-CLI Commands
# View queue statistics
wp wpgraphql subscription stats
# Test event emission
wp wpgraphql subscription test-event --type=postUpdated --node-id=123
# Clean up old events and expired connections
wp wpgraphql subscription cleanup --hours=1 --connections
# Create database table
wp wpgraphql subscription create-table
Debug Mode
Enable debug mode by adding to your wp-config.php:
// Enable WPGraphQL debug mode to see admin interfaces
define('GRAPHQL_DEBUG', true);
Then visit GraphQL → Subscription Queue in WordPress admin.
Troubleshooting
Multiple Connections Freezing
This usually indicates PHP-FPM process pool exhaustion. Increase pm.max_children in your PHP-FPM configuration.
Events Not Appearing in Streams
- Check that database tables exist:
SHOW TABLES LIKE 'wp_wpgraphql_subscription_events'; SHOW TABLES LIKE 'wp_wpgraphql_subscription_connections'; SHOW TABLES LIKE 'wp_wpgraphql_subscription_documents'; - Verify events are being stored:
SELECT * FROM wp_wpgraphql_subscription_events ORDER BY created_at DESC LIMIT 10 - Check subscriptions are registered:
SELECT * FROM wp_wpgraphql_subscription_documents - Check error logs for PHP or database errors
Session Blocking Issues
The plugin automatically calls session_write_close() to prevent session locking. If you're still experiencing issues, ensure no other plugins are starting sessions after the SSE stream begins.
Scaling & Performance Considerations
Database Load Concerns
⚠️ Important: The current database-based storage is designed for development and small-to-medium production sites. For high-traffic scenarios, consider these scaling implications: