How to fix P6003: Pulse subscription cancelled (Pulse) in Prisma

PrismaINTERMEDIATEHIGHUpdated Dec 22, 2025ยท 120 views

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');
}
  1. Verify subscription limit is not exceeded
  2. Implement proper subscription cleanup
  3. Add reconnection logic for network interruptions
  4. Monitor subscription health
prisma โ€” error
// 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');
}
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

  1. Network connectivity issues between application and Prisma Pulse infrastructure
  2. Exceeding the limit of 10 active subscriptions per table
  3. Explicitly calling subscription.stop() or stream.stop() in code
  4. Application shutdown or process termination without cleanup
  5. Pulse service interruption or maintenance
  6. Connection timeout due to inactivity or firewall rules

How to fix "P6003: Pulse subscription cancelled (Pulse)"

1Verify subscription limit is not exceeded

Check how many active subscriptions you have per table. Prisma Pulse initially limits you to 10 active subscriptions per table.

typescript
// 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.

2Implement proper subscription cleanup

Ensure subscriptions are properly stopped when no longer needed to avoid resource exhaustion.

typescript
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.

3Add reconnection logic for network interruptions

Prisma Pulse doesn't automatically reconnect on network failures. Implement retry logic to handle P6003 errors.

typescript
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.

4Monitor subscription health

Add monitoring to detect when subscriptions are cancelled and alert accordingly.

typescript
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.

5Use stream() for persistent event delivery

If you need guaranteed event delivery, use stream() instead of subscribe(). Streams require event persistence to be enabled.

typescript
// 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:

typescript
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:

typescript
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