DocsRealtime
Realtime Subscriptions
Live data synchronization through GraphQL subscriptions powered by PostgreSQL LISTEN/NOTIFY.
Overview
Postrust provides realtime data synchronization through GraphQL subscriptions. Subscribe to changes on any table or view and receive updates instantly.
- Live updates when data changes
- Reactive dashboards and UIs
- Collaborative features
- No polling required
Architecture
Architecture
┌──────────────┐ WebSocket ┌──────────────┐ LISTEN/NOTIFY ┌────────────┐
│ Client │◀────────────▶│ Postrust │◀────────────────▶│ PostgreSQL│
│ (Browser) │ │ Server │ │ Database │
└──────────────┘ └──────────────┘ └────────────┘Connecting
Connect via WebSocket to the GraphQL endpoint:
ws://localhost:3000/graphqlBasic Subscription
GraphQL
# Subscribe to all changes on a table
subscription {
users {
id
name
email
updatedAt
}
}
# Subscribe with filters
subscription {
orders(filter: { status: { eq: "pending" } }) {
id
total
status
customer {
name
email
}
}
}Subscribe to Views
Subscribe to PostgreSQL views for computed or aggregated data:
GraphQL
subscription {
salesDashboard {
totalRevenue
orderCount
averageOrderValue
topProducts {
name
salesCount
}
}
}JavaScript Client
TypeScript
import { createClient } from 'graphql-ws';
const client = createClient({
url: 'ws://localhost:3000/graphql',
connectionParams: {
authorization: `Bearer ${token}`,
},
});
// Subscribe to orders
const unsubscribe = client.subscribe(
{
query: `
subscription {
orders(filter: { status: { eq: "pending" } }) {
id
total
status
}
}
`,
},
{
next: (data) => console.log('Update:', data),
error: (err) => console.error('Error:', err),
complete: () => console.log('Done'),
}
);
// Later: unsubscribe()React with Apollo
React
import { useSubscription, gql } from '@apollo/client';
const ORDERS_SUBSCRIPTION = gql`
subscription OnOrderUpdate {
orders(filter: { status: { eq: "pending" } }) {
id
total
status
customer { name }
}
}
`;
function PendingOrders() {
const { data, loading, error } = useSubscription(ORDERS_SUBSCRIPTION);
if (loading) return <p>Connecting...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<ul>
{data.orders.map(order => (
<li key={order.id}>
Order #{order.id} - ${order.total}
</li>
))}
</ul>
);
}PostgreSQL Triggers
Create triggers for fine-grained notifications:
SQL
-- Notification function
CREATE OR REPLACE FUNCTION notify_table_change()
RETURNS TRIGGER AS $$
BEGIN
PERFORM pg_notify(
'table_change',
json_build_object(
'table', TG_TABLE_NAME,
'operation', TG_OP,
'data', CASE
WHEN TG_OP = 'DELETE' THEN row_to_json(OLD)
ELSE row_to_json(NEW)
END
)::text
);
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;
-- Apply to table
CREATE TRIGGER orders_notify
AFTER INSERT OR UPDATE OR DELETE ON orders
FOR EACH ROW EXECUTE FUNCTION notify_table_change();Use Cases
Live Dashboards
Real-time metrics, KPIs, and analytics updates
Chat Applications
Instant message delivery and presence
Collaborative Editing
Multi-user document editing and cursors
Notifications
Push alerts and activity feeds
Best Practices
- Use filters - Subscribe to specific records, not entire tables
- Select only needed fields - Minimize payload size
- Handle reconnection - Implement retry logic for network issues
- Clean up subscriptions - Unsubscribe when components unmount