83b1ad3e35
Previously each match goal sync did: DELETE (auto-commit) → N individual INSERTs (each auto-commit). During those ~50ms readers saw 0 goals for the match — the inconsistency window. Now: collectGoals() builds the rows in memory, replaceGoals() wraps the DELETE + single bulk VALUES INSERT in a transaction. Under Postgres READ COMMITTED, readers see the old goals until commit and the full new set after — never an empty window. Also drop sync pool from max:5 → max:2; the job is fully sequential and was holding idle connections unnecessarily. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>