jorgex-stack 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/PRD.md +310 -297
  2. package/README.md +68 -56
  3. package/dist/cli.js +37 -3
  4. package/package.json +1 -1
  5. package/stack/agents/code-simplifier.md +21 -10
  6. package/stack/agents/implementer.md +1 -0
  7. package/stack/agents/orchestrator.md +194 -192
  8. package/stack/agents/security-auditor.md +7 -0
  9. package/stack/agents/silent-failure-hunter.md +7 -0
  10. package/stack/agents/test-analyzer.md +7 -0
  11. package/stack/agents/tester.md +71 -71
  12. package/stack/agents/type-design-analyzer.md +1 -1
  13. package/stack/commands/lean-audit.md +59 -0
  14. package/stack/commands/xreview.md +82 -80
  15. package/stack/hooks/hooks.json +18 -18
  16. package/stack/scripts/post-pr-review.cjs +159 -156
  17. package/stack/skills/diagnose/SKILL.md +117 -117
  18. package/stack/skills/diagnose/scripts/hitl-loop.template.sh +41 -41
  19. package/stack/skills/find-skills/SKILL.md +133 -133
  20. package/stack/skills/lean-code/SKILL.md +69 -0
  21. package/stack/skills/mcp-builder/LICENSE.txt +201 -201
  22. package/stack/skills/mcp-builder/SKILL.md +236 -236
  23. package/stack/skills/mcp-builder/reference/evaluation.md +601 -601
  24. package/stack/skills/mcp-builder/reference/mcp_best_practices.md +249 -249
  25. package/stack/skills/mcp-builder/reference/node_mcp_server.md +969 -969
  26. package/stack/skills/mcp-builder/reference/python_mcp_server.md +718 -718
  27. package/stack/skills/mcp-builder/scripts/connections.py +151 -151
  28. package/stack/skills/mcp-builder/scripts/evaluation.py +373 -373
  29. package/stack/skills/mcp-builder/scripts/example_evaluation.xml +22 -22
  30. package/stack/skills/mcp-builder/scripts/requirements.txt +2 -2
  31. package/stack/skills/obsidian-cli/SKILL.md +106 -106
  32. package/stack/skills/obsidian-markdown/SKILL.md +196 -196
  33. package/stack/skills/obsidian-markdown/references/CALLOUTS.md +58 -58
  34. package/stack/skills/obsidian-markdown/references/EMBEDS.md +63 -63
  35. package/stack/skills/obsidian-markdown/references/PROPERTIES.md +61 -61
  36. package/stack/skills/react-doctor/SKILL.md +19 -19
  37. package/stack/skills/skill-creator/LICENSE.txt +201 -201
  38. package/stack/skills/skill-creator/agents/analyzer.md +274 -274
  39. package/stack/skills/skill-creator/agents/comparator.md +202 -202
  40. package/stack/skills/skill-creator/agents/grader.md +223 -223
  41. package/stack/skills/skill-creator/assets/eval_review.html +146 -146
  42. package/stack/skills/skill-creator/eval-viewer/generate_review.py +471 -471
  43. package/stack/skills/skill-creator/eval-viewer/viewer.html +1325 -1325
  44. package/stack/skills/skill-creator/references/schemas.md +430 -430
  45. package/stack/skills/skill-creator/scripts/aggregate_benchmark.py +401 -401
  46. package/stack/skills/skill-creator/scripts/generate_report.py +326 -326
  47. package/stack/skills/skill-creator/scripts/improve_description.py +248 -248
  48. package/stack/skills/skill-creator/scripts/package_skill.py +136 -136
  49. package/stack/skills/skill-creator/scripts/quick_validate.py +102 -102
  50. package/stack/skills/skill-creator/scripts/run_eval.py +310 -310
  51. package/stack/skills/skill-creator/scripts/run_loop.py +332 -332
  52. package/stack/skills/skill-creator/scripts/utils.py +47 -47
  53. package/stack/skills/supabase/SKILL.md +135 -135
  54. package/stack/skills/supabase/assets/feedback-issue-template.md +17 -17
  55. package/stack/skills/supabase/references/skill-feedback.md +17 -17
  56. package/stack/skills/supabase-postgres-best-practices/SKILL.md +64 -64
  57. package/stack/skills/supabase-postgres-best-practices/references/_contributing.md +170 -170
  58. package/stack/skills/supabase-postgres-best-practices/references/_sections.md +39 -39
  59. package/stack/skills/supabase-postgres-best-practices/references/_template.md +34 -34
  60. package/stack/skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -55
  61. package/stack/skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -49
  62. package/stack/skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -46
  63. package/stack/skills/supabase-postgres-best-practices/references/conn-limits.md +44 -44
  64. package/stack/skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -41
  65. package/stack/skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -46
  66. package/stack/skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -54
  67. package/stack/skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -53
  68. package/stack/skills/supabase-postgres-best-practices/references/data-pagination.md +50 -50
  69. package/stack/skills/supabase-postgres-best-practices/references/data-upsert.md +50 -50
  70. package/stack/skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -56
  71. package/stack/skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -68
  72. package/stack/skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -50
  73. package/stack/skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -54
  74. package/stack/skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -45
  75. package/stack/skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -55
  76. package/stack/skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -55
  77. package/stack/skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -44
  78. package/stack/skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -40
  79. package/stack/skills/supabase-postgres-best-practices/references/query-index-types.md +48 -48
  80. package/stack/skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -43
  81. package/stack/skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -45
  82. package/stack/skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -80
  83. package/stack/skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -46
  84. package/stack/skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -59
  85. package/stack/skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -55
  86. package/stack/skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -55
  87. package/stack/skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -61
  88. package/stack/skills/supabase-postgres-best-practices/references/security-privileges.md +54 -54
  89. package/stack/skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -50
  90. package/stack/skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -63
  91. package/stack/skills/tdd/SKILL.md +109 -109
  92. package/stack/skills/tdd/deep-modules.md +33 -33
  93. package/stack/skills/tdd/interface-design.md +31 -31
  94. package/stack/skills/tdd/mocking.md +59 -59
  95. package/stack/skills/tdd/refactoring.md +10 -10
  96. package/stack/skills/tdd/tests.md +61 -61
  97. package/stack/skills/to-issues/SKILL.md +83 -83
  98. package/stack/skills/to-prd/SKILL.md +72 -72
  99. package/upstreams.json +96 -96
@@ -1,50 +1,50 @@
1
- ---
2
- title: Use Cursor-Based Pagination Instead of OFFSET
3
- impact: MEDIUM-HIGH
4
- impactDescription: Consistent O(1) performance regardless of page depth
5
- tags: pagination, cursor, keyset, offset, performance
6
- ---
7
-
8
- ## Use Cursor-Based Pagination Instead of OFFSET
9
-
10
- OFFSET-based pagination scans all skipped rows, getting slower on deeper pages. Cursor pagination is O(1).
11
-
12
- **Incorrect (OFFSET pagination):**
13
-
14
- ```sql
15
- -- Page 1: scans 20 rows
16
- select * from products order by id limit 20 offset 0;
17
-
18
- -- Page 100: scans 2000 rows to skip 1980
19
- select * from products order by id limit 20 offset 1980;
20
-
21
- -- Page 10000: scans 200,000 rows!
22
- select * from products order by id limit 20 offset 199980;
23
- ```
24
-
25
- **Correct (cursor/keyset pagination):**
26
-
27
- ```sql
28
- -- Page 1: get first 20
29
- select * from products order by id limit 20;
30
- -- Application stores last_id = 20
31
-
32
- -- Page 2: start after last ID
33
- select * from products where id > 20 order by id limit 20;
34
- -- Uses index, always fast regardless of page depth
35
-
36
- -- Page 10000: same speed as page 1
37
- select * from products where id > 199980 order by id limit 20;
38
- ```
39
-
40
- For multi-column sorting:
41
-
42
- ```sql
43
- -- Cursor must include all sort columns
44
- select * from products
45
- where (created_at, id) > ('2024-01-15 10:00:00', 12345)
46
- order by created_at, id
47
- limit 20;
48
- ```
49
-
50
- Reference: [Pagination](https://supabase.com/docs/guides/database/pagination)
1
+ ---
2
+ title: Use Cursor-Based Pagination Instead of OFFSET
3
+ impact: MEDIUM-HIGH
4
+ impactDescription: Consistent O(1) performance regardless of page depth
5
+ tags: pagination, cursor, keyset, offset, performance
6
+ ---
7
+
8
+ ## Use Cursor-Based Pagination Instead of OFFSET
9
+
10
+ OFFSET-based pagination scans all skipped rows, getting slower on deeper pages. Cursor pagination is O(1).
11
+
12
+ **Incorrect (OFFSET pagination):**
13
+
14
+ ```sql
15
+ -- Page 1: scans 20 rows
16
+ select * from products order by id limit 20 offset 0;
17
+
18
+ -- Page 100: scans 2000 rows to skip 1980
19
+ select * from products order by id limit 20 offset 1980;
20
+
21
+ -- Page 10000: scans 200,000 rows!
22
+ select * from products order by id limit 20 offset 199980;
23
+ ```
24
+
25
+ **Correct (cursor/keyset pagination):**
26
+
27
+ ```sql
28
+ -- Page 1: get first 20
29
+ select * from products order by id limit 20;
30
+ -- Application stores last_id = 20
31
+
32
+ -- Page 2: start after last ID
33
+ select * from products where id > 20 order by id limit 20;
34
+ -- Uses index, always fast regardless of page depth
35
+
36
+ -- Page 10000: same speed as page 1
37
+ select * from products where id > 199980 order by id limit 20;
38
+ ```
39
+
40
+ For multi-column sorting:
41
+
42
+ ```sql
43
+ -- Cursor must include all sort columns
44
+ select * from products
45
+ where (created_at, id) > ('2024-01-15 10:00:00', 12345)
46
+ order by created_at, id
47
+ limit 20;
48
+ ```
49
+
50
+ Reference: [Pagination](https://supabase.com/docs/guides/database/pagination)
@@ -1,50 +1,50 @@
1
- ---
2
- title: Use UPSERT for Insert-or-Update Operations
3
- impact: MEDIUM
4
- impactDescription: Atomic operation, eliminates race conditions
5
- tags: upsert, on-conflict, insert, update
6
- ---
7
-
8
- ## Use UPSERT for Insert-or-Update Operations
9
-
10
- Using separate SELECT-then-INSERT/UPDATE creates race conditions. Use INSERT ... ON CONFLICT for atomic upserts.
11
-
12
- **Incorrect (check-then-insert race condition):**
13
-
14
- ```sql
15
- -- Race condition: two requests check simultaneously
16
- select * from settings where user_id = 123 and key = 'theme';
17
- -- Both find nothing
18
-
19
- -- Both try to insert
20
- insert into settings (user_id, key, value) values (123, 'theme', 'dark');
21
- -- One succeeds, one fails with duplicate key error!
22
- ```
23
-
24
- **Correct (atomic UPSERT):**
25
-
26
- ```sql
27
- -- Single atomic operation
28
- insert into settings (user_id, key, value)
29
- values (123, 'theme', 'dark')
30
- on conflict (user_id, key)
31
- do update set value = excluded.value, updated_at = now();
32
-
33
- -- Returns the inserted/updated row
34
- insert into settings (user_id, key, value)
35
- values (123, 'theme', 'dark')
36
- on conflict (user_id, key)
37
- do update set value = excluded.value
38
- returning *;
39
- ```
40
-
41
- Insert-or-ignore pattern:
42
-
43
- ```sql
44
- -- Insert only if not exists (no update)
45
- insert into page_views (page_id, user_id)
46
- values (1, 123)
47
- on conflict (page_id, user_id) do nothing;
48
- ```
49
-
50
- Reference: [INSERT ON CONFLICT](https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT)
1
+ ---
2
+ title: Use UPSERT for Insert-or-Update Operations
3
+ impact: MEDIUM
4
+ impactDescription: Atomic operation, eliminates race conditions
5
+ tags: upsert, on-conflict, insert, update
6
+ ---
7
+
8
+ ## Use UPSERT for Insert-or-Update Operations
9
+
10
+ Using separate SELECT-then-INSERT/UPDATE creates race conditions. Use INSERT ... ON CONFLICT for atomic upserts.
11
+
12
+ **Incorrect (check-then-insert race condition):**
13
+
14
+ ```sql
15
+ -- Race condition: two requests check simultaneously
16
+ select * from settings where user_id = 123 and key = 'theme';
17
+ -- Both find nothing
18
+
19
+ -- Both try to insert
20
+ insert into settings (user_id, key, value) values (123, 'theme', 'dark');
21
+ -- One succeeds, one fails with duplicate key error!
22
+ ```
23
+
24
+ **Correct (atomic UPSERT):**
25
+
26
+ ```sql
27
+ -- Single atomic operation
28
+ insert into settings (user_id, key, value)
29
+ values (123, 'theme', 'dark')
30
+ on conflict (user_id, key)
31
+ do update set value = excluded.value, updated_at = now();
32
+
33
+ -- Returns the inserted/updated row
34
+ insert into settings (user_id, key, value)
35
+ values (123, 'theme', 'dark')
36
+ on conflict (user_id, key)
37
+ do update set value = excluded.value
38
+ returning *;
39
+ ```
40
+
41
+ Insert-or-ignore pattern:
42
+
43
+ ```sql
44
+ -- Insert only if not exists (no update)
45
+ insert into page_views (page_id, user_id)
46
+ values (1, 123)
47
+ on conflict (page_id, user_id) do nothing;
48
+ ```
49
+
50
+ Reference: [INSERT ON CONFLICT](https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT)
@@ -1,56 +1,56 @@
1
- ---
2
- title: Use Advisory Locks for Application-Level Locking
3
- impact: MEDIUM
4
- impactDescription: Efficient coordination without row-level lock overhead
5
- tags: advisory-locks, coordination, application-locks
6
- ---
7
-
8
- ## Use Advisory Locks for Application-Level Locking
9
-
10
- Advisory locks provide application-level coordination without requiring database rows to lock.
11
-
12
- **Incorrect (creating rows just for locking):**
13
-
14
- ```sql
15
- -- Creating dummy rows to lock on
16
- create table resource_locks (
17
- resource_name text primary key
18
- );
19
-
20
- insert into resource_locks values ('report_generator');
21
-
22
- -- Lock by selecting the row
23
- select * from resource_locks where resource_name = 'report_generator' for update;
24
- ```
25
-
26
- **Correct (advisory locks):**
27
-
28
- ```sql
29
- -- Session-level advisory lock (released on disconnect or unlock)
30
- select pg_advisory_lock(hashtext('report_generator'));
31
- -- ... do exclusive work ...
32
- select pg_advisory_unlock(hashtext('report_generator'));
33
-
34
- -- Transaction-level lock (released on commit/rollback)
35
- begin;
36
- select pg_advisory_xact_lock(hashtext('daily_report'));
37
- -- ... do work ...
38
- commit; -- Lock automatically released
39
- ```
40
-
41
- Try-lock for non-blocking operations:
42
-
43
- ```sql
44
- -- Returns immediately with true/false instead of waiting
45
- select pg_try_advisory_lock(hashtext('resource_name'));
46
-
47
- -- Use in application
48
- if (acquired) {
49
- -- Do work
50
- select pg_advisory_unlock(hashtext('resource_name'));
51
- } else {
52
- -- Skip or retry later
53
- }
54
- ```
55
-
56
- Reference: [Advisory Locks](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)
1
+ ---
2
+ title: Use Advisory Locks for Application-Level Locking
3
+ impact: MEDIUM
4
+ impactDescription: Efficient coordination without row-level lock overhead
5
+ tags: advisory-locks, coordination, application-locks
6
+ ---
7
+
8
+ ## Use Advisory Locks for Application-Level Locking
9
+
10
+ Advisory locks provide application-level coordination without requiring database rows to lock.
11
+
12
+ **Incorrect (creating rows just for locking):**
13
+
14
+ ```sql
15
+ -- Creating dummy rows to lock on
16
+ create table resource_locks (
17
+ resource_name text primary key
18
+ );
19
+
20
+ insert into resource_locks values ('report_generator');
21
+
22
+ -- Lock by selecting the row
23
+ select * from resource_locks where resource_name = 'report_generator' for update;
24
+ ```
25
+
26
+ **Correct (advisory locks):**
27
+
28
+ ```sql
29
+ -- Session-level advisory lock (released on disconnect or unlock)
30
+ select pg_advisory_lock(hashtext('report_generator'));
31
+ -- ... do exclusive work ...
32
+ select pg_advisory_unlock(hashtext('report_generator'));
33
+
34
+ -- Transaction-level lock (released on commit/rollback)
35
+ begin;
36
+ select pg_advisory_xact_lock(hashtext('daily_report'));
37
+ -- ... do work ...
38
+ commit; -- Lock automatically released
39
+ ```
40
+
41
+ Try-lock for non-blocking operations:
42
+
43
+ ```sql
44
+ -- Returns immediately with true/false instead of waiting
45
+ select pg_try_advisory_lock(hashtext('resource_name'));
46
+
47
+ -- Use in application
48
+ if (acquired) {
49
+ -- Do work
50
+ select pg_advisory_unlock(hashtext('resource_name'));
51
+ } else {
52
+ -- Skip or retry later
53
+ }
54
+ ```
55
+
56
+ Reference: [Advisory Locks](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)
@@ -1,68 +1,68 @@
1
- ---
2
- title: Prevent Deadlocks with Consistent Lock Ordering
3
- impact: MEDIUM-HIGH
4
- impactDescription: Eliminate deadlock errors, improve reliability
5
- tags: deadlocks, locking, transactions, ordering
6
- ---
7
-
8
- ## Prevent Deadlocks with Consistent Lock Ordering
9
-
10
- Deadlocks occur when transactions lock resources in different orders. Always
11
- acquire locks in a consistent order.
12
-
13
- **Incorrect (inconsistent lock ordering):**
14
-
15
- ```sql
16
- -- Transaction A -- Transaction B
17
- begin; begin;
18
- update accounts update accounts
19
- set balance = balance - 100 set balance = balance - 50
20
- where id = 1; where id = 2; -- B locks row 2
21
-
22
- update accounts update accounts
23
- set balance = balance + 100 set balance = balance + 50
24
- where id = 2; -- A waits for B where id = 1; -- B waits for A
25
-
26
- -- DEADLOCK! Both waiting for each other
27
- ```
28
-
29
- **Correct (lock rows in consistent order first):**
30
-
31
- ```sql
32
- -- Explicitly acquire locks in ID order before updating
33
- begin;
34
- select * from accounts where id in (1, 2) order by id for update;
35
-
36
- -- Now perform updates in any order - locks already held
37
- update accounts set balance = balance - 100 where id = 1;
38
- update accounts set balance = balance + 100 where id = 2;
39
- commit;
40
- ```
41
-
42
- Alternative: use a single statement to update atomically:
43
-
44
- ```sql
45
- -- Single statement acquires all locks atomically
46
- begin;
47
- update accounts
48
- set balance = balance + case id
49
- when 1 then -100
50
- when 2 then 100
51
- end
52
- where id in (1, 2);
53
- commit;
54
- ```
55
-
56
- Detect deadlocks in logs:
57
-
58
- ```sql
59
- -- Check for recent deadlocks
60
- select * from pg_stat_database where deadlocks > 0;
61
-
62
- -- Enable deadlock logging
63
- set log_lock_waits = on;
64
- set deadlock_timeout = '1s';
65
- ```
66
-
67
- Reference:
68
- [Deadlocks](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-DEADLOCKS)
1
+ ---
2
+ title: Prevent Deadlocks with Consistent Lock Ordering
3
+ impact: MEDIUM-HIGH
4
+ impactDescription: Eliminate deadlock errors, improve reliability
5
+ tags: deadlocks, locking, transactions, ordering
6
+ ---
7
+
8
+ ## Prevent Deadlocks with Consistent Lock Ordering
9
+
10
+ Deadlocks occur when transactions lock resources in different orders. Always
11
+ acquire locks in a consistent order.
12
+
13
+ **Incorrect (inconsistent lock ordering):**
14
+
15
+ ```sql
16
+ -- Transaction A -- Transaction B
17
+ begin; begin;
18
+ update accounts update accounts
19
+ set balance = balance - 100 set balance = balance - 50
20
+ where id = 1; where id = 2; -- B locks row 2
21
+
22
+ update accounts update accounts
23
+ set balance = balance + 100 set balance = balance + 50
24
+ where id = 2; -- A waits for B where id = 1; -- B waits for A
25
+
26
+ -- DEADLOCK! Both waiting for each other
27
+ ```
28
+
29
+ **Correct (lock rows in consistent order first):**
30
+
31
+ ```sql
32
+ -- Explicitly acquire locks in ID order before updating
33
+ begin;
34
+ select * from accounts where id in (1, 2) order by id for update;
35
+
36
+ -- Now perform updates in any order - locks already held
37
+ update accounts set balance = balance - 100 where id = 1;
38
+ update accounts set balance = balance + 100 where id = 2;
39
+ commit;
40
+ ```
41
+
42
+ Alternative: use a single statement to update atomically:
43
+
44
+ ```sql
45
+ -- Single statement acquires all locks atomically
46
+ begin;
47
+ update accounts
48
+ set balance = balance + case id
49
+ when 1 then -100
50
+ when 2 then 100
51
+ end
52
+ where id in (1, 2);
53
+ commit;
54
+ ```
55
+
56
+ Detect deadlocks in logs:
57
+
58
+ ```sql
59
+ -- Check for recent deadlocks
60
+ select * from pg_stat_database where deadlocks > 0;
61
+
62
+ -- Enable deadlock logging
63
+ set log_lock_waits = on;
64
+ set deadlock_timeout = '1s';
65
+ ```
66
+
67
+ Reference:
68
+ [Deadlocks](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-DEADLOCKS)
@@ -1,50 +1,50 @@
1
- ---
2
- title: Keep Transactions Short to Reduce Lock Contention
3
- impact: MEDIUM-HIGH
4
- impactDescription: 3-5x throughput improvement, fewer deadlocks
5
- tags: transactions, locking, contention, performance
6
- ---
7
-
8
- ## Keep Transactions Short to Reduce Lock Contention
9
-
10
- Long-running transactions hold locks that block other queries. Keep transactions as short as possible.
11
-
12
- **Incorrect (long transaction with external calls):**
13
-
14
- ```sql
15
- begin;
16
- select * from orders where id = 1 for update; -- Lock acquired
17
-
18
- -- Application makes HTTP call to payment API (2-5 seconds)
19
- -- Other queries on this row are blocked!
20
-
21
- update orders set status = 'paid' where id = 1;
22
- commit; -- Lock held for entire duration
23
- ```
24
-
25
- **Correct (minimal transaction scope):**
26
-
27
- ```sql
28
- -- Validate data and call APIs outside transaction
29
- -- Application: response = await paymentAPI.charge(...)
30
-
31
- -- Only hold lock for the actual update
32
- begin;
33
- update orders
34
- set status = 'paid', payment_id = $1
35
- where id = $2 and status = 'pending'
36
- returning *;
37
- commit; -- Lock held for milliseconds
38
- ```
39
-
40
- Use `statement_timeout` to prevent runaway transactions:
41
-
42
- ```sql
43
- -- Abort queries running longer than 30 seconds
44
- set statement_timeout = '30s';
45
-
46
- -- Or per-session
47
- set local statement_timeout = '5s';
48
- ```
49
-
50
- Reference: [Transaction Management](https://www.postgresql.org/docs/current/tutorial-transactions.html)
1
+ ---
2
+ title: Keep Transactions Short to Reduce Lock Contention
3
+ impact: MEDIUM-HIGH
4
+ impactDescription: 3-5x throughput improvement, fewer deadlocks
5
+ tags: transactions, locking, contention, performance
6
+ ---
7
+
8
+ ## Keep Transactions Short to Reduce Lock Contention
9
+
10
+ Long-running transactions hold locks that block other queries. Keep transactions as short as possible.
11
+
12
+ **Incorrect (long transaction with external calls):**
13
+
14
+ ```sql
15
+ begin;
16
+ select * from orders where id = 1 for update; -- Lock acquired
17
+
18
+ -- Application makes HTTP call to payment API (2-5 seconds)
19
+ -- Other queries on this row are blocked!
20
+
21
+ update orders set status = 'paid' where id = 1;
22
+ commit; -- Lock held for entire duration
23
+ ```
24
+
25
+ **Correct (minimal transaction scope):**
26
+
27
+ ```sql
28
+ -- Validate data and call APIs outside transaction
29
+ -- Application: response = await paymentAPI.charge(...)
30
+
31
+ -- Only hold lock for the actual update
32
+ begin;
33
+ update orders
34
+ set status = 'paid', payment_id = $1
35
+ where id = $2 and status = 'pending'
36
+ returning *;
37
+ commit; -- Lock held for milliseconds
38
+ ```
39
+
40
+ Use `statement_timeout` to prevent runaway transactions:
41
+
42
+ ```sql
43
+ -- Abort queries running longer than 30 seconds
44
+ set statement_timeout = '30s';
45
+
46
+ -- Or per-session
47
+ set local statement_timeout = '5s';
48
+ ```
49
+
50
+ Reference: [Transaction Management](https://www.postgresql.org/docs/current/tutorial-transactions.html)
@@ -1,54 +1,54 @@
1
- ---
2
- title: Use SKIP LOCKED for Non-Blocking Queue Processing
3
- impact: MEDIUM-HIGH
4
- impactDescription: 10x throughput for worker queues
5
- tags: skip-locked, queue, workers, concurrency
6
- ---
7
-
8
- ## Use SKIP LOCKED for Non-Blocking Queue Processing
9
-
10
- When multiple workers process a queue, SKIP LOCKED allows workers to process different rows without waiting.
11
-
12
- **Incorrect (workers block each other):**
13
-
14
- ```sql
15
- -- Worker 1 and Worker 2 both try to get next job
16
- begin;
17
- select * from jobs where status = 'pending' order by created_at limit 1 for update;
18
- -- Worker 2 waits for Worker 1's lock to release!
19
- ```
20
-
21
- **Correct (SKIP LOCKED for parallel processing):**
22
-
23
- ```sql
24
- -- Each worker skips locked rows and gets the next available
25
- begin;
26
- select * from jobs
27
- where status = 'pending'
28
- order by created_at
29
- limit 1
30
- for update skip locked;
31
-
32
- -- Worker 1 gets job 1, Worker 2 gets job 2 (no waiting)
33
-
34
- update jobs set status = 'processing' where id = $1;
35
- commit;
36
- ```
37
-
38
- Complete queue pattern:
39
-
40
- ```sql
41
- -- Atomic claim-and-update in one statement
42
- update jobs
43
- set status = 'processing', worker_id = $1, started_at = now()
44
- where id = (
45
- select id from jobs
46
- where status = 'pending'
47
- order by created_at
48
- limit 1
49
- for update skip locked
50
- )
51
- returning *;
52
- ```
53
-
54
- Reference: [SELECT FOR UPDATE SKIP LOCKED](https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE)
1
+ ---
2
+ title: Use SKIP LOCKED for Non-Blocking Queue Processing
3
+ impact: MEDIUM-HIGH
4
+ impactDescription: 10x throughput for worker queues
5
+ tags: skip-locked, queue, workers, concurrency
6
+ ---
7
+
8
+ ## Use SKIP LOCKED for Non-Blocking Queue Processing
9
+
10
+ When multiple workers process a queue, SKIP LOCKED allows workers to process different rows without waiting.
11
+
12
+ **Incorrect (workers block each other):**
13
+
14
+ ```sql
15
+ -- Worker 1 and Worker 2 both try to get next job
16
+ begin;
17
+ select * from jobs where status = 'pending' order by created_at limit 1 for update;
18
+ -- Worker 2 waits for Worker 1's lock to release!
19
+ ```
20
+
21
+ **Correct (SKIP LOCKED for parallel processing):**
22
+
23
+ ```sql
24
+ -- Each worker skips locked rows and gets the next available
25
+ begin;
26
+ select * from jobs
27
+ where status = 'pending'
28
+ order by created_at
29
+ limit 1
30
+ for update skip locked;
31
+
32
+ -- Worker 1 gets job 1, Worker 2 gets job 2 (no waiting)
33
+
34
+ update jobs set status = 'processing' where id = $1;
35
+ commit;
36
+ ```
37
+
38
+ Complete queue pattern:
39
+
40
+ ```sql
41
+ -- Atomic claim-and-update in one statement
42
+ update jobs
43
+ set status = 'processing', worker_id = $1, started_at = now()
44
+ where id = (
45
+ select id from jobs
46
+ where status = 'pending'
47
+ order by created_at
48
+ limit 1
49
+ for update skip locked
50
+ )
51
+ returning *;
52
+ ```
53
+
54
+ Reference: [SELECT FOR UPDATE SKIP LOCKED](https://www.postgresql.org/docs/current/sql-select.html#SQL-FOR-UPDATE-SHARE)