Skip to content

Conversation

@Karavil
Copy link
Contributor

@Karavil Karavil commented Jan 8, 2026

Summary

This PR brings back the in-memory queue table stats from #5350, with additional documentation explaining the critical difference between the in-memory queue and the changeLog table.

Why This Matters

In the original review of #5350, it was assumed that the changeLog table query would provide roughly the same information as the in-memory table stats. However, in production we observed:

  • changeLog table: ~52k rows (changes committed to DB but not yet purged)
  • in-memory queue: 100k+ changes (causing back pressure)

These diverged significantly because view-syncers had slow SQLite queries, causing them to consume changes slowly. The changeLog was being drained normally, but the in-memory queue kept growing.

The Difference

Metric What it measures When it grows
changeLog table Changes committed to CVR database but not yet purged When changes are committed faster than purged
in-memory queue Changes waiting to be sent to downstream consumers When downstream consumers (view-syncers, backup-replicator) are slow

Example Log Output

applying back pressure with 150000 queued changes (threshold: 100000)

Top tables in the in-memory queue:
 1. public.assignment_problem    45,000 pending
 2. public.student_session       28,000 pending
 3. public.live_whiteboard_state 22,000 pending
 4. public.problem_tracker       18,000 pending

NOTE: The in-memory queue (above) tracks changes waiting to be sent to
downstream consumers (view-syncers, backup-replicator). This is different
from the changeLog table in your CVR database, which contains changes that
have been committed but not yet purged. These can diverge significantly
when downstream consumers are slow.

To inspect the changeLog (committed changes) in your CVR database:
  SELECT
    (change->'relation'->>'schema') || '.' || (change->'relation'->>'name') AS table_name,
    change->>'tag' AS operation,
    COUNT(*) AS count
  FROM "<app_id>/cdc"."changeLog"
  GROUP BY 1, 2
  ORDER BY 3 DESC
  LIMIT 20;

Changes

  • Add getTableFromChange helper to extract table names from insert/update/delete/truncate changes
  • Track table stats as changes flow through the queue (increment on store, decrement on process)
  • Format and log top 20 tables when back pressure is applied
  • Include clear explanation of in-memory queue vs changeLog difference
  • Clear stats on abort
  • Add unit tests for getTableFromChange helper

Related PRs

This PR adds the in-memory stats back with better documentation explaining why both are valuable.

…essure

The back pressure log now shows which tables have the most pending changes
in the in-memory queue, providing real-time insight into what's causing
the backlog.

IMPORTANT: This is different from the changeLog table query!

The changeLog table in the CVR database contains changes that have been
committed but not yet purged. The in-memory queue tracks changes waiting
to be sent to downstream consumers (view-syncers, backup-replicator).

These can diverge significantly:
- changeLog might be small (e.g. 50k) if changes are being committed quickly
- in-memory queue might be large (e.g. 100k+) if downstream consumers are slow

For example, when view-syncers have slow SQLite queries, they consume changes
slowly, causing the in-memory queue to grow even though the changeLog is
being drained normally.

Changes:
- Add getTableFromChange helper to extract table names from data changes
- Track table stats as changes flow through the queue (increment on store,
  decrement on process)
- Format and log top 20 tables when back pressure is applied
- Include explanation of the difference between in-memory queue and changeLog
- Clear stats on abort
- Add unit tests for getTableFromChange helper

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@vercel
Copy link

vercel bot commented Jan 8, 2026

@Karavil is attempting to deploy a commit to the Rocicorp Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant