How to fix P6003: Pulse subscription cancelled (Pulse) in Prisma
This error occurs when a Prisma Pulse subscription is terminated unexpectedly, often due to connection issues, resource limits, or manual cancellation. Understanding subscription lifecycle management is key to preventing this error.
Quick fix
Fixes P6003
// Track active subscriptions
const activeSubscriptions = new Map<string, any>();
const subscription = await prisma.user.subscribe({
create: { after: true }
});
activeSubscriptions.set('user-subscription-1', subscription);
// Check count before creating new ones
if (activeSubscriptions.size >= 10) {
console.warn('Subscription limit approaching');
}- Verify subscription limit is not exceeded
- Implement proper subscription cleanup
- Add reconnection logic for network interruptions
- Monitor subscription health
// Track active subscriptionsconst activeSubscriptions = new Map<string, any>();const subscription = await prisma.user.subscribe({create: { after: true }});activeSubscriptions.set('user-subscription-1', subscription);// Check count before creating new onesif (activeSubscriptions.size >= 10) {console.warn('Subscription limit approaching');}P6003: Pulse subscription cancelled (Pulse)
What this error means
The P6003 error indicates that an active Prisma Pulse subscription has been cancelled before the stream completed naturally. Prisma Pulse enables real-time database change notifications through subscriptions to specific tables or queries. When a subscription is cancelled, it means the stream of database events has been interrupted. This can happen for several reasons: network disconnections between your application and Prisma's infrastructure, exceeding subscription limits (initially 10 active subscriptions per table), manual cancellation via the stop() method, or infrastructure issues on either the client or server side. When this error occurs, your application will no longer receive real-time updates for the affected subscription. Prisma Pulse currently has limited automatic reconnection capabilities, so applications need to handle reconnection logic explicitly.
Typical symptoms
- Real-time database updates stop arriving in your application
- Error logs showing "P6003: Pulse subscription cancelled"
- Subscription event handlers no longer fire after working previously
- Application loses sync with database changes
- No automatic reconnection after network interruption
Common causes
- Network connectivity issues between application and Prisma Pulse infrastructure
- Exceeding the limit of 10 active subscriptions per table
- Explicitly calling subscription.stop() or stream.stop() in code
- Application shutdown or process termination without cleanup
- Pulse service interruption or maintenance
- Connection timeout due to inactivity or firewall rules
How to fix "P6003: Pulse subscription cancelled (Pulse)"
Check how many active subscriptions you have per table. Prisma Pulse initially limits you to 10 active subscriptions per table.
// Track active subscriptions
const activeSubscriptions = new Map<string, any>();
const subscription = await prisma.user.subscribe({
create: { after: true }
});
activeSubscriptions.set('user-subscription-1', subscription);
// Check count before creating new ones
if (activeSubscriptions.size >= 10) {
console.warn('Subscription limit approaching');
}Always stop subscriptions you no longer need to free up slots.
Ensure subscriptions are properly stopped when no longer needed to avoid resource exhaustion.
let subscription: any = null;
async function startSubscription() {
subscription = await prisma.user.subscribe({
create: { after: true }
});
for await (const event of subscription) {
console.log('User created:', event);
}
}
// Cleanup on shutdown
process.on('SIGTERM', async () => {
if (subscription) {
subscription.stop();
}
await prisma.$disconnect();
});This prevents zombie subscriptions that count against your limit.
Prisma Pulse doesn't automatically reconnect on network failures. Implement retry logic to handle P6003 errors.
async function createResilientSubscription(maxRetries = 3) {
let retries = 0;
while (retries < maxRetries) {
try {
const subscription = await prisma.user.subscribe({
create: { after: true }
});
for await (const event of subscription) {
console.log('Event received:', event);
}
} catch (error: any) {
if (error.code === 'P6003') {
retries++;
console.log(`Subscription cancelled, retry ${retries}/${maxRetries}`);
await new Promise(resolve => setTimeout(resolve, 1000 * retries));
continue;
}
throw error;
}
}
}This provides automatic recovery from transient connection issues.
Add monitoring to detect when subscriptions are cancelled and alert accordingly.
interface SubscriptionHealth {
id: string;
startTime: Date;
lastEventTime: Date | null;
status: 'active' | 'cancelled' | 'error';
}
const healthMap = new Map<string, SubscriptionHealth>();
async function monitoredSubscription(id: string) {
healthMap.set(id, {
id,
startTime: new Date(),
lastEventTime: null,
status: 'active'
});
try {
const subscription = await prisma.user.subscribe({
create: { after: true }
});
for await (const event of subscription) {
const health = healthMap.get(id)!;
health.lastEventTime = new Date();
health.status = 'active';
}
} catch (error: any) {
const health = healthMap.get(id);
if (health) {
health.status = error.code === 'P6003' ? 'cancelled' : 'error';
}
throw error;
}
}This helps identify patterns in subscription failures.
If you need guaranteed event delivery, use stream() instead of subscribe(). Streams require event persistence to be enabled.
// subscribe() delivers ephemeral events - missed if subscription inactive
const subscription = await prisma.user.subscribe({
create: { after: true }
});
// stream() delivers persisted events - replays missed events
const stream = await prisma.user.stream({
create: { after: true }
});Note that stream() requires event persistence to be enabled in your Pulse project settings. This ensures events aren't lost during connection interruptions.
Advanced notes
Subscription Lifecycle Best Practices:
When building applications with Prisma Pulse, consider using a subscription manager pattern to handle lifecycle, reconnection, and cleanup:
class PulseSubscriptionManager {
private subscriptions = new Map<string, any>();
private reconnectDelay = 1000;
async create(id: string, config: any) {
if (this.subscriptions.size >= 10) {
throw new Error('Maximum subscriptions reached');
}
const subscription = await this.createWithRetry(config);
this.subscriptions.set(id, subscription);
return subscription;
}
private async createWithRetry(config: any, attempt = 0): Promise<any> {
try {
return await prisma.user.subscribe(config);
} catch (error: any) {
if (error.code === 'P6003' && attempt < 3) {
await new Promise(r => setTimeout(r, this.reconnectDelay * (attempt + 1)));
return this.createWithRetry(config, attempt + 1);
}
throw error;
}
}
async stopAll() {
for (const [id, sub] of this.subscriptions) {
sub.stop();
this.subscriptions.delete(id);
}
}
}Connection Heartbeat: Prisma is planning to add heartbeat capability that throws an error when the connection is no longer active, allowing applications to reconnect automatically. Until this feature is available, implement your own heartbeat mechanism using periodic keep-alive messages or timeout detection.
Debugging Tips: Enable Prisma logging to see connection events:
const prisma = new PrismaClient({
log: ['query', 'info', 'warn', 'error'],
});This helps identify whether P6003 errors correlate with specific database operations or network conditions.
Frequently asked questions
- What does "P6003" mean?
- The P6003 error indicates that an active Prisma Pulse subscription has been cancelled before the stream completed naturally. Prisma Pulse enables real-time database change notifications through subscriptions to specific tables or queries. When a subscription is cancelled, it means the stream of database events has been interrupted.
- How do I fix "P6003"?
- This error occurs when a Prisma Pulse subscription is terminated unexpectedly, often due to connection issues, resource limits, or manual cancellation. Understanding subscription lifecycle management is key to preventing this error.
- What causes "P6003"?
- Network connectivity issues between application and Prisma Pulse infrastructure Exceeding the limit of 10 active subscriptions per table Explicitly calling subscription.stop() or stream.stop() in code
- Is the "P6003" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- ๐Prisma Official Documentation
- ๐prisma.io - error reference(Official Docs)
- ๐prisma.io - api reference(Official Docs)
- ๐prisma.io - getting started(Official Docs)
- ๐prisma.io - known limitations(Official Docs)
- ๐