Skip to content

perf: add missing indexes on member_account_id and velocity account_id#701

Draft
sandipndev wants to merge 1 commit intomainfrom
perf/indexes-and-shared-locks
Draft

perf: add missing indexes on member_account_id and velocity account_id#701
sandipndev wants to merge 1 commit intomainfrom
perf/indexes-and-shared-locks

Conversation

@sandipndev
Copy link
Copy Markdown
Member

@sandipndev sandipndev commented Apr 2, 2026

Summary

Add two missing database indexes that are hit on every post_transaction_in_op call:

  • idx_cala_account_set_member_accounts_member_id on cala_account_set_member_accounts(member_account_id)
  • idx_cala_velocity_account_controls_account_id on cala_velocity_account_controls(account_id)

Why these matter

Two queries run on every single cala transaction post:

1. fetch_mappings_in_op — finds which account sets each account belongs to:

SELECT m.account_set_id, m.member_account_id
FROM cala_account_set_member_accounts m
JOIN cala_account_sets s ON m.account_set_id = s.id
WHERE m.member_account_id = ANY($2)

2. find_for_enforcement — finds velocity controls for accounts:

SELECT values, velocity_context_values
FROM cala_velocity_account_controls v
JOIN cala_accounts a ON v.account_id = a.id
WHERE account_id = ANY($1)

Without indexes, PostgreSQL does a sequential scan of the entire table for each query. With 1000 loans in lana-bank, cala_account_set_member_accounts has ~14,000 rows (14 accounts per loan). Every transaction post — including every interest accrual — scans all 14,000 rows to find the ~2-3 matching ones.

With the index, it's an index lookup — O(log n) instead of O(n). The benefit grows with data volume. At 10,000 loans with daily accruals, you'd have 140,000+ rows being scanned on every single transaction post.

Benchmark (lana-bank, 100 loans parallel=10)

Metric Before After Change
100 loan creation 39.4s 35.3s -10.4%
10 days interest accrual 28.9s 26.6s -8.0%

Test plan

  • Existing cala tests pass
  • lana-bank e2e tests pass with local cala pointed at this branch

Found via autonomous performance investigation using autoresearch on the lana-bank loan workflow

🤖 Generated with Claude Code

@sandipndev sandipndev force-pushed the perf/indexes-and-shared-locks branch from d5f9e7f to 7add0e8 Compare April 2, 2026 14:59
@sandipndev sandipndev changed the title perf: add missing indexes and use shared advisory locks for account member ops perf: add missing indexes on member_account_id and velocity account_id Apr 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

📊 Performance Report

Commit: 7add0e8
Updated: 2026-04-02 15:15:56 UTC

Cala Performance Benchmark Results (non-representative)

Criterion Benchmark Results (single-threaded)

Benchmark Time per Run Throughput % vs Baseline
post_simple_transaction 5.781ms 172 tx/s 0 (baseline)
post_multi_layer_transaction 6.584ms 151 tx/s -13.0%
post_simple_transaction_with_effective_balances 8.220ms 121 tx/s -42.0%
post_simple_transaction_with_skipped_velocity 6.849ms 145 tx/s -18.0%
post_simple_transaction_with_velocity 7.932ms 126 tx/s -37.0%
post_simple_transaction_with_hit_velocity 3.701ms 270 tx/s +35.0%
post_simple_transaction_with_one_account_set 7.015ms 142 tx/s -21.0%
post_simple_transaction_with_five_account_sets 7.072ms 141 tx/s -22.0%

Load Testing Results (parallel-execution)

Scenario tx/s
1 parallel 103.89
2 parallel 151.89
5 parallel 181.56
10 parallel 182.56
20 parallel 179.55
2 contention 144.21
5 contention 153.40
2 acct_sets 126.50
5 acct_sets 139.58

Note: Performance results may vary based on system resources and database state.

Last updated by commit 7add0e8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant