@evertonferreira96/agents 0.0.0-stage → 0.1.0

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 (258) hide show
  1. package/.claude/agents/api.md +45 -0
  2. package/.claude/agents/app.md +41 -0
  3. package/.claude/agents/architect.md +49 -0
  4. package/.claude/agents/infra.md +27 -0
  5. package/.claude/agents/product.md +58 -0
  6. package/.claude/agents/quick.md +33 -0
  7. package/.claude/agents/security.md +39 -0
  8. package/.claude/agents/ui.md +54 -0
  9. package/.claude/agents/verifier.md +56 -0
  10. package/.claude/agents/web.md +41 -0
  11. package/.claude/hooks/config-update-check.mjs +14 -0
  12. package/.claude/hooks/context-budget.mjs +51 -0
  13. package/.claude/hooks/graphify-update.sh +16 -0
  14. package/.claude/hooks/guard-bash.sh +64 -0
  15. package/.claude/hooks/orchestrator-guard.sh +49 -0
  16. package/.claude/hooks/post-compact.sh +26 -0
  17. package/.claude/hooks/readonly-guard.sh +54 -0
  18. package/.claude/hooks/stop-verify.sh +52 -0
  19. package/.claude/rules/api.md +21 -0
  20. package/.claude/rules/db.md +9 -0
  21. package/.claude/rules/delivery-diagram.md +16 -0
  22. package/.claude/rules/git-workflow.md +34 -0
  23. package/.claude/rules/graphify.md +3 -0
  24. package/.claude/rules/mobile.md +22 -0
  25. package/.claude/rules/tickets.md +9 -0
  26. package/.claude/rules/ui.md +14 -0
  27. package/.claude/rules/web.md +27 -0
  28. package/.claude/settings.json +114 -0
  29. package/.claude/skills/animate/RECIPES.md +324 -0
  30. package/.claude/skills/animate/SKILL.md +208 -0
  31. package/.claude/skills/animate/agents/openai.yaml +5 -0
  32. package/.claude/skills/animate-expo/RECIPES.md +385 -0
  33. package/.claude/skills/animate-expo/SKILL.md +264 -0
  34. package/.claude/skills/animate-expo/agents/openai.yaml +5 -0
  35. package/.claude/skills/animation-performance/SKILL.md +223 -0
  36. package/.claude/skills/animation-performance/agents/openai.yaml +5 -0
  37. package/.claude/skills/apple-design/SKILL.md +291 -0
  38. package/.claude/skills/apple-design/agents/openai.yaml +5 -0
  39. package/.claude/skills/arch-api/SKILL.md +291 -0
  40. package/.claude/skills/arch-api/agents/openai.yaml +3 -0
  41. package/.claude/skills/arch-api/references/common.md +174 -0
  42. package/.claude/skills/arch-api/references/contract.md +289 -0
  43. package/.claude/skills/arch-api/references/domain.md +301 -0
  44. package/.claude/skills/arch-api/references/endpoints.md +184 -0
  45. package/.claude/skills/arch-api/references/review.md +228 -0
  46. package/.claude/skills/arch-api/references/security.md +151 -0
  47. package/.claude/skills/arch-app/SKILL.md +278 -0
  48. package/.claude/skills/arch-app/agents/openai.yaml +3 -0
  49. package/.claude/skills/arch-app/references/navigation-session.md +257 -0
  50. package/.claude/skills/arch-app/references/review.md +155 -0
  51. package/.claude/skills/arch-app/references/screens.md +214 -0
  52. package/.claude/skills/arch-app/references/services.md +301 -0
  53. package/.claude/skills/arch-app/references/ui-mobile.md +124 -0
  54. package/.claude/skills/arch-db/SKILL.md +181 -0
  55. package/.claude/skills/arch-db/agents/openai.yaml +3 -0
  56. package/.claude/skills/arch-db/references/indexes-queries.md +251 -0
  57. package/.claude/skills/arch-db/references/migrations.md +191 -0
  58. package/.claude/skills/arch-db/references/modeling.md +214 -0
  59. package/.claude/skills/arch-db/references/mysql.md +262 -0
  60. package/.claude/skills/arch-db/references/pooling-ops.md +112 -0
  61. package/.claude/skills/arch-db/references/review.md +143 -0
  62. package/.claude/skills/arch-db/references/transactions-locks.md +141 -0
  63. package/.claude/skills/arch-web/SKILL.md +307 -0
  64. package/.claude/skills/arch-web/agents/openai.yaml +3 -0
  65. package/.claude/skills/arch-web/references/auth-session-env.md +165 -0
  66. package/.claude/skills/arch-web/references/blocks.md +198 -0
  67. package/.claude/skills/arch-web/references/cache.md +124 -0
  68. package/.claude/skills/arch-web/references/review.md +142 -0
  69. package/.claude/skills/arch-web/references/services.md +297 -0
  70. package/.claude/skills/arch-web/references/tests.md +159 -0
  71. package/.claude/skills/arch-web/references/ui-forms.md +143 -0
  72. package/.claude/skills/break-ui/CATALOG.md +135 -0
  73. package/.claude/skills/break-ui/SKILL.md +176 -0
  74. package/.claude/skills/break-ui/agents/openai.yaml +5 -0
  75. package/.claude/skills/brief/SKILL.md +91 -0
  76. package/.claude/skills/brief/agents/openai.yaml +3 -0
  77. package/.claude/skills/diagnosing-bugs/SKILL.md +138 -0
  78. package/.claude/skills/diagnosing-bugs/agents/openai.yaml +3 -0
  79. package/.claude/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
  80. package/.claude/skills/emil-design-eng/SKILL.md +675 -0
  81. package/.claude/skills/emil-design-eng/agents/openai.yaml +5 -0
  82. package/.claude/skills/find-animation-opportunities/SKILL.md +141 -0
  83. package/.claude/skills/find-animation-opportunities/agents/openai.yaml +5 -0
  84. package/.claude/skills/graphify/.graphify_version +1 -0
  85. package/.claude/skills/graphify/SKILL.md +742 -0
  86. package/.claude/skills/graphify/agents/openai.yaml +3 -0
  87. package/.claude/skills/graphify/references/add-watch.md +56 -0
  88. package/.claude/skills/graphify/references/exports.md +91 -0
  89. package/.claude/skills/graphify/references/extraction-spec.md +70 -0
  90. package/.claude/skills/graphify/references/github-and-merge.md +46 -0
  91. package/.claude/skills/graphify/references/hooks.md +33 -0
  92. package/.claude/skills/graphify/references/query.md +317 -0
  93. package/.claude/skills/graphify/references/transcribe.md +52 -0
  94. package/.claude/skills/graphify/references/update.md +221 -0
  95. package/.claude/skills/grill-me/SKILL.md +7 -0
  96. package/.claude/skills/grill-me/agents/openai.yaml +5 -0
  97. package/.claude/skills/grill-with-docs/SKILL.md +64 -0
  98. package/.claude/skills/grill-with-docs/agents/openai.yaml +5 -0
  99. package/.claude/skills/grilling/SKILL.md +30 -0
  100. package/.claude/skills/grilling/agents/openai.yaml +3 -0
  101. package/.claude/skills/handoff/SKILL.md +28 -0
  102. package/.claude/skills/handoff/agents/openai.yaml +5 -0
  103. package/.claude/skills/impeccable/SKILL.md +89 -0
  104. package/.claude/skills/impeccable/agents/openai.yaml +5 -0
  105. package/.claude/skills/impeccable/reference/adapt.md +318 -0
  106. package/.claude/skills/impeccable/reference/adapt.native.md +58 -0
  107. package/.claude/skills/impeccable/reference/android.md +46 -0
  108. package/.claude/skills/impeccable/reference/animate.md +89 -0
  109. package/.claude/skills/impeccable/reference/audit.md +137 -0
  110. package/.claude/skills/impeccable/reference/audit.native.md +139 -0
  111. package/.claude/skills/impeccable/reference/bolder.md +33 -0
  112. package/.claude/skills/impeccable/reference/clarify.md +94 -0
  113. package/.claude/skills/impeccable/reference/colorize.md +86 -0
  114. package/.claude/skills/impeccable/reference/component-review.md +63 -0
  115. package/.claude/skills/impeccable/reference/craft-floor.md +44 -0
  116. package/.claude/skills/impeccable/reference/craft.md +5 -0
  117. package/.claude/skills/impeccable/reference/critique.md +809 -0
  118. package/.claude/skills/impeccable/reference/degraded/asset-producer.md +42 -0
  119. package/.claude/skills/impeccable/reference/degraded/documenter.md +24 -0
  120. package/.claude/skills/impeccable/reference/degraded/finish-reviewer.md +38 -0
  121. package/.claude/skills/impeccable/reference/degraded/manual-edit-applier.md +92 -0
  122. package/.claude/skills/impeccable/reference/delight.md +70 -0
  123. package/.claude/skills/impeccable/reference/distill.md +111 -0
  124. package/.claude/skills/impeccable/reference/doctor.md +54 -0
  125. package/.claude/skills/impeccable/reference/document.md +416 -0
  126. package/.claude/skills/impeccable/reference/extract.md +69 -0
  127. package/.claude/skills/impeccable/reference/generate.md +101 -0
  128. package/.claude/skills/impeccable/reference/harden.md +345 -0
  129. package/.claude/skills/impeccable/reference/hooks.md +113 -0
  130. package/.claude/skills/impeccable/reference/init.md +131 -0
  131. package/.claude/skills/impeccable/reference/ios.md +51 -0
  132. package/.claude/skills/impeccable/reference/layout.md +84 -0
  133. package/.claude/skills/impeccable/reference/live-setup.md +104 -0
  134. package/.claude/skills/impeccable/reference/live.md +325 -0
  135. package/.claude/skills/impeccable/reference/mode-operate.md +21 -0
  136. package/.claude/skills/impeccable/reference/mode-persuade.md +19 -0
  137. package/.claude/skills/impeccable/reference/mode-read.md +21 -0
  138. package/.claude/skills/impeccable/reference/new-work.md +154 -0
  139. package/.claude/skills/impeccable/reference/onboard.md +234 -0
  140. package/.claude/skills/impeccable/reference/operate.md +61 -0
  141. package/.claude/skills/impeccable/reference/optimize.md +258 -0
  142. package/.claude/skills/impeccable/reference/overdrive.md +127 -0
  143. package/.claude/skills/impeccable/reference/polish.md +105 -0
  144. package/.claude/skills/impeccable/reference/quieter.md +99 -0
  145. package/.claude/skills/impeccable/reference/region-map.md +26 -0
  146. package/.claude/skills/impeccable/reference/routing.md +24 -0
  147. package/.claude/skills/impeccable/reference/shape.md +59 -0
  148. package/.claude/skills/impeccable/reference/typeset.md +80 -0
  149. package/.claude/skills/impeccable/reference/visualize.md +47 -0
  150. package/.claude/skills/impeccable/scripts/VERSION +1 -0
  151. package/.claude/skills/impeccable/scripts/command-metadata.json +98 -0
  152. package/.claude/skills/impeccable/scripts/data/font-index-failures.json +121 -0
  153. package/.claude/skills/impeccable/scripts/data/font-index.json +1 -0
  154. package/.claude/skills/impeccable/scripts/impeccable +206 -0
  155. package/.claude/skills/impeccable/scripts/impeccable.cmd +214 -0
  156. package/.claude/skills/impeccable/scripts/live-browser-dom.js +281 -0
  157. package/.claude/skills/impeccable/scripts/live-browser-ignores.js +242 -0
  158. package/.claude/skills/impeccable/scripts/live-browser-session.js +148 -0
  159. package/.claude/skills/impeccable/scripts/live-browser.js +13532 -0
  160. package/.claude/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  161. package/.claude/skills/improve-animations/AUDIT.md +115 -0
  162. package/.claude/skills/improve-animations/PLAN-TEMPLATE.md +73 -0
  163. package/.claude/skills/improve-animations/SKILL.md +110 -0
  164. package/.claude/skills/improve-animations/agents/openai.yaml +5 -0
  165. package/.claude/skills/mobile-native/SKILL.md +311 -0
  166. package/.claude/skills/mobile-native/agents/openai.yaml +3 -0
  167. package/.claude/skills/orchestrate/SKILL.md +181 -0
  168. package/.claude/skills/orchestrate/agents/openai.yaml +3 -0
  169. package/.claude/skills/pick-ui-library/SKILL.md +85 -0
  170. package/.claude/skills/pick-ui-library/agents/openai.yaml +5 -0
  171. package/.claude/skills/ponytail/SKILL.md +52 -0
  172. package/.claude/skills/ponytail/agents/openai.yaml +3 -0
  173. package/.claude/skills/ponytail-audit/SKILL.md +103 -0
  174. package/.claude/skills/ponytail-audit/agents/openai.yaml +3 -0
  175. package/.claude/skills/ponytail-debt/SKILL.md +44 -0
  176. package/.claude/skills/ponytail-debt/agents/openai.yaml +3 -0
  177. package/.claude/skills/ponytail-review/SKILL.md +101 -0
  178. package/.claude/skills/ponytail-review/agents/openai.yaml +3 -0
  179. package/.claude/skills/postgres-best-practices/SKILL.md +42 -0
  180. package/.claude/skills/postgres-best-practices/agents/openai.yaml +3 -0
  181. package/.claude/skills/postgres-best-practices/references/backup-restore.md +372 -0
  182. package/.claude/skills/postgres-best-practices/references/bulk-loading.md +315 -0
  183. package/.claude/skills/postgres-best-practices/references/connection-pooling.md +310 -0
  184. package/.claude/skills/postgres-best-practices/references/hot-standby.md +221 -0
  185. package/.claude/skills/postgres-best-practices/references/indexing.md +318 -0
  186. package/.claude/skills/postgres-best-practices/references/logical-replication.md +610 -0
  187. package/.claude/skills/postgres-best-practices/references/major-version-upgrades.md +334 -0
  188. package/.claude/skills/postgres-best-practices/references/performance-diagnostics.md +553 -0
  189. package/.claude/skills/postgres-best-practices/references/query-optimization.md +294 -0
  190. package/.claude/skills/postgres-best-practices/references/query-patterns.md +566 -0
  191. package/.claude/skills/postgres-best-practices/references/schema-design.md +362 -0
  192. package/.claude/skills/postgres-best-practices/references/security-roles.md +489 -0
  193. package/.claude/skills/postgres-best-practices/references/transaction-isolation.md +344 -0
  194. package/.claude/skills/project-docs/SKILL.md +330 -0
  195. package/.claude/skills/project-docs/agents/openai.yaml +3 -0
  196. package/.claude/skills/prototype/PICKER.md +197 -0
  197. package/.claude/skills/prototype/SKILL.md +98 -0
  198. package/.claude/skills/prototype/agents/openai.yaml +5 -0
  199. package/.claude/skills/retro/SKILL.md +43 -0
  200. package/.claude/skills/retro/agents/openai.yaml +5 -0
  201. package/.claude/skills/review/SKILL.md +74 -0
  202. package/.claude/skills/review/agents/openai.yaml +3 -0
  203. package/.claude/skills/review/references/smells.md +23 -0
  204. package/.claude/skills/review-animations/SKILL.md +120 -0
  205. package/.claude/skills/review-animations/STANDARDS.md +187 -0
  206. package/.claude/skills/review-animations/agents/openai.yaml +5 -0
  207. package/.claude/skills/tdd/SKILL.md +38 -0
  208. package/.claude/skills/tdd/agents/openai.yaml +3 -0
  209. package/.claude/skills/tdd/mocking.md +59 -0
  210. package/.claude/skills/tdd/tests.md +77 -0
  211. package/.claude/skills/triage/SKILL.md +58 -0
  212. package/.claude/skills/triage/agents/openai.yaml +3 -0
  213. package/.claude/skills/ui-ux-pro-max/SKILL.md +378 -0
  214. package/.claude/skills/ui-ux-pro-max/agents/openai.yaml +5 -0
  215. package/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
  216. package/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
  217. package/.claude/skills/ui-ux-pro-max/data/icons.csv +101 -0
  218. package/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
  219. package/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
  220. package/.claude/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  221. package/.claude/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  222. package/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  223. package/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  224. package/.claude/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  225. package/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  226. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  227. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  228. package/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  229. package/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  230. package/.claude/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  231. package/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  232. package/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  233. package/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  234. package/.claude/skills/ui-ux-pro-max/data/styles.csv +68 -0
  235. package/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
  236. package/.claude/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  237. package/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  238. package/.claude/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  239. package/.claude/skills/ui-ux-pro-max/scripts/core.py +253 -0
  240. package/.claude/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  241. package/.claude/skills/ui-ux-pro-max/scripts/search.py +114 -0
  242. package/.claude/skills/writing-for-agents/SKILL-MECHANICS.md +22 -0
  243. package/.claude/skills/writing-for-agents/SKILL.md +81 -0
  244. package/.claude/skills/writing-for-agents/agents/openai.yaml +3 -0
  245. package/.worktreeinclude +3 -0
  246. package/AGENTS.md +44 -0
  247. package/README.md +14 -2
  248. package/VERSION +1 -0
  249. package/bin/agents.mjs +45 -0
  250. package/docs/adr/README.md +31 -0
  251. package/docs/brief-template.md +3 -0
  252. package/docs/plans/README.md +73 -0
  253. package/package.json +46 -4
  254. package/scripts/bootstrap.mjs +188 -0
  255. package/scripts/check-catalog.mjs +43 -0
  256. package/scripts/skills-update.mjs +51 -0
  257. package/skills-lock.json +269 -0
  258. package/templates/CLAUDE.project.md +41 -0
@@ -0,0 +1,553 @@
1
+ # Performance Diagnostics Reference
2
+
3
+ ## Contents
4
+ - Essential pg_stat views
5
+ - Table health diagnostics
6
+ - Index health diagnostics
7
+ - Active query analysis
8
+ - Lock analysis
9
+ - VACUUM and bloat
10
+ - Connection management
11
+ - pg_stat_statements setup and queries
12
+
13
+ ## Essential pg_stat Views
14
+
15
+ | View | What it tells you |
16
+ |------|------------------|
17
+ | `pg_stat_user_tables` | Seq scans, index scans, row counts, dead tuples, last vacuum/analyze |
18
+ | `pg_stat_user_indexes` | Index usage counts, tuple reads |
19
+ | `pg_stat_activity` | Currently running queries, wait events, state |
20
+ | `pg_stat_statements` | Top queries by time, calls, rows (extension) |
21
+ | `pg_stat_bgwriter` | Checkpoint frequency, buffer allocation |
22
+ | `pg_stat_io` (PG16+) | I/O statistics by backend type. PG18+ adds byte-level columns and per-backend stats |
23
+ | `pg_locks` | Current locks held and awaited |
24
+
25
+ ## Table Health Diagnostics
26
+
27
+ ### Tables with Most Sequential Scans
28
+
29
+ ```sql
30
+ SELECT
31
+ schemaname,
32
+ relname AS table_name,
33
+ seq_scan,
34
+ seq_tup_read,
35
+ idx_scan,
36
+ pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
37
+ CASE WHEN seq_scan + idx_scan > 0
38
+ THEN round(100.0 * idx_scan / (seq_scan + idx_scan), 1)
39
+ ELSE 0 END AS idx_scan_pct
40
+ FROM pg_stat_user_tables
41
+ WHERE seq_scan > 0
42
+ ORDER BY seq_tup_read DESC
43
+ LIMIT 20;
44
+ ```
45
+
46
+ High `seq_tup_read` with low `idx_scan_pct` = missing index opportunity.
47
+
48
+ ### Tables with High Dead Tuple Ratio
49
+
50
+ ```sql
51
+ SELECT
52
+ schemaname,
53
+ relname AS table_name,
54
+ n_live_tup,
55
+ n_dead_tup,
56
+ CASE WHEN n_live_tup > 0
57
+ THEN round(100.0 * n_dead_tup / n_live_tup, 1)
58
+ ELSE 0 END AS dead_pct,
59
+ last_autovacuum,
60
+ last_autoanalyze
61
+ FROM pg_stat_user_tables
62
+ WHERE n_dead_tup > 1000
63
+ ORDER BY n_dead_tup DESC
64
+ LIMIT 20;
65
+ ```
66
+
67
+ `dead_pct` > 20% = VACUUM is falling behind. Check autovacuum settings.
68
+
69
+ ### Relation Storage Breakdown
70
+
71
+ ```sql
72
+ SELECT
73
+ schemaname,
74
+ tablename,
75
+ pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS total_size,
76
+ pg_size_pretty(
77
+ pg_total_relation_size(schemaname || '.' || tablename) -
78
+ pg_relation_size(schemaname || '.' || tablename)
79
+ ) AS index_and_toast_size
80
+ FROM pg_tables
81
+ WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
82
+ ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC
83
+ LIMIT 20;
84
+ ```
85
+
86
+ This separates heap size from indexes and TOAST; it is not a bloat estimate. For bloat measurements, use the `pgstattuple` extension (requires superuser or elevated privileges):
87
+
88
+ ```sql
89
+ CREATE EXTENSION IF NOT EXISTS pgstattuple;
90
+ SELECT * FROM pgstattuple('orders');
91
+ -- dead_tuple_percent > 20% = significant bloat
92
+ ```
93
+
94
+ ## Index Health Diagnostics
95
+
96
+ ### Unused Indexes (Wasting Space and Slowing Writes)
97
+
98
+ ```sql
99
+ SELECT
100
+ schemaname,
101
+ relname AS table_name,
102
+ indexrelname AS index_name,
103
+ pg_size_pretty(pg_relation_size(indexrelid)) AS index_size,
104
+ idx_scan AS times_used
105
+ FROM pg_stat_user_indexes
106
+ WHERE idx_scan = 0
107
+ AND indexrelname NOT LIKE '%_pkey' -- exclude primary keys
108
+ ORDER BY pg_relation_size(indexrelid) DESC;
109
+ ```
110
+
111
+ ### Index Hit Rate (Should Be > 99%)
112
+
113
+ ```sql
114
+ SELECT
115
+ sum(idx_blks_hit) AS idx_hit,
116
+ sum(idx_blks_read) AS idx_read,
117
+ CASE WHEN sum(idx_blks_hit + idx_blks_read) > 0
118
+ THEN round(100.0 * sum(idx_blks_hit) / sum(idx_blks_hit + idx_blks_read), 2)
119
+ ELSE 100 END AS hit_rate_pct
120
+ FROM pg_statio_user_indexes;
121
+ ```
122
+
123
+ ### Table Cache Hit Rate (Should Be > 99%)
124
+
125
+ ```sql
126
+ SELECT
127
+ sum(heap_blks_hit) AS heap_hit,
128
+ sum(heap_blks_read) AS heap_read,
129
+ CASE WHEN sum(heap_blks_hit + heap_blks_read) > 0
130
+ THEN round(100.0 * sum(heap_blks_hit) / sum(heap_blks_hit + heap_blks_read), 2)
131
+ ELSE 100 END AS hit_rate_pct
132
+ FROM pg_statio_user_tables;
133
+ ```
134
+
135
+ Hit rate < 99% = consider increasing `shared_buffers` or optimizing queries.
136
+
137
+ ### shared_buffers Tuning
138
+
139
+ `shared_buffers` is the primary in-memory page cache. Every page read from disk passes through it, and frequently accessed pages stay cached here.
140
+
141
+ **Sizing rule of thumb**: Start at **25% of total RAM**. Going higher (up to ~40%) can help on read-heavy workloads with large working sets, but beyond that the OS page cache becomes less effective and returns diminish.
142
+
143
+ ```sql
144
+ -- Current setting
145
+ SHOW shared_buffers;
146
+
147
+ -- Effective cache (shared_buffers + OS page cache estimate — planner hint only)
148
+ SHOW effective_cache_size;
149
+ ```
150
+
151
+ **Diagnostic: Is shared_buffers large enough?**
152
+
153
+ Combine the cache hit rate above with a working set estimate:
154
+
155
+ ```sql
156
+ -- Total size of all user tables and indexes
157
+ SELECT
158
+ pg_size_pretty(sum(pg_total_relation_size(relid))) AS total_data_size
159
+ FROM pg_stat_user_tables;
160
+
161
+ -- Compare to shared_buffers
162
+ SELECT
163
+ setting || ' ' || unit AS shared_buffers,
164
+ pg_size_pretty(setting::bigint * 8192) AS shared_buffers_bytes
165
+ FROM pg_settings
166
+ WHERE name = 'shared_buffers';
167
+ ```
168
+
169
+ If your hot data (frequently accessed tables + their indexes) significantly exceeds `shared_buffers`, the hit rate drops and you'll see more `shared read` in EXPLAIN output.
170
+
171
+ **When to increase shared_buffers:**
172
+ - Table/index cache hit rate consistently below 99%
173
+ - `shared read` dominates `shared hit` in EXPLAIN plans for hot queries
174
+ - Server has available RAM (check OS isn't swapping)
175
+
176
+ **When NOT to increase shared_buffers:**
177
+ - Low hit rate caused by full table scans (fix with indexes or query changes, not more cache)
178
+ - Server is already memory-constrained (each connection also uses `work_mem`, `maintenance_work_mem`, etc.)
179
+ - Hit rate is already 99%+ (adding more cache won't help)
180
+
181
+ **After changing shared_buffers:**
182
+ - Requires a server restart (`pg_ctl restart`)
183
+ - Update `effective_cache_size` to roughly `shared_buffers + estimated OS page cache` (typically ~75% of total RAM)
184
+ - Monitor hit rates for a representative period after the change
185
+
186
+ **Per-table cache usage** (requires `pg_buffercache` extension):
187
+
188
+ ```sql
189
+ CREATE EXTENSION IF NOT EXISTS pg_buffercache;
190
+
191
+ SELECT
192
+ c.relname,
193
+ pg_size_pretty(count(*) * current_setting('block_size')::bigint) AS buffered,
194
+ round(100.0 * count(*) / (SELECT setting::int FROM pg_settings WHERE name = 'shared_buffers'), 1) AS pct_of_cache
195
+ FROM pg_buffercache b
196
+ JOIN pg_class c ON pg_relation_filenode(c.oid) = b.relfilenode
197
+ WHERE b.reldatabase = (SELECT oid FROM pg_database WHERE datname = current_database())
198
+ GROUP BY c.relname
199
+ ORDER BY count(*) DESC
200
+ LIMIT 20;
201
+ ```
202
+
203
+ This shows which tables/indexes are consuming the most shared_buffers — useful for identifying cache hogs or verifying that hot tables are actually cached.
204
+
205
+ ### Finding Missing Foreign Key Indexes
206
+
207
+ FK columns without indexes cause slow JOINs and slow CASCADE deletes:
208
+
209
+ ```sql
210
+ SELECT
211
+ c.conrelid::regclass AS table_name,
212
+ c.conname AS constraint_name,
213
+ pg_get_constraintdef(c.oid) AS constraint_definition
214
+ FROM pg_constraint c
215
+ WHERE c.contype = 'f'
216
+ AND NOT EXISTS (
217
+ SELECT 1 FROM pg_index i
218
+ WHERE i.indrelid = c.conrelid
219
+ AND i.indisvalid
220
+ AND i.indpred IS NULL
221
+ AND i.indnkeyatts >= cardinality(c.conkey)
222
+ AND (
223
+ SELECT array_agg(key_attnum ORDER BY ordinality)
224
+ FROM unnest(i.indkey::smallint[]) WITH ORDINALITY
225
+ AS keys(key_attnum, ordinality)
226
+ WHERE ordinality <= cardinality(c.conkey)
227
+ ) = c.conkey
228
+ );
229
+ ```
230
+
231
+ ### pg_stat_io (PG16+)
232
+
233
+ I/O statistics by backend type and context — helps identify I/O-heavy operations:
234
+
235
+ ```sql
236
+ SELECT
237
+ backend_type, object, context,
238
+ reads, read_time,
239
+ writes, write_time,
240
+ hits
241
+ FROM pg_stat_io
242
+ WHERE reads > 0 OR writes > 0
243
+ ORDER BY reads + writes DESC
244
+ LIMIT 10;
245
+ ```
246
+
247
+ ## Active Query Analysis
248
+
249
+ ### Currently Running Queries
250
+
251
+ ```sql
252
+ SELECT
253
+ pid,
254
+ now() - query_start AS duration,
255
+ state,
256
+ wait_event_type,
257
+ wait_event,
258
+ left(query, 100) AS query_preview
259
+ FROM pg_stat_activity
260
+ WHERE state != 'idle'
261
+ AND pid != pg_backend_pid()
262
+ ORDER BY duration DESC;
263
+ ```
264
+
265
+ ### Long-Running Queries (> 5 minutes)
266
+
267
+ ```sql
268
+ SELECT
269
+ pid,
270
+ now() - query_start AS duration,
271
+ usename,
272
+ application_name,
273
+ client_addr,
274
+ left(query, 200) AS query
275
+ FROM pg_stat_activity
276
+ WHERE state = 'active'
277
+ AND now() - query_start > interval '5 minutes'
278
+ AND pid != pg_backend_pid()
279
+ ORDER BY duration DESC;
280
+ ```
281
+
282
+ ### Cancel or Terminate a Query
283
+
284
+ ```sql
285
+ -- Replace 12345 with a PID selected from pg_stat_activity.
286
+ -- Graceful cancel (sends a cancel signal)
287
+ SELECT pg_cancel_backend(12345);
288
+
289
+ -- Force terminate (kills the connection)
290
+ SELECT pg_terminate_backend(12345);
291
+ ```
292
+
293
+ Do not target your current session (`pg_backend_pid()`). Prefer cancellation first; terminate only when cancellation does not resolve the problem.
294
+
295
+ ## Lock Analysis
296
+
297
+ ### Blocked Queries and What's Blocking Them
298
+
299
+ ```sql
300
+ SELECT
301
+ blocked.pid AS blocked_pid,
302
+ blocked.query AS blocked_query,
303
+ blocking.pid AS blocking_pid,
304
+ blocking.query AS blocking_query,
305
+ now() - blocked.query_start AS blocked_duration
306
+ FROM pg_stat_activity blocked
307
+ JOIN pg_locks bl ON bl.pid = blocked.pid
308
+ JOIN pg_locks kl ON kl.locktype = bl.locktype
309
+ AND kl.database IS NOT DISTINCT FROM bl.database
310
+ AND kl.relation IS NOT DISTINCT FROM bl.relation
311
+ AND kl.page IS NOT DISTINCT FROM bl.page
312
+ AND kl.tuple IS NOT DISTINCT FROM bl.tuple
313
+ AND kl.virtualxid IS NOT DISTINCT FROM bl.virtualxid
314
+ AND kl.transactionid IS NOT DISTINCT FROM bl.transactionid
315
+ AND kl.classid IS NOT DISTINCT FROM bl.classid
316
+ AND kl.objid IS NOT DISTINCT FROM bl.objid
317
+ AND kl.objsubid IS NOT DISTINCT FROM bl.objsubid
318
+ AND kl.pid != bl.pid
319
+ JOIN pg_stat_activity blocking ON blocking.pid = kl.pid
320
+ WHERE NOT bl.granted AND kl.granted;
321
+ ```
322
+
323
+ ### Lock Types Quick Reference
324
+
325
+ | Lock | Acquired by | Conflicts with |
326
+ |------|------------|----------------|
327
+ | `AccessShareLock` | SELECT | AccessExclusiveLock |
328
+ | `RowShareLock` | SELECT FOR UPDATE/SHARE | ExclusiveLock, AccessExclusiveLock |
329
+ | `RowExclusiveLock` | INSERT, UPDATE, DELETE | ShareLock, ShareRowExclusiveLock, ExclusiveLock, AccessExclusiveLock |
330
+ | `ShareLock` | CREATE INDEX (non-concurrent) | RowExclusiveLock and above |
331
+ | `AccessExclusiveLock` | ALTER TABLE, DROP TABLE, VACUUM FULL | Everything |
332
+
333
+ ### Advisory Locks
334
+
335
+ For application-level coordination without row locking:
336
+
337
+ ```sql
338
+ -- Choose one acquisition method, not both.
339
+ -- Blocking acquisition:
340
+ SELECT pg_advisory_lock(hashtext('my_job_name'));
341
+
342
+ -- Release once for each successful session-level acquisition:
343
+ SELECT pg_advisory_unlock(hashtext('my_job_name'));
344
+
345
+ -- Or use a non-blocking acquisition:
346
+ SELECT pg_try_advisory_lock(hashtext('my_job_name'));
347
+ SELECT pg_advisory_unlock(hashtext('my_job_name'));
348
+ ```
349
+
350
+ ## VACUUM and Bloat
351
+
352
+ ### Check Autovacuum Status
353
+
354
+ ```sql
355
+ SELECT
356
+ schemaname,
357
+ relname,
358
+ n_dead_tup,
359
+ last_autovacuum,
360
+ last_autoanalyze,
361
+ autovacuum_count,
362
+ autoanalyze_count
363
+ FROM pg_stat_user_tables
364
+ WHERE n_dead_tup > 0
365
+ ORDER BY n_dead_tup DESC
366
+ LIMIT 20;
367
+ ```
368
+
369
+ ### VACUUM Time Tracking (PG18+)
370
+
371
+ PG18 adds cumulative timing columns to `pg_stat_all_tables`:
372
+
373
+ ```sql
374
+ SELECT
375
+ schemaname,
376
+ relname,
377
+ total_vacuum_time,
378
+ total_autovacuum_time,
379
+ total_analyze_time,
380
+ total_autoanalyze_time
381
+ FROM pg_stat_user_tables
382
+ WHERE total_autovacuum_time > 0
383
+ ORDER BY total_autovacuum_time DESC
384
+ LIMIT 10;
385
+ ```
386
+
387
+ ### Autovacuum Tuning for High-Write Tables
388
+
389
+ ```sql
390
+ -- Per-table autovacuum settings for a high-churn table
391
+ ALTER TABLE hot_table SET (
392
+ autovacuum_vacuum_scale_factor = 0.01, -- trigger at 1% dead tuples (default 20%)
393
+ autovacuum_vacuum_cost_delay = 2, -- faster vacuum (default 2ms)
394
+ autovacuum_analyze_scale_factor = 0.005 -- trigger analyze more often
395
+ );
396
+
397
+ -- PG18+: fixed dead-tuple threshold (in addition to percentage-based)
398
+ -- autovacuum_vacuum_max_threshold = 100000000 -- trigger at fixed count regardless of table size
399
+ ```
400
+
401
+ **PG18 vacuum improvements:**
402
+ - **Eager freezing**: Normal vacuums can freeze some pages opportunistically, reducing later freeze-only vacuum passes. Controlled by `vacuum_max_eager_freeze_failure_rate`.
403
+ - **`autovacuum_worker_slots`**: New GUC specifying max background worker slots; `autovacuum_max_workers` is now adjustable at runtime.
404
+ - **VACUUM/ANALYZE processes inheritance children by default**: Use `VACUUM (ONLY) tablename` for old behavior (parent table only).
405
+
406
+ ### Manual VACUUM Operations
407
+
408
+ ```sql
409
+ -- Standard VACUUM (reclaims space for reuse, doesn't lock)
410
+ VACUUM orders;
411
+
412
+ -- VACUUM with buffer usage limit (PG16+): limit shared buffer impact
413
+ VACUUM (BUFFER_USAGE_LIMIT '256kB') orders;
414
+
415
+ -- VACUUM with analysis
416
+ VACUUM ANALYZE orders;
417
+
418
+ -- VACUUM FULL (rewrites entire table — LOCKS TABLE, use as last resort)
419
+ VACUUM FULL orders;
420
+
421
+ -- VACUUM VERBOSE (show progress)
422
+ VACUUM VERBOSE orders;
423
+ ```
424
+
425
+ ### Monitoring VACUUM Progress
426
+
427
+ ```sql
428
+ SELECT
429
+ relid::regclass AS table_name,
430
+ phase,
431
+ heap_blks_total,
432
+ heap_blks_scanned,
433
+ heap_blks_vacuumed,
434
+ CASE WHEN heap_blks_total > 0
435
+ THEN round(100.0 * heap_blks_vacuumed / heap_blks_total, 1)
436
+ ELSE 0 END AS pct_complete
437
+ FROM pg_stat_progress_vacuum;
438
+ ```
439
+
440
+ ## Connection Management
441
+
442
+ ### Connection Overview
443
+
444
+ ```sql
445
+ SELECT
446
+ state,
447
+ count(*) AS connections,
448
+ max(now() - state_change) AS longest_in_state
449
+ FROM pg_stat_activity
450
+ GROUP BY state
451
+ ORDER BY count(*) DESC;
452
+ ```
453
+
454
+ ### Idle Connections Holding Resources
455
+
456
+ ```sql
457
+ SELECT
458
+ pid,
459
+ usename,
460
+ application_name,
461
+ client_addr,
462
+ now() - state_change AS idle_duration,
463
+ left(query, 100) AS last_query
464
+ FROM pg_stat_activity
465
+ WHERE state = 'idle'
466
+ AND now() - state_change > interval '10 minutes'
467
+ ORDER BY idle_duration DESC;
468
+ ```
469
+
470
+ ### Connection Limits
471
+
472
+ ```sql
473
+ -- Current vs max connections
474
+ SELECT
475
+ count(*) AS current_connections,
476
+ (SELECT setting::int FROM pg_settings WHERE name = 'max_connections') AS max_connections;
477
+ ```
478
+
479
+ If hitting connection limits, use PgBouncer or application-side connection pooling rather than increasing `max_connections`.
480
+
481
+ ## pg_stat_statements
482
+
483
+ ### Setup
484
+
485
+ ```sql
486
+ -- In postgresql.conf:
487
+ -- shared_preload_libraries = 'pg_stat_statements'
488
+
489
+ CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
490
+ ```
491
+
492
+ ### Top Queries by Total Time
493
+
494
+ ```sql
495
+ SELECT
496
+ left(query, 100) AS query,
497
+ calls,
498
+ round(total_exec_time::numeric, 1) AS total_ms,
499
+ round(mean_exec_time::numeric, 1) AS avg_ms,
500
+ round((100.0 * total_exec_time / nullif(sum(total_exec_time) OVER (), 0))::numeric, 1) AS pct_total,
501
+ rows
502
+ FROM pg_stat_statements
503
+ WHERE dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
504
+ ORDER BY total_exec_time DESC
505
+ LIMIT 20;
506
+ ```
507
+
508
+ ### Top Queries by Mean Time (Slowest Individual Executions)
509
+
510
+ ```sql
511
+ SELECT
512
+ left(query, 100) AS query,
513
+ calls,
514
+ round(mean_exec_time::numeric, 1) AS avg_ms,
515
+ round(min_exec_time::numeric, 1) AS min_ms,
516
+ round(max_exec_time::numeric, 1) AS max_ms,
517
+ round(stddev_exec_time::numeric, 1) AS stddev_ms
518
+ FROM pg_stat_statements
519
+ WHERE calls >= 10 -- ignore rare queries
520
+ AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
521
+ ORDER BY mean_exec_time DESC
522
+ LIMIT 20;
523
+ ```
524
+
525
+ ### Parallel Worker Usage (PG18+)
526
+
527
+ PG18 adds parallel worker tracking to `pg_stat_statements`:
528
+
529
+ ```sql
530
+ SELECT
531
+ left(query, 80) AS query,
532
+ calls,
533
+ round(mean_exec_time::numeric, 1) AS avg_ms,
534
+ parallel_workers_to_launch,
535
+ parallel_workers_launched
536
+ FROM pg_stat_statements
537
+ WHERE parallel_workers_to_launch > 0
538
+ AND dbid = (SELECT oid FROM pg_database WHERE datname = current_database())
539
+ ORDER BY parallel_workers_to_launch - parallel_workers_launched DESC
540
+ LIMIT 10;
541
+ ```
542
+
543
+ A gap between `to_launch` and `launched` indicates insufficient parallel workers.
544
+
545
+ ### Reset Statistics
546
+
547
+ ```sql
548
+ -- Reset pg_stat_statements (do this after config changes or deployments)
549
+ SELECT pg_stat_statements_reset();
550
+
551
+ -- Reset table/index stats
552
+ SELECT pg_stat_reset();
553
+ ```