Skip to content

Conversation

@tanmaysharma2001
Copy link
Contributor

🔍 Description

Fixes a critical memory leak in RealtimeClient where Web Workers created with the worker: true option were never terminated on disconnect, causing workers to accumulate indefinitely in long-running applications.

What changed?

  • Added a new private method _terminateWorker() in RealtimeClient.ts that properly terminates the Web Worker with error handling
  • Updated _teardownConnection() to call _terminateWorker() during connection cleanup
  • Worker termination now happens alongside other resource cleanup (timers, channels)

Why was this change needed?

Web Workers were being created in _startWorkerHeartbeat() (line 691) but never terminated in _teardownConnection() (line 628-649). Each disconnect/reconnect cycle would leak one worker, causing memory accumulation over time.

Impact:

  • Affects anyone using RealtimeClient with worker: true option
  • Critical for long-running applications (SPAs, Electron apps) with multiple connection cycles
  • Memory leak: ~10-50KB per orphaned worker (browser-dependent)

Reproduction:

const client = new RealtimeClient(url, { params: { apikey }, worker: true })

for (let i = 0; i < 10; i++) {
  client.connect()
  await new Promise(resolve => setTimeout(resolve, 1000))
  client.disconnect() // Worker leaked here ❌
}
// 10 workers still running after this loop

Closes #1902

📸 Screenshots/Examples

Before this fix:

// Worker created but never terminated
private _teardownConnection(): void {
  // ... connection cleanup ...
  this._clearAllTimers()
  // ❌ Missing: worker termination
  this.channels.forEach((channel) => channel.teardown())
}

After this fix:

// Worker properly terminated with error handling
private _terminateWorker(): void {
  if (this.workerRef) {
    try {
      this.workerRef.terminate()
      this.log('worker', 'worker terminated')
    } catch (e) {
      this.log('error', 'Error terminating worker', e)
    } finally {
      this.workerRef = undefined
    }
  }
}

private _teardownConnection(): void {
  // ... connection cleanup ...
  this._clearAllTimers()
  this._terminateWorker()  // ✅ Worker properly cleaned up
  this.channels.forEach((channel) => channel.teardown())
}

🔄 Breaking changes

  • [☑️] This PR contains no breaking changes

📋 Checklist

  • [☑️ ] I have read the Contributing Guidelines
  • [☑️] My PR title follows the conventional commit format: <type>(<scope>): <description>
  • [☑️] I have run npx nx format to ensure consistent code formatting
  • [☑️] I have added tests for new functionality (if applicable)
  • [☑️] I have updated documentation (if applicable)

📝 Additional notes

@tanmaysharma2001 tanmaysharma2001 requested review from a team as code owners November 28, 2025 07:24
@tanmaysharma2001 tanmaysharma2001 deleted the fix-realtime-js-worker-memory-leak branch November 28, 2025 07:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web Worker memory leak on disconnect

1 participant