KamoCRM

Read the public changelog's commit counts from a ledger, not COUNT(*)

PerformanceSecurityService
Shipped
September 23, 2026 at 1:48 PM UTC
Author
Kamo
Commit
41e4a00

pg_stat_statements: `SELECT COUNT(c) FROM CommitLog c WHERE c.project IN (:~33 public projects) [AND c.commitTypeId = :t]` ran ~140K times a day at 100-200 ms each (measured on production before this change) — every list page view (page(), addresses()/sitemap) and every /changelog/public/stats call, on endpoints that take no authentication. commit_logs has ~19K rows across 38 projects; the count itself is cheap, but it ran on every request. create_commit_log_ledger.sql adds the same total+journal shape create_lead_intake_ledger.sql uses: commit_log_counts (a total per (project, commit type)) plus an append-only commit_log_count_deltas journal that a row trigger on commit_logs writes in the same transaction as an insert, a project/type-changing update, or a delete. Applied by hand as the owner and backfilled; DaemonService now folds and recounts it (separate commit, perf(changelog): fold and recount the public changelog's commit-log ledger, deployed first). **************** and **************** now read total + journal in one native statement instead of a JPQL COUNT(c) — new methods on PublicChangelogService (its header already explains why a filter/query the public page needs lives here and not in kamo-shared-library) rather than CommitLogRepository, so this needed no shared-library release. todayCount() is untouched: it is a bounded time-window count backed by ix_commit_logs_date_uid, not the ~140K-call pattern. Verified against production before switching: ledger totals matched COUNT(*) exactly across all 264 (project, commit type) pairs (0 mismatches) after the backfill, and the three commit_logs triggers fire correctly (proven inside a rolled-back transaction as kamo_app, the app's own credential).

All changes

Like what you see shipping?

All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.

Start Free ForeverView Pricing