Transaction Callsite Audit
Generated: 2026-05-03 Purpose: Identify every interactivedb.transaction(...) callsite that must
be migrated to getTxDb + ctx.waitUntil(end()) rather than the HTTP driver.
Confirmed interactive transactions (need getTxDb)
| File | Line | Purpose |
|---|---|---|
| server/src/routes/appointments.ts | 1417 | Appointment update with conflict check |
| server/src/routes/auth.ts | 1792 | Signup with phone-uniqueness lock |
| server/src/routes/installments.ts | 88 | Create installment plan |
| server/src/routes/installments.ts | 431 | Pay installment |
| server/src/routes/installments.ts | 567 | Bulk installment update |
| server/src/routes/invoices.tsx | 375 | Convert quotation to invoice |
| server/src/routes/payroll.ts | 289 | Payroll run creation |
| server/src/routes/public-documents.ts | 421 | Public document signing |
| server/src/routes/treatment-plans.ts | 607 | Treatment plan creation |
| server/src/routes/treatment-plans.ts | 774 | Treatment plan update |
| server/src/lib/importer.ts | 657 | Bulk-import batch insert + ID-mapping write |
| server/src/scheduled/installment-invoices.ts | 73 | Cron: generate invoice for installment term |
| server/src/scheduled/appointment-invoices.ts | 120 | Cron: generate invoice 48h before appointment |
Non-issues (no migration needed)
routes/admin.ts:1874—DO $$ BEGIN ... END $$is a PL/pgSQL block, not an interactive tx. Stays ongetReadDb.routes/inventory.ts— “transaction” in identifiers refers to stock transactions (the entity), not DB transactions. Stays ongetReadDb.lib/schema-ensure.ts:83,:127,:170,:171,:175,:261,:273— allDO $$ BEGIN ... END $$PL/pgSQL blocks executed viadb.execute(sql\…`)for idempotent schema setup. Not interactive transactions; stays ongetReadDb` (or whatever single-statement driver schema-ensure currently uses).
Migration plan
Each row above gets a dedicated commit. Wrap the existingdb.transaction(...)
body verbatim inside getTxDb() and ensure ctx.waitUntil(end()) is registered.
Plan-task coverage
The Phase 1 plan (2026-05-03-app-performance-neon-tanstack.md) currently
covers the route callsites in Tasks 8–11:
- Task 8:
appointments.ts:1417 - Task 9:
auth.ts:1792 - Task 10:
installments.ts(lines 88, 431, 567) - Task 11:
payroll.ts:289,treatment-plans.ts:607+:774,public-documents.ts:421
Newly-discovered callsites (additions to plan)
The grep surfaced three callsites the original plan table omitted. They will need their own migration commits — flagging here for Sarmad’s review on which task to fold them into:routes/invoices.tsx:375— quotation→invoice conversion. Naturally fits a new “Task 11.5: migrate invoices.tsx tx” or could be added to Task 5 (billing batch), but Task 5 is non-tx-only so a separate tx commit is cleaner.lib/importer.ts:657— bulk-import batch insert. Importer runs inside a route handler, so it has a requestctxavailable; same pattern applies. Needs its own commit (no current task covers it).scheduled/installment-invoices.ts:73andscheduled/appointment-invoices.ts:120— Cron-triggered handlers. These run viascheduled()notfetch(), so thectx.waitUntil(end())pattern is identical (the CloudflareScheduledEventalso exposeswaitUntil). Needs its own commit.
Needs Sarmad’s review: confirm the four newly-discovered callsites (invoices.tsx, importer.ts, two scheduled handlers) should be migrated in Phase 1 and decide which task to fold them into.

