Summary
claims_router.py:list_claims() (line ~543) executes a separate _get_attestation_summary() query for each claim in the result set — an N+1 query pattern. With the default limit of 50, this means 51 DB roundtrips instead of 1.
Proposed Fix
Replace the per-claim loop with a single query using LEFT JOIN + GROUP BY:
SELECT c.*, er.entity_text AS claimant_name,
COUNT(a.id) AS att_count,
jsonb_object_agg(a.verdict, a.cnt) FILTER (WHERE a.verdict IS NOT NULL) AS att_summary
FROM claims c
LEFT JOIN entity_registry er ON c.claimant_uri = er.fuseki_uri
LEFT JOIN (
SELECT claim_rid, verdict, COUNT(*) AS cnt
FROM claim_attestations
GROUP BY claim_rid, verdict
) a ON a.claim_rid = c.claim_rid
{where}
GROUP BY c.claim_rid, er.entity_text
ORDER BY c.created_at DESC
LIMIT ... OFFSET ...
Impact
Performance improvement for claim listing, especially as dogfooding scales beyond 49 claims. No API contract change.
Summary
claims_router.py:list_claims()(line ~543) executes a separate_get_attestation_summary()query for each claim in the result set — an N+1 query pattern. With the default limit of 50, this means 51 DB roundtrips instead of 1.Proposed Fix
Replace the per-claim loop with a single query using
LEFT JOIN+GROUP BY:Impact
Performance improvement for claim listing, especially as dogfooding scales beyond 49 claims. No API contract change.