nextjs-hackathon-stack 0.1.40 → 0.1.42

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 (174) hide show
  1. package/dist/index.js +3 -63
  2. package/package.json +1 -1
  3. package/template/.claude/agents/backend.md +54 -0
  4. package/template/.claude/agents/business-analyst.md +195 -0
  5. package/template/.claude/agents/code-reviewer.md +76 -0
  6. package/template/.claude/agents/frontend.md +85 -0
  7. package/template/.claude/agents/security-researcher.md +54 -0
  8. package/template/.claude/agents/technical-lead.md +92 -0
  9. package/template/.claude/agents/test-qa.md +85 -0
  10. package/template/.claude/rules/architecture.mdc +48 -0
  11. package/template/.claude/rules/coding-standards.mdc +120 -0
  12. package/template/.claude/rules/components.mdc +49 -0
  13. package/template/.claude/rules/data-fetching.mdc +115 -0
  14. package/template/.claude/rules/forms.mdc +100 -0
  15. package/template/.claude/rules/general.mdc +54 -0
  16. package/template/.claude/rules/migrations.mdc +11 -0
  17. package/template/.claude/rules/nextjs.mdc +71 -0
  18. package/template/.claude/rules/security.mdc +108 -0
  19. package/template/.claude/rules/supabase.mdc +70 -0
  20. package/template/.claude/rules/testing.mdc +136 -0
  21. package/template/.claude/settings.json +16 -0
  22. package/template/.claude/skills/build-feature/SKILL.md +198 -0
  23. package/template/.claude/skills/build-feature/references/server-action-test-template.md +103 -0
  24. package/template/.claude/skills/create-api-route/SKILL.md +62 -0
  25. package/template/.claude/skills/discover-feature/SKILL.md +200 -0
  26. package/template/.claude/skills/memory/SKILL.md +208 -0
  27. package/template/.claude/skills/review-branch/SKILL.md +43 -0
  28. package/template/.claude/skills/review-branch/references/review-checklist.md +36 -0
  29. package/template/.claude/skills/security-audit/SKILL.md +40 -0
  30. package/template/.claude/skills/security-audit/references/audit-steps.md +41 -0
  31. package/template/.claude/skills/supabase/SKILL.md +105 -0
  32. package/template/.claude/skills/supabase/assets/feedback-issue-template.md +17 -0
  33. package/template/.claude/skills/supabase/references/skill-feedback.md +17 -0
  34. package/template/.claude/skills/supabase-postgres-best-practices/SKILL.md +65 -0
  35. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp__contributing.md +170 -0
  36. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp__sections.md +39 -0
  37. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp__template.md +34 -0
  38. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_advanced-full-text-search.md +55 -0
  39. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_advanced-jsonb-indexing.md +49 -0
  40. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-idle-timeout.md +46 -0
  41. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-limits.md +44 -0
  42. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-pooling.md +41 -0
  43. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_conn-prepared-statements.md +46 -0
  44. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-batch-inserts.md +54 -0
  45. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-n-plus-one.md +53 -0
  46. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-pagination.md +50 -0
  47. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_data-upsert.md +50 -0
  48. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-advisory.md +56 -0
  49. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-deadlock-prevention.md +68 -0
  50. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-short-transactions.md +50 -0
  51. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_lock-skip-locked.md +54 -0
  52. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_monitor-explain-analyze.md +45 -0
  53. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_monitor-pg-stat-statements.md +55 -0
  54. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_monitor-vacuum-analyze.md +55 -0
  55. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-composite-indexes.md +44 -0
  56. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-covering-indexes.md +40 -0
  57. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-index-types.md +48 -0
  58. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-missing-indexes.md +43 -0
  59. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_query-partial-indexes.md +45 -0
  60. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-constraints.md +80 -0
  61. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-data-types.md +46 -0
  62. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-foreign-key-indexes.md +59 -0
  63. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-lowercase-identifiers.md +55 -0
  64. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-partitioning.md +55 -0
  65. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_schema-primary-keys.md +61 -0
  66. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_security-privileges.md +54 -0
  67. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_security-rls-basics.md +50 -0
  68. package/template/.claude/skills/supabase-postgres-best-practices/references/pgbp_security-rls-performance.md +57 -0
  69. package/template/.cursor/agents/business-analyst.md +197 -0
  70. package/template/.cursor/agents/technical-lead.md +3 -3
  71. package/template/.cursor/mcp.json +6 -2
  72. package/template/.cursor/skills/build-feature/SKILL.md +20 -21
  73. package/template/.cursor/skills/discover-feature/SKILL.md +118 -29
  74. package/template/.cursor/skills/supabase/SKILL.md +104 -0
  75. package/template/.cursor/skills/supabase/assets/feedback-issue-template.md +17 -0
  76. package/template/.cursor/skills/supabase/references/skill-feedback.md +17 -0
  77. package/template/.cursor/skills/supabase-postgres-best-practices/SKILL.md +64 -0
  78. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp__contributing.md +170 -0
  79. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp__sections.md +39 -0
  80. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp__template.md +34 -0
  81. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_advanced-full-text-search.md +55 -0
  82. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_advanced-jsonb-indexing.md +49 -0
  83. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-idle-timeout.md +46 -0
  84. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-limits.md +44 -0
  85. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-pooling.md +41 -0
  86. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_conn-prepared-statements.md +46 -0
  87. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-batch-inserts.md +54 -0
  88. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-n-plus-one.md +53 -0
  89. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-pagination.md +50 -0
  90. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_data-upsert.md +50 -0
  91. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-advisory.md +56 -0
  92. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-deadlock-prevention.md +68 -0
  93. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-short-transactions.md +50 -0
  94. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_lock-skip-locked.md +54 -0
  95. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_monitor-explain-analyze.md +45 -0
  96. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_monitor-pg-stat-statements.md +55 -0
  97. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_monitor-vacuum-analyze.md +55 -0
  98. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-composite-indexes.md +44 -0
  99. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-covering-indexes.md +40 -0
  100. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-index-types.md +48 -0
  101. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-missing-indexes.md +43 -0
  102. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_query-partial-indexes.md +45 -0
  103. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-constraints.md +80 -0
  104. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-data-types.md +46 -0
  105. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-foreign-key-indexes.md +59 -0
  106. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-lowercase-identifiers.md +55 -0
  107. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-partitioning.md +55 -0
  108. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_schema-primary-keys.md +61 -0
  109. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_security-privileges.md +54 -0
  110. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_security-rls-basics.md +50 -0
  111. package/template/.cursor/skills/supabase-postgres-best-practices/references/pgbp_security-rls-performance.md +57 -0
  112. package/template/.mcp.json +16 -0
  113. package/template/.opencode/agents/backend.md +72 -0
  114. package/template/.opencode/agents/business-analyst.md +153 -0
  115. package/template/.opencode/agents/code-reviewer.md +80 -0
  116. package/template/.opencode/agents/frontend.md +84 -0
  117. package/template/.opencode/agents/security-researcher.md +58 -0
  118. package/template/.opencode/agents/technical-lead.md +131 -0
  119. package/template/.opencode/agents/test-qa.md +103 -0
  120. package/template/.opencode/memory/architecture-snapshot.md +127 -0
  121. package/template/.opencode/skills/build-feature/SKILL.md +208 -0
  122. package/template/.opencode/skills/create-api-route/SKILL.md +63 -0
  123. package/template/.opencode/skills/discover-feature/SKILL.md +194 -0
  124. package/template/.opencode/skills/memory/SKILL.md +199 -0
  125. package/template/.opencode/skills/review-branch/SKILL.md +43 -0
  126. package/template/.opencode/skills/security-audit/SKILL.md +40 -0
  127. package/template/.opencode/skills/supabase/SKILL.md +105 -0
  128. package/template/.opencode/skills/supabase/assets/feedback-issue-template.md +17 -0
  129. package/template/.opencode/skills/supabase/references/skill-feedback.md +17 -0
  130. package/template/.opencode/skills/supabase-postgres-best-practices/SKILL.md +65 -0
  131. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp__contributing.md +170 -0
  132. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp__sections.md +39 -0
  133. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp__template.md +34 -0
  134. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_advanced-full-text-search.md +55 -0
  135. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_advanced-jsonb-indexing.md +49 -0
  136. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-idle-timeout.md +46 -0
  137. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-limits.md +44 -0
  138. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-pooling.md +41 -0
  139. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_conn-prepared-statements.md +46 -0
  140. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-batch-inserts.md +54 -0
  141. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-n-plus-one.md +53 -0
  142. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-pagination.md +50 -0
  143. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_data-upsert.md +50 -0
  144. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-advisory.md +56 -0
  145. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-deadlock-prevention.md +68 -0
  146. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-short-transactions.md +50 -0
  147. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_lock-skip-locked.md +54 -0
  148. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_monitor-explain-analyze.md +45 -0
  149. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_monitor-pg-stat-statements.md +55 -0
  150. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_monitor-vacuum-analyze.md +55 -0
  151. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-composite-indexes.md +44 -0
  152. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-covering-indexes.md +40 -0
  153. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-index-types.md +48 -0
  154. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-missing-indexes.md +43 -0
  155. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_query-partial-indexes.md +45 -0
  156. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-constraints.md +80 -0
  157. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-data-types.md +46 -0
  158. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-foreign-key-indexes.md +59 -0
  159. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-lowercase-identifiers.md +55 -0
  160. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-partitioning.md +55 -0
  161. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_schema-primary-keys.md +61 -0
  162. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_security-privileges.md +54 -0
  163. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_security-rls-basics.md +50 -0
  164. package/template/.opencode/skills/supabase-postgres-best-practices/references/pgbp_security-rls-performance.md +57 -0
  165. package/template/.requirements/README.md +1 -1
  166. package/template/AGENTS.md +1 -1
  167. package/template/CLAUDE.md +1 -1
  168. package/template/Dockerfile.memory +7 -0
  169. package/template/README.md +15 -2
  170. package/template/_gitignore +3 -0
  171. package/template/docker-compose.yml +28 -0
  172. package/template/ia-flow.md +341 -0
  173. package/template/opencode.json +23 -0
  174. package/template/.cursor/agents/business-intelligence.md +0 -83
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: Eliminate N+1 Queries with Batch Loading
3
+ impact: MEDIUM-HIGH
4
+ impactDescription: 10-100x fewer database round trips
5
+ tags: n-plus-one, batch, performance, queries
6
+ ---
7
+
8
+ ## Eliminate N+1 Queries with Batch Loading
9
+
10
+ N+1 queries execute one query per item in a loop. Batch them into a single query using arrays or JOINs.
11
+
12
+ **Incorrect (N+1 queries):**
13
+
14
+ ```sql
15
+ -- First query: get all users
16
+ select id from users where active = true; -- Returns 100 IDs
17
+
18
+ -- Then N queries, one per user
19
+ select * from orders where user_id = 1;
20
+ select * from orders where user_id = 2;
21
+ select * from orders where user_id = 3;
22
+ -- ... 97 more queries!
23
+
24
+ -- Total: 101 round trips to database
25
+ ```
26
+
27
+ **Correct (single batch query):**
28
+
29
+ ```sql
30
+ -- Collect IDs and query once with ANY
31
+ select * from orders where user_id = any(array[1, 2, 3, ...]);
32
+
33
+ -- Or use JOIN instead of loop
34
+ select u.id, u.name, o.*
35
+ from users u
36
+ left join orders o on o.user_id = u.id
37
+ where u.active = true;
38
+
39
+ -- Total: 1 round trip
40
+ ```
41
+
42
+ Application pattern:
43
+
44
+ ```sql
45
+ -- Instead of looping in application code:
46
+ -- for user in users: db.query("SELECT * FROM orders WHERE user_id = $1", user.id)
47
+
48
+ -- Pass array parameter:
49
+ select * from orders where user_id = any($1::bigint[]);
50
+ -- Application passes: [1, 2, 3, 4, 5, ...]
51
+ ```
52
+
53
+ Reference: [N+1 Query Problem](https://supabase.com/docs/guides/database/query-optimization)
@@ -0,0 +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)
@@ -0,0 +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)
@@ -0,0 +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)
@@ -0,0 +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)
@@ -0,0 +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)
@@ -0,0 +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)
@@ -0,0 +1,45 @@
1
+ ---
2
+ title: Use EXPLAIN ANALYZE to Diagnose Slow Queries
3
+ impact: LOW-MEDIUM
4
+ impactDescription: Identify exact bottlenecks in query execution
5
+ tags: explain, analyze, diagnostics, query-plan
6
+ ---
7
+
8
+ ## Use EXPLAIN ANALYZE to Diagnose Slow Queries
9
+
10
+ EXPLAIN ANALYZE executes the query and shows actual timings, revealing the true performance bottlenecks.
11
+
12
+ **Incorrect (guessing at performance issues):**
13
+
14
+ ```sql
15
+ -- Query is slow, but why?
16
+ select * from orders where customer_id = 123 and status = 'pending';
17
+ -- "It must be missing an index" - but which one?
18
+ ```
19
+
20
+ **Correct (use EXPLAIN ANALYZE):**
21
+
22
+ ```sql
23
+ explain (analyze, buffers, format text)
24
+ select * from orders where customer_id = 123 and status = 'pending';
25
+
26
+ -- Output reveals the issue:
27
+ -- Seq Scan on orders (cost=0.00..25000.00 rows=50 width=100) (actual time=0.015..450.123 rows=50 loops=1)
28
+ -- Filter: ((customer_id = 123) AND (status = 'pending'::text))
29
+ -- Rows Removed by Filter: 999950
30
+ -- Buffers: shared hit=5000 read=15000
31
+ -- Planning Time: 0.150 ms
32
+ -- Execution Time: 450.500 ms
33
+ ```
34
+
35
+ Key things to look for:
36
+
37
+ ```sql
38
+ -- Seq Scan on large tables = missing index
39
+ -- Rows Removed by Filter = poor selectivity or missing index
40
+ -- Buffers: read >> hit = data not cached, needs more memory
41
+ -- Nested Loop with high loops = consider different join strategy
42
+ -- Sort Method: external merge = work_mem too low
43
+ ```
44
+
45
+ Reference: [EXPLAIN](https://supabase.com/docs/guides/database/inspect)
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Enable pg_stat_statements for Query Analysis
3
+ impact: LOW-MEDIUM
4
+ impactDescription: Identify top resource-consuming queries
5
+ tags: pg-stat-statements, monitoring, statistics, performance
6
+ ---
7
+
8
+ ## Enable pg_stat_statements for Query Analysis
9
+
10
+ pg_stat_statements tracks execution statistics for all queries, helping identify slow and frequent queries.
11
+
12
+ **Incorrect (no visibility into query patterns):**
13
+
14
+ ```sql
15
+ -- Database is slow, but which queries are the problem?
16
+ -- No way to know without pg_stat_statements
17
+ ```
18
+
19
+ **Correct (enable and query pg_stat_statements):**
20
+
21
+ ```sql
22
+ -- Enable the extension
23
+ create extension if not exists pg_stat_statements;
24
+
25
+ -- Find slowest queries by total time
26
+ select
27
+ calls,
28
+ round(total_exec_time::numeric, 2) as total_time_ms,
29
+ round(mean_exec_time::numeric, 2) as mean_time_ms,
30
+ query
31
+ from pg_stat_statements
32
+ order by total_exec_time desc
33
+ limit 10;
34
+
35
+ -- Find most frequent queries
36
+ select calls, query
37
+ from pg_stat_statements
38
+ order by calls desc
39
+ limit 10;
40
+
41
+ -- Reset statistics after optimization
42
+ select pg_stat_statements_reset();
43
+ ```
44
+
45
+ Key metrics to monitor:
46
+
47
+ ```sql
48
+ -- Queries with high mean time (candidates for optimization)
49
+ select query, mean_exec_time, calls
50
+ from pg_stat_statements
51
+ where mean_exec_time > 100 -- > 100ms average
52
+ order by mean_exec_time desc;
53
+ ```
54
+
55
+ Reference: [pg_stat_statements](https://supabase.com/docs/guides/database/extensions/pg_stat_statements)
@@ -0,0 +1,55 @@
1
+ ---
2
+ title: Maintain Table Statistics with VACUUM and ANALYZE
3
+ impact: MEDIUM
4
+ impactDescription: 2-10x better query plans with accurate statistics
5
+ tags: vacuum, analyze, statistics, maintenance, autovacuum
6
+ ---
7
+
8
+ ## Maintain Table Statistics with VACUUM and ANALYZE
9
+
10
+ Outdated statistics cause the query planner to make poor decisions. VACUUM reclaims space, ANALYZE updates statistics.
11
+
12
+ **Incorrect (stale statistics):**
13
+
14
+ ```sql
15
+ -- Table has 1M rows but stats say 1000
16
+ -- Query planner chooses wrong strategy
17
+ explain select * from orders where status = 'pending';
18
+ -- Shows: Seq Scan (because stats show small table)
19
+ -- Actually: Index Scan would be much faster
20
+ ```
21
+
22
+ **Correct (maintain fresh statistics):**
23
+
24
+ ```sql
25
+ -- Manually analyze after large data changes
26
+ analyze orders;
27
+
28
+ -- Analyze specific columns used in WHERE clauses
29
+ analyze orders (status, created_at);
30
+
31
+ -- Check when tables were last analyzed
32
+ select
33
+ relname,
34
+ last_vacuum,
35
+ last_autovacuum,
36
+ last_analyze,
37
+ last_autoanalyze
38
+ from pg_stat_user_tables
39
+ order by last_analyze nulls first;
40
+ ```
41
+
42
+ Autovacuum tuning for busy tables:
43
+
44
+ ```sql
45
+ -- Increase frequency for high-churn tables
46
+ alter table orders set (
47
+ autovacuum_vacuum_scale_factor = 0.05, -- Vacuum at 5% dead tuples (default 20%)
48
+ autovacuum_analyze_scale_factor = 0.02 -- Analyze at 2% changes (default 10%)
49
+ );
50
+
51
+ -- Check autovacuum status
52
+ select * from pg_stat_progress_vacuum;
53
+ ```
54
+
55
+ Reference: [VACUUM](https://supabase.com/docs/guides/database/database-size#vacuum-operations)
@@ -0,0 +1,44 @@
1
+ ---
2
+ title: Create Composite Indexes for Multi-Column Queries
3
+ impact: HIGH
4
+ impactDescription: 5-10x faster multi-column queries
5
+ tags: indexes, composite-index, multi-column, query-optimization
6
+ ---
7
+
8
+ ## Create Composite Indexes for Multi-Column Queries
9
+
10
+ When queries filter on multiple columns, a composite index is more efficient than separate single-column indexes.
11
+
12
+ **Incorrect (separate indexes require bitmap scan):**
13
+
14
+ ```sql
15
+ -- Two separate indexes
16
+ create index orders_status_idx on orders (status);
17
+ create index orders_created_idx on orders (created_at);
18
+
19
+ -- Query must combine both indexes (slower)
20
+ select * from orders where status = 'pending' and created_at > '2024-01-01';
21
+ ```
22
+
23
+ **Correct (composite index):**
24
+
25
+ ```sql
26
+ -- Single composite index (leftmost column first for equality checks)
27
+ create index orders_status_created_idx on orders (status, created_at);
28
+
29
+ -- Query uses one efficient index scan
30
+ select * from orders where status = 'pending' and created_at > '2024-01-01';
31
+ ```
32
+
33
+ **Column order matters** - place equality columns first, range columns last:
34
+
35
+ ```sql
36
+ -- Good: status (=) before created_at (>)
37
+ create index idx on orders (status, created_at);
38
+
39
+ -- Works for: WHERE status = 'pending'
40
+ -- Works for: WHERE status = 'pending' AND created_at > '2024-01-01'
41
+ -- Does NOT work for: WHERE created_at > '2024-01-01' (leftmost prefix rule)
42
+ ```
43
+
44
+ Reference: [Multicolumn Indexes](https://www.postgresql.org/docs/current/indexes-multicolumn.html)
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: Use Covering Indexes to Avoid Table Lookups
3
+ impact: MEDIUM-HIGH
4
+ impactDescription: 2-5x faster queries by eliminating heap fetches
5
+ tags: indexes, covering-index, include, index-only-scan
6
+ ---
7
+
8
+ ## Use Covering Indexes to Avoid Table Lookups
9
+
10
+ Covering indexes include all columns needed by a query, enabling index-only scans that skip the table entirely.
11
+
12
+ **Incorrect (index scan + heap fetch):**
13
+
14
+ ```sql
15
+ create index users_email_idx on users (email);
16
+
17
+ -- Must fetch name and created_at from table heap
18
+ select email, name, created_at from users where email = 'user@example.com';
19
+ ```
20
+
21
+ **Correct (index-only scan with INCLUDE):**
22
+
23
+ ```sql
24
+ -- Include non-searchable columns in the index
25
+ create index users_email_idx on users (email) include (name, created_at);
26
+
27
+ -- All columns served from index, no table access needed
28
+ select email, name, created_at from users where email = 'user@example.com';
29
+ ```
30
+
31
+ Use INCLUDE for columns you SELECT but don't filter on:
32
+
33
+ ```sql
34
+ -- Searching by status, but also need customer_id and total
35
+ create index orders_status_idx on orders (status) include (customer_id, total);
36
+
37
+ select status, customer_id, total from orders where status = 'shipped';
38
+ ```
39
+
40
+ Reference: [Index-Only Scans](https://www.postgresql.org/docs/current/indexes-index-only-scans.html)
@@ -0,0 +1,48 @@
1
+ ---
2
+ title: Choose the Right Index Type for Your Data
3
+ impact: HIGH
4
+ impactDescription: 10-100x improvement with correct index type
5
+ tags: indexes, btree, gin, gist, brin, hash, index-types
6
+ ---
7
+
8
+ ## Choose the Right Index Type for Your Data
9
+
10
+ Different index types excel at different query patterns. The default B-tree isn't always optimal.
11
+
12
+ **Incorrect (B-tree for JSONB containment):**
13
+
14
+ ```sql
15
+ -- B-tree cannot optimize containment operators
16
+ create index products_attrs_idx on products (attributes);
17
+ select * from products where attributes @> '{"color": "red"}';
18
+ -- Full table scan - B-tree doesn't support @> operator
19
+ ```
20
+
21
+ **Correct (GIN for JSONB):**
22
+
23
+ ```sql
24
+ -- GIN supports @>, ?, ?&, ?| operators
25
+ create index products_attrs_idx on products using gin (attributes);
26
+ select * from products where attributes @> '{"color": "red"}';
27
+ ```
28
+
29
+ Index type guide:
30
+
31
+ ```sql
32
+ -- B-tree (default): =, <, >, BETWEEN, IN, IS NULL
33
+ create index users_created_idx on users (created_at);
34
+
35
+ -- GIN: arrays, JSONB, full-text search
36
+ create index posts_tags_idx on posts using gin (tags);
37
+
38
+ -- GiST: geometric data, range types, nearest-neighbor (KNN) queries
39
+ create index locations_idx on places using gist (location);
40
+
41
+ -- BRIN: large time-series tables (10-100x smaller)
42
+ create index events_time_idx on events using brin (created_at);
43
+
44
+ -- Hash: equality-only (slightly faster than B-tree for =)
45
+ create index sessions_token_idx on sessions using hash (token);
46
+ ```
47
+
48
+ Reference: [Index Types](https://www.postgresql.org/docs/current/indexes-types.html)