Skip to content

Add confirm_lsn to replay a load-test backlog from the start - #129

Open
lukashes wants to merge 1 commit into
mainfrom
feat/load-replay-confirm-lsn
Open

Add confirm_lsn to replay a load-test backlog from the start#129
lukashes wants to merge 1 commit into
mainfrom
feat/load-replay-confirm-lsn

Conversation

@lukashes

Copy link
Copy Markdown
Owner

Problem

Load tests want to generate a backlog once and then measure the reader against the same data repeatedly. Today the first make start-outboxx consumes the backlog and confirms the LSN, so the slot advances and the WAL is recycled; a second run reads nothing.

Solution

  • Add confirm_lsn to [source.postgres], default true. When false, sendFeedback keeps sending (so the keepalive and liveness path are unchanged) but always confirms the first LSN seen, so the slot never advances and PostgreSQL keeps the WAL. Every restart then re-reads the same backlog from the start.
  • The source captures the first change LSN and reports it while pinned; main wires the flag and warns at startup when it is off (the mode is not durable and must not ship to production).
  • The load stand's outboxx config sets confirm_lsn = false, and its image builds with -Dlog_level=info to keep the run quiet.

Workflow: make load once, then make start-outboxx as many times as you like.

Verification

New integration test drives a real slot: with confirm_lsn = false, after reading a multi-row batch and calling sendFeedback(last_lsn), the slot's confirmed_flush_lsn settles on the first LSN, below the batch's last.

With confirm_lsn=false the slot is never advanced: feedback keeps flowing as a
keepalive but always confirms the first LSN, so PostgreSQL keeps the WAL and every
restart re-reads the same backlog. Generate load once, then rerun make
start-outboxx as many times as needed. Default stays true, where advancing the
slot is what makes delivery at-least-once.

The load stand enables it and builds with -Dlog_level=info to keep the run quiet.
@github-actions

Copy link
Copy Markdown
Contributor

📊 Benchmark Results

Current run is the minimum over 3 passes, compared against the base branch (main @ 10c320b), built on the same runner.

Benchmark Baseline Current Δ Time Allocs Status
Converter DELETE 132.21μs 130.88μs -1.0% 14 → 14 ➡️
Converter INSERT 126.92μs 125.91μs -0.8% 14 → 14 ➡️
Converter UPDATE 178.38μs 176.89μs -0.8% 23 → 23 ➡️
JsonSerializer 42.09μs 41.55μs -1.3% 3 → 3 ➡️
KafkaProducer produce 206.92μs 203.86μs -1.5% 1 → 1 ➡️
KafkaProducer sendMessage 248.80μs 245.58μs -1.3% 0 → 0 ➡️
PgOutputDecoder 95.23μs 94.94μs -0.3% 6 → 6 ➡️
getPartitionKeyValue boolean 16.74μs 16.52μs -1.3% 1 → 1 ➡️
getPartitionKeyValue integer 51.29μs 51.11μs -0.3% 3 → 3 ➡️
getPartitionKeyValue not found 0.03μs 0.03μs +0.0% 0 → 0 ⚪ noise
getPartitionKeyValue string 18.57μs 18.46μs -0.6% 1 → 1 ➡️
matchStreams found 17.81μs 17.60μs -1.1% 1 → 1 ➡️
matchStreams not found 0.06μs 0.06μs +0.0% 0 → 0 ⚪ noise

Summary: ➡️ 11 neutral · ⚪ 2 ignored (sub-μs)

Thresholds: <1μs ignore · 1–20μs 15% · 20–50μs 10% · ≥50μs 5%. Measured on a shared CI runner — treat small deltas as noise. Informational only; this check never fails the build.

@lukashes lukashes added the marinating Deliberately paused to settle before deciding label Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

marinating Deliberately paused to settle before deciding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant