How to Query Recent CDC Tables in ClickHouse
May 2026
In ClickHouse, recent CDC queries are mostly about knowing when FINAL matters and when a timestamp column should do the filtering.
Short Answer
To query recent CDC tables in ClickHouse, read the final-state table and use a real business timestamp for your recent window, but add FINAL when you need immediate point-in-time correctness on freshly mutated keys. That is the practical way to handle ReplacingMergeTree tables whose background merges may not have converged yet.
If you need recent deletes, check the companion tombstone table rather than trying to infer deletes from missing rows. The _skippr_order_token column exists to rank competing mutations, not to serve as your user-facing time dimension.
Why Teams Struggle with This
This matters because ClickHouse can briefly show multiple versions of the same business key right after CDC writes. A query that is technically fast but reads before merges converge can still be the wrong query for a freshness-sensitive dashboard.
- Use FINAL when duplicate versions on fresh data would create a wrong answer.
- Avoid relying on _skippr_order_token as if it were a readable event timestamp.
- Keep a source-derived updated_at or committed_at column when readers need recent windows.
- Use tombstones for delete visibility instead of guessing from absence.
How Skippr Handles It
Skippr makes this easier by documenting the ClickHouse caveat directly: ReplacingMergeTree converges through background merges, and FINAL is the way to force point-in-time consistency when the query cannot wait. The CDC design still gives you tombstones and order-token ranking, so the pieces are explicit.
A concrete example: if a dashboard needs the latest state of orders changed in the last hour, query the orders table with FINAL and filter on updated_at >= now() - INTERVAL 1 HOUR. If you also need deleted orders, read _skippr_tombstones_orders for the same business keys or time window.
- Recent current-state reads come from the target table, optionally with FINAL.
- Recent delete reads come from the companion tombstone table.
- The order token is for conflict resolution, not for human recency semantics.
- ClickHouse query correctness depends on understanding merge timing, not only table names.
What the First Useful Version Looks Like
The ClickHouse version of this question is not "where is the latest row stored." It is "do I need convergence now or can I wait for background merges."
Once that trade-off is explicit, recent CDC queries become much more predictable.
