Skip to content

[Performance] Remaining fetch-latency optimizations (post #5) #6

@waritctd

Description

@waritctd

Follow-ups to #5 (which removed the post-mutation full reload and the users.list() N+1). Root cause of perceived slowness: chatty sequential queries × network RTT to the remote DB (Supabase pooler, Tokyo, ~70–90 ms/query). These are optimizations, not ship-blockers.

1. Collapse INSERT+SELECT in ensureX helpers (POST create)

EmployeeRepository.create() runs ~20 sequential round trips; the ensureTitle/Division/Position/Level/Location/Status helpers each do an INSERT ... ON CONFLICT then a separate SELECT to read the id back.

  • Fix: add RETURNING <id> to the upsert (or INSERT ... ON CONFLICT DO UPDATE ... RETURNING) so each is one round trip.
  • Impact: removes ~6 round trips from every employee create (~0.5 s on remote DB).
  • Files: backend/.../employee/EmployeeRepository.java

2. Server-side pagination + push filters down

GET /api/employees returns the whole table (16 LEFT JOINs, no LIMIT); the frontend filters/paginates client-side.

  • Fix: add LIMIT/OFFSET (or keyset) + use the existing filter params server-side; add a pg_trgm GIN index for the ILIKE '%x%' search.
  • Impact: keeps list fast and payload small as the dataset grows past a few hundred rows.
  • Files: EmployeeRepository.findEmployees, EmployeeController, EmployeeListPage.jsx, new Flyway index migration.

3. Warm the Hikari pool

minimum-idle: 1 means cold connections pay a full TLS handshake to the remote DB on first use after idle.

  • Fix: set minimum-idle = maximum-pool-size; consider enabling PgJDBC server-side prepared-statement caching (safe on the 5432 session pooler; must be disabled if ever switching to the 6543 transaction pooler).
  • Impact: removes cold-start stalls.
  • Files: backend/src/main/resources/application.yml

4. (Optional) single-query employee detail

GET /api/employees/{id} runs 4 sequential queries (detail + assignments + salary + pending count). Low priority — could be one query with LEFT JOIN LATERAL / JSON aggregation if it shows up in profiling.

Acceptance criteria

  • Employee create issues materially fewer DB round trips (verify via query log).
  • /api/employees supports server-side pagination + filtering; search uses an index.
  • Hikari keeps warm idle connections.

Metadata

Metadata

Assignees

No one assigned

    Labels

    performancePerformance / latencyphase-1Phase 1 production launch

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions