@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,372 @@
1
+ # Backup & Restore Reference
2
+
3
+ ## Contents
4
+ - Backup strategy overview
5
+ - Logical backups (pg_dump / pg_restore)
6
+ - Physical backups (pg_basebackup)
7
+ - Point-in-Time Recovery (PITR)
8
+ - Verification and testing
9
+ - Automation patterns
10
+
11
+ ## Backup Strategy Overview
12
+
13
+ | Method | What it captures | Granularity | Speed | Use case |
14
+ |--------|-----------------|-------------|-------|----------|
15
+ | `pg_dump` | Logical (SQL/custom) | Per-database, per-table | Slow on large DBs | Dev snapshots, migrations, selective restore |
16
+ | `pg_dumpall` | All databases + globals | Entire cluster | Slow | Full cluster backup including roles/tablespaces |
17
+ | `pg_basebackup` | Physical (file copy) | Entire cluster | Fast | Production backups, PITR base, replica setup |
18
+ | Continuous archiving | WAL segments | Incremental | Continuous | PITR — restore to any point in time |
19
+
20
+ **Production recommendation**: `pg_basebackup` + continuous WAL archiving for PITR capability. Supplement with periodic `pg_dump` for portable, version-independent backups.
21
+
22
+ ## Logical Backups (pg_dump / pg_restore)
23
+
24
+ ### pg_dump Formats
25
+
26
+ | Format | Flag | Parallel restore? | Selective restore? | Notes |
27
+ |--------|------|-------------------|-------------------|-------|
28
+ | Custom | `-Fc` | Yes | Yes | **Recommended default** — compressed, flexible |
29
+ | Directory | `-Fd` | Yes | Yes | One file per table, good for large DBs |
30
+ | Plain SQL | `-Fp` | No | No (manual editing) | Human-readable, good for version control |
31
+ | Tar | `-Ft` | No | Yes | Compatibility option |
32
+
33
+ ### Common pg_dump Patterns
34
+
35
+ ```bash
36
+ # Full database backup (custom format — recommended)
37
+ pg_dump -Fc -f backup.dump mydb
38
+
39
+ # With compression level (0-9, default varies by format)
40
+ pg_dump -Fc -Z 6 -f backup.dump mydb
41
+
42
+ # Parallel dump (directory format only, 4 workers)
43
+ pg_dump -Fd -j 4 -f backup_dir/ mydb
44
+
45
+ # Schema only (no data)
46
+ pg_dump -Fc --schema-only -f schema.dump mydb
47
+
48
+ # Data only (no schema)
49
+ pg_dump -Fc --data-only -f data.dump mydb
50
+
51
+ # Specific tables
52
+ pg_dump -Fc -t orders -t customers -f subset.dump mydb
53
+
54
+ # Specific schema
55
+ pg_dump -Fc -n public -f public_schema.dump mydb
56
+
57
+ # Exclude large tables
58
+ pg_dump -Fc -T audit_log -T event_archive -f without_logs.dump mydb
59
+
60
+ # Include CREATE DATABASE in output
61
+ pg_dump -Fc --create -f backup_with_create.dump mydb
62
+ ```
63
+
64
+ ### pg_restore Patterns
65
+
66
+ ```bash
67
+ # Restore to an existing (empty) database
68
+ pg_restore -d mydb backup.dump
69
+
70
+ # Parallel restore (4 workers — significantly faster for large DBs)
71
+ pg_restore -d mydb -j 4 backup.dump
72
+
73
+ # Create the database during restore
74
+ pg_restore --create -d postgres backup.dump
75
+
76
+ # List contents of a backup (inspect before restoring)
77
+ pg_restore --list backup.dump
78
+
79
+ # Restore specific tables only
80
+ pg_restore -d mydb -t orders -t customers backup.dump
81
+
82
+ # Schema only
83
+ pg_restore -d mydb --schema-only backup.dump
84
+
85
+ # Data only (schema already exists)
86
+ pg_restore -d mydb --data-only backup.dump
87
+
88
+ # Clean (drop) objects before recreating
89
+ pg_restore -d mydb --clean --if-exists backup.dump
90
+
91
+ # Restore atomically and stop on the first error
92
+ pg_restore -d mydb --single-transaction -j 1 backup.dump
93
+ # Note: --single-transaction is incompatible with -j > 1
94
+ ```
95
+
96
+ Selective restore patterns do not automatically include dependencies. Schema-qualify table patterns when names may exist in multiple schemas, and verify required types, sequences, constraints, and referenced tables separately.
97
+
98
+ ### Restoring Plain SQL Dumps
99
+
100
+ ```bash
101
+ # Plain SQL dumps are restored with psql, not pg_restore
102
+ psql -d mydb -f backup.sql
103
+
104
+ # With error handling
105
+ psql -d mydb -v ON_ERROR_STOP=1 -f backup.sql
106
+ ```
107
+
108
+ ### pg_dumpall — Cluster-Wide Backup
109
+
110
+ `pg_dumpall` is the only way to back up global objects (roles, tablespaces):
111
+
112
+ ```bash
113
+ # Full cluster (all databases + globals) — plain SQL only
114
+ pg_dumpall -f cluster_backup.sql
115
+
116
+ # Globals only (roles, tablespaces) — use alongside per-database pg_dump
117
+ pg_dumpall --globals-only -f globals.sql
118
+
119
+ # Roles only
120
+ pg_dumpall --roles-only -f roles.sql
121
+ ```
122
+
123
+ **Best practice**: Use `pg_dumpall --globals-only` for roles/tablespaces, then `pg_dump -Fc` per database for data. This gives you parallel restore capability while preserving globals.
124
+
125
+ ### Optimizer Statistics in Backups (PG18+)
126
+
127
+ ```bash
128
+ # Dump optimizer statistics (speeds up post-restore query performance)
129
+ pg_dump -Fc --statistics -f backup.dump mydb
130
+
131
+ # Statistics only (no schema or data)
132
+ pg_dump -Fc --statistics-only -f stats.dump mydb
133
+
134
+ # Skip statistics
135
+ pg_dump -Fc --no-statistics -f backup.dump mydb
136
+ ```
137
+
138
+ Without statistics, the planner uses default estimates after restore until `ANALYZE` runs on all tables. Dumping statistics avoids the post-restore performance dip.
139
+
140
+ ### Performance Tips for Large Databases
141
+
142
+ 1. **Use parallel dump/restore** (`-Fd -j N`) — scales well with CPU cores
143
+ 2. **Dump to fast storage** — local NVMe, not network mounts
144
+ 3. **Increase `maintenance_work_mem`** on the restore target for faster index rebuilds
145
+ 4. **Disable triggers during data-only restore**: `pg_restore --disable-triggers` (requires superuser)
146
+ 5. **Drop indexes before restore, recreate after** — faster than incremental index maintenance during bulk inserts
147
+ 6. **Restore schema first, then data, then indexes**:
148
+ ```bash
149
+ pg_restore -d mydb --section=pre-data backup.dump
150
+ pg_restore -d mydb --data-only -j 4 backup.dump
151
+ pg_restore -d mydb --section=post-data -j 4 backup.dump
152
+ ```
153
+
154
+ ## Physical Backups (pg_basebackup)
155
+
156
+ `pg_basebackup` creates a byte-for-byte copy of the entire cluster, suitable as a base for PITR or setting up replicas.
157
+
158
+ ```bash
159
+ # Basic backup (plain format)
160
+ pg_basebackup -D /backup/base -Fp -Xs -P
161
+
162
+ # Compressed tar format
163
+ pg_basebackup -D /backup/base -Ft -z -Xs -P
164
+
165
+ # With checkpoint mode (fast = don't wait for next scheduled checkpoint)
166
+ pg_basebackup -D /backup/base -Fp -Xs -P --checkpoint=fast
167
+
168
+ # To a remote server
169
+ pg_basebackup -h primary_host -U repl_user -D /backup/base -Fp -Xs -P
170
+ ```
171
+
172
+ | Flag | Meaning |
173
+ |------|---------|
174
+ | `-D` | Target directory |
175
+ | `-Fp` | Plain format (ready-to-use data directory) |
176
+ | `-Ft` | Tar format (one tar per tablespace) |
177
+ | `-z` | Compress (with tar format) |
178
+ | `-Xs` | Stream WAL during backup (ensures consistency) |
179
+ | `-P` | Show progress |
180
+ | `--checkpoint=fast` | Start backup immediately (don't wait for next checkpoint) |
181
+
182
+ ### Prerequisites
183
+
184
+ The connection used by `pg_basebackup` must authenticate as a superuser or a role with `REPLICATION` privilege. `max_wal_senders` must also have enough capacity for the backup connection:
185
+
186
+ ```sql
187
+ -- On the primary
188
+ CREATE ROLE backup_user WITH REPLICATION LOGIN PASSWORD '...';
189
+ ```
190
+
191
+ And `pg_hba.conf` must allow replication connections:
192
+
193
+ ```
194
+ host replication backup_user backup_server_ip/32 scram-sha-256
195
+ ```
196
+
197
+ [PG15+] `--target=server:/path` writes the backup on the database server. A non-superuser using this target needs both `REPLICATION` privilege for the backup connection and membership in `pg_write_server_files` for the server-side write. `--target` is unavailable in PG14 and cannot be combined with `-Xstream`; use `-Xfetch` or `-Xnone`.
198
+
199
+ ## Point-in-Time Recovery (PITR)
200
+
201
+ PITR lets you restore a database to any specific point in time — invaluable for recovering from accidental data deletion or corruption.
202
+
203
+ ### How PITR Works
204
+
205
+ 1. Take a **base backup** (`pg_basebackup`)
206
+ 2. Continuously **archive WAL segments** as they're produced
207
+ 3. To recover: restore the base backup, then **replay WAL** up to the target time
208
+
209
+ ### Step 1: Configure WAL Archiving
210
+
211
+ In `postgresql.conf`:
212
+
213
+ ```
214
+ archive_mode = on
215
+ archive_command = 'cp %p /archive/wal/%f' # or use pgBackRest, barman, etc.
216
+ # archive_library = '' # PG15+: use archive modules instead of shell commands
217
+ ```
218
+
219
+ Requires a restart after enabling `archive_mode`.
220
+
221
+ Verify archiving is working:
222
+
223
+ ```sql
224
+ SELECT * FROM pg_stat_archiver;
225
+ -- Check: archived_count is increasing, last_failed_time is NULL
226
+ ```
227
+
228
+ ### Step 2: Take Base Backups Regularly
229
+
230
+ ```bash
231
+ # Weekly base backup (adjust frequency based on WAL volume)
232
+ pg_basebackup -D /backup/base_$(date +%Y%m%d) -Ft -z -Xs -P --checkpoint=fast
233
+ ```
234
+
235
+ ### Step 3: Recovery
236
+
237
+ To recover to a specific point in time:
238
+
239
+ 1. Stop PostgreSQL
240
+ 2. Replace the data directory with the base backup
241
+ 3. Create `recovery.signal` (PG12+) or `recovery.conf` (PG11-)
242
+ 4. Configure recovery target in `postgresql.conf`:
243
+
244
+ ```
245
+ # In postgresql.conf (PG12+):
246
+ restore_command = 'cp /archive/wal/%f %p'
247
+ recovery_target_time = '2024-06-15 14:30:00'
248
+ recovery_target_action = 'promote' # 'pause' to inspect before promoting
249
+ ```
250
+
251
+ 5. Start PostgreSQL — it replays WAL up to the target time, then promotes to read-write
252
+
253
+ ### Recovery Target Options
254
+
255
+ ```text
256
+ -- Recover to a specific time
257
+ recovery_target_time = '2024-06-15 14:30:00+00'
258
+
259
+ -- Recover to a specific transaction ID
260
+ recovery_target_xid = '12345678'
261
+
262
+ -- Recover to a named restore point
263
+ recovery_target_name = 'before_migration'
264
+
265
+ -- Stop as soon as a consistent state is reached
266
+ -- (for an online backup, normally the point where the backup ended)
267
+ recovery_target = 'immediate'
268
+
269
+ -- Recover to a specific WAL position
270
+ recovery_target_lsn = '0/1A2B3C4D'
271
+ ```
272
+
273
+ To recover through the end of all available WAL, omit every `recovery_target*` setting. `recovery_target = 'immediate'` is an explicit early stopping target, so later available WAL can remain unapplied. PostgreSQL may still replay the WAL required to make an online backup consistent.
274
+
275
+ ### Creating Named Restore Points
276
+
277
+ Before risky operations, create a named restore point:
278
+
279
+ ```sql
280
+ SELECT pg_create_restore_point('before_schema_migration');
281
+ SELECT pg_create_restore_point('before_bulk_delete');
282
+ ```
283
+
284
+ This gives you an exact target to recover to if the operation goes wrong.
285
+
286
+ ## Verification and Testing
287
+
288
+ ### Verify Backup Integrity
289
+
290
+ ```bash
291
+ # List contents without restoring
292
+ pg_restore --list backup.dump
293
+
294
+ # Verify a plain-format physical backup (PG13+)
295
+ pg_verifybackup /backup/base_20240615
296
+
297
+ # PG18+: verify a tar-format backup directly
298
+ pg_verifybackup --no-parse-wal /backup/base_tar_20240615
299
+ ```
300
+
301
+ ### Test Restores Regularly
302
+
303
+ **A backup that hasn't been tested is not a backup.** Schedule regular restore tests:
304
+
305
+ ```bash
306
+ # Restore to a test database
307
+ createdb mydb_restore_test
308
+ pg_restore -d mydb_restore_test backup.dump
309
+
310
+ # Verify row counts
311
+ psql -d mydb_restore_test -c "
312
+ SELECT schemaname, relname, n_live_tup
313
+ FROM pg_stat_user_tables
314
+ ORDER BY n_live_tup DESC;
315
+ "
316
+
317
+ # Clean up
318
+ dropdb mydb_restore_test
319
+ ```
320
+
321
+ ### Post-Restore Checklist
322
+
323
+ After restoring a backup:
324
+
325
+ 1. **Run `ANALYZE`** on all tables — optimizer statistics may be stale or missing
326
+ ```sql
327
+ ANALYZE; -- all tables
328
+ ```
329
+ 2. **Verify sequences** — if restoring data-only, sequences may not match the data
330
+ ```sql
331
+ SELECT sequencename, last_value FROM pg_sequences WHERE schemaname = 'public';
332
+ ```
333
+ 3. **Check for invalid indexes** — concurrent index builds may have been in progress
334
+ ```sql
335
+ SELECT indexrelid::regclass, indisvalid FROM pg_index WHERE NOT indisvalid;
336
+ ```
337
+ 4. **Verify replication slots are clean** — stale slots from the source won't work
338
+ ```sql
339
+ SELECT slot_name, active FROM pg_replication_slots;
340
+ ```
341
+
342
+ ## Automation Patterns
343
+
344
+ ### Scripted Backup with Retention
345
+
346
+ ```bash
347
+ #!/bin/bash
348
+ BACKUP_DIR="/backup/pg"
349
+ RETENTION_DAYS=30
350
+ DB_NAME="mydb"
351
+ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
352
+
353
+ # Dump
354
+ pg_dump -Fc -Z 6 -f "${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.dump" "${DB_NAME}"
355
+
356
+ # Verify dump was created and is non-empty
357
+ if [ ! -s "${BACKUP_DIR}/${DB_NAME}_${TIMESTAMP}.dump" ]; then
358
+ echo "ERROR: Backup file is empty or missing" >&2
359
+ exit 1
360
+ fi
361
+
362
+ # Clean old backups
363
+ find "${BACKUP_DIR}" -name "${DB_NAME}_*.dump" -mtime +${RETENTION_DAYS} -delete
364
+ ```
365
+
366
+ ### Dedicated Backup Tools
367
+
368
+ For production environments, consider purpose-built tools that handle scheduling, retention, compression, and PITR:
369
+
370
+ - **pgBackRest** — parallel backup/restore, incremental backups, S3/GCS/Azure support, built-in PITR
371
+ - **Barman** — backup management with retention policies, remote backup, WAL archiving
372
+ - **pg_probackup** — incremental backups with page-level tracking, merge, validation
@@ -0,0 +1,315 @@
1
+ # Bulk Data Loading Reference
2
+
3
+ ## Contents
4
+ - COPY vs INSERT performance
5
+ - COPY FROM patterns
6
+ - Optimizing large loads
7
+ - ETL staging patterns
8
+ - Bulk updates and deletes
9
+
10
+ ## COPY vs INSERT Performance
11
+
12
+ | Method | Rows/sec (typical) | Use case |
13
+ |--------|-------------------|----------|
14
+ | Single-row INSERT | ~1,000-5,000 | Application writes |
15
+ | Multi-row INSERT (VALUES) | ~10,000-50,000 | Batch inserts from code |
16
+ | `COPY FROM` | ~100,000-500,000+ | Bulk loading from files or streams |
17
+ | `COPY FROM` (binary) | ~200,000-1,000,000+ | Maximum throughput (binary format) |
18
+
19
+ `COPY` is **10-100x faster** than individual INSERTs because it bypasses per-row overhead (parsing, planning, WAL per statement).
20
+
21
+ ## COPY FROM Patterns
22
+
23
+ ### From a File
24
+
25
+ ```sql
26
+ -- CSV with header
27
+ COPY orders FROM '/path/to/orders.csv' WITH (FORMAT csv, HEADER true);
28
+
29
+ -- Tab-delimited
30
+ COPY orders FROM '/path/to/orders.tsv' WITH (FORMAT text);
31
+
32
+ -- Custom delimiter
33
+ COPY orders FROM '/path/to/orders.dat' WITH (DELIMITER '|');
34
+
35
+ -- With NULL handling
36
+ COPY orders FROM '/path/to/orders.csv'
37
+ WITH (FORMAT csv, HEADER true, NULL '');
38
+ ```
39
+
40
+ ### From STDIN (Piped Data)
41
+
42
+ ```bash
43
+ # Pipe from another command
44
+ cat orders.csv | psql -d mydb -c "\COPY orders FROM STDIN WITH (FORMAT csv, HEADER true)"
45
+
46
+ # Pipe from gzip
47
+ gunzip -c orders.csv.gz | psql -d mydb -c "\COPY orders FROM STDIN WITH (FORMAT csv, HEADER true)"
48
+ ```
49
+
50
+ ### From Application Code
51
+
52
+ Most drivers support COPY protocol for streaming data:
53
+
54
+ ```python
55
+ # Python (psycopg 3)
56
+ with conn.cursor() as cur:
57
+ with cur.copy("COPY orders (id, customer_id, total) FROM STDIN") as copy:
58
+ for row in data:
59
+ copy.write_row(row)
60
+ ```
61
+
62
+ ```javascript
63
+ // Node.js (pg-copy-streams)
64
+ const { from } = require('pg-copy-streams');
65
+ const stream = client.query(from('COPY orders FROM STDIN WITH (FORMAT csv)'));
66
+ fileStream.pipe(stream);
67
+ ```
68
+
69
+ ### COPY TO (Export)
70
+
71
+ ```sql
72
+ -- Export to CSV
73
+ COPY orders TO '/path/to/orders.csv' WITH (FORMAT csv, HEADER true);
74
+
75
+ -- Export query results
76
+ COPY (SELECT id, total FROM orders WHERE created_at > '2024-01-01')
77
+ TO '/path/to/recent.csv' WITH (FORMAT csv, HEADER true);
78
+ ```
79
+
80
+ ### Error Handling (PG17+)
81
+
82
+ ```sql
83
+ -- Skip invalid rows instead of failing the entire COPY
84
+ COPY orders FROM '/path/to/orders.csv'
85
+ WITH (FORMAT csv, HEADER true, ON_ERROR ignore);
86
+
87
+ -- PG18+: limit how many errors to tolerate
88
+ COPY orders FROM '/path/to/orders.csv'
89
+ WITH (FORMAT csv, HEADER true, ON_ERROR ignore, REJECT_LIMIT 100);
90
+ ```
91
+
92
+ ## Optimizing Large Loads
93
+
94
+ ### 1. Drop Indexes, Load, Recreate
95
+
96
+ Building indexes incrementally during COPY is much slower than building them once after:
97
+
98
+ ```sql
99
+ -- Before load: drop non-essential indexes
100
+ DROP INDEX idx_orders_customer_id;
101
+ DROP INDEX idx_orders_created_at;
102
+
103
+ -- Load data
104
+ COPY orders FROM '/path/to/orders.csv' WITH (FORMAT csv, HEADER true);
105
+
106
+ -- After load: recreate indexes (concurrently if table is in use)
107
+ CREATE INDEX idx_orders_customer_id ON orders(customer_id);
108
+ CREATE INDEX idx_orders_created_at ON orders(created_at);
109
+
110
+ -- Update statistics
111
+ ANALYZE orders;
112
+ ```
113
+
114
+ ### 2. Disable Triggers During Load
115
+
116
+ ```sql
117
+ -- Disable all triggers on the table
118
+ ALTER TABLE orders DISABLE TRIGGER ALL;
119
+
120
+ -- Load data
121
+ COPY orders FROM '/path/to/orders.csv' WITH (FORMAT csv, HEADER true);
122
+
123
+ -- Re-enable triggers
124
+ ALTER TABLE orders ENABLE TRIGGER ALL;
125
+ ```
126
+
127
+ `DISABLE TRIGGER ALL` requires superuser privileges when the table has foreign-key or other internally generated constraint triggers. A table owner can use `DISABLE TRIGGER USER` to disable only user-defined triggers. Disabling constraint triggers can admit invalid data, so validate constraints before re-enabling writes.
128
+
129
+ ### 3. Increase maintenance_work_mem
130
+
131
+ Larger `maintenance_work_mem` speeds up index creation after the load:
132
+
133
+ ```sql
134
+ SET maintenance_work_mem = '1GB'; -- for the duration of the load session
135
+ ```
136
+
137
+ ### 4. Disable Autovacuum During Load
138
+
139
+ For very large bulk loads, temporarily disable autovacuum to avoid competing I/O:
140
+
141
+ ```sql
142
+ ALTER TABLE orders SET (autovacuum_enabled = false);
143
+
144
+ -- Load data...
145
+
146
+ ALTER TABLE orders SET (autovacuum_enabled = true);
147
+ VACUUM ANALYZE orders;
148
+ ```
149
+
150
+ ### 5. Use Unlogged Tables for Staging
151
+
152
+ Unlogged tables skip WAL writes — 2-3x faster for writes but **data is lost on crash**:
153
+
154
+ ```sql
155
+ CREATE UNLOGGED TABLE staging_orders (LIKE orders INCLUDING ALL);
156
+
157
+ COPY staging_orders FROM '/path/to/orders.csv' WITH (FORMAT csv, HEADER true);
158
+
159
+ -- Transform and move to the real table
160
+ INSERT INTO orders SELECT * FROM staging_orders;
161
+
162
+ DROP TABLE staging_orders;
163
+ ```
164
+
165
+ ### 6. Batch Size for Programmatic Inserts
166
+
167
+ When COPY isn't available, use multi-row INSERT with batches of 100-1,000 rows:
168
+
169
+ ```sql
170
+ -- Single round-trip for 1,000 rows
171
+ INSERT INTO orders (customer_id, total, created_at)
172
+ VALUES
173
+ (1, 99.99, now()),
174
+ (2, 149.99, now()),
175
+ -- ... up to ~1,000 rows per statement
176
+ (1000, 79.99, now());
177
+ ```
178
+
179
+ Beyond ~1,000 rows per statement, parse overhead increases. Use COPY for larger batches.
180
+
181
+ ### 7. Parallel Loading into Partitioned Tables
182
+
183
+ Load data into individual partitions concurrently from separate sessions:
184
+
185
+ ```bash
186
+ # Session 1
187
+ psql -c "COPY events_2024_q1 FROM '/data/q1.csv' WITH (FORMAT csv)"
188
+
189
+ # Session 2 (concurrent)
190
+ psql -c "COPY events_2024_q2 FROM '/data/q2.csv' WITH (FORMAT csv)"
191
+ ```
192
+
193
+ ## ETL Staging Patterns
194
+
195
+ ### Staging Table with Upsert
196
+
197
+ ```sql
198
+ -- Create staging table (temporary or unlogged)
199
+ CREATE TEMP TABLE staging_customers (LIKE customers INCLUDING DEFAULTS);
200
+
201
+ -- Load raw data
202
+ COPY staging_customers FROM '/path/to/customers.csv' WITH (FORMAT csv, HEADER true);
203
+
204
+ -- Upsert into production table
205
+ INSERT INTO customers (id, name, email, updated_at)
206
+ SELECT id, name, email, now()
207
+ FROM staging_customers
208
+ ON CONFLICT (id)
209
+ DO UPDATE SET
210
+ name = EXCLUDED.name,
211
+ email = EXCLUDED.email,
212
+ updated_at = EXCLUDED.updated_at;
213
+ ```
214
+
215
+ ### Staging Table with MERGE (PG15+)
216
+
217
+ ```sql
218
+ MERGE INTO customers AS target
219
+ USING staging_customers AS source
220
+ ON target.id = source.id
221
+ WHEN MATCHED AND source.name IS DISTINCT FROM target.name THEN
222
+ UPDATE SET name = source.name, email = source.email, updated_at = now()
223
+ WHEN NOT MATCHED THEN
224
+ INSERT (id, name, email, updated_at)
225
+ VALUES (source.id, source.name, source.email, now());
226
+ ```
227
+
228
+ ### Swap Table Pattern
229
+
230
+ For full-refresh loads where you replace all data:
231
+
232
+ ```sql
233
+ -- Load into a new table
234
+ CREATE TABLE orders_new (LIKE orders INCLUDING ALL);
235
+ COPY orders_new FROM '/path/to/orders.csv' WITH (FORMAT csv, HEADER true);
236
+ ANALYZE orders_new;
237
+
238
+ -- Atomic swap (brief exclusive lock)
239
+ BEGIN;
240
+ ALTER TABLE orders RENAME TO orders_old;
241
+ ALTER TABLE orders_new RENAME TO orders;
242
+ DROP TABLE orders_old;
243
+ COMMIT;
244
+ ```
245
+
246
+ `LIKE ... INCLUDING ALL` does not copy foreign keys, triggers, rules, grants, row-level security policies, or publication membership. Recreate and verify those objects before swapping, or use a data-only refresh when the original table's identity and dependencies must remain unchanged.
247
+
248
+ ## Bulk Updates and Deletes
249
+
250
+ ### Chunked Deletes
251
+
252
+ Large DELETEs lock rows and generate WAL. This loop limits each statement to 10,000 rows:
253
+
254
+ ```sql
255
+ -- Delete in batches of 10,000
256
+ DO $$
257
+ DECLARE
258
+ rows_deleted int;
259
+ BEGIN
260
+ LOOP
261
+ DELETE FROM audit_log
262
+ WHERE id IN (
263
+ SELECT id FROM audit_log
264
+ WHERE created_at < now() - interval '1 year'
265
+ LIMIT 10000
266
+ );
267
+ GET DIAGNOSTICS rows_deleted = ROW_COUNT;
268
+ EXIT WHEN rows_deleted = 0;
269
+ -- Optional: brief pause to reduce WAL pressure
270
+ PERFORM pg_sleep(0.1);
271
+ END LOOP;
272
+ END $$;
273
+ ```
274
+
275
+ The entire `DO` block is still one transaction: locks, WAL, and dead rows accumulate until it finishes. For true transaction-level batching, execute one limited DELETE per client transaction and commit between batches.
276
+
277
+ ### Chunked Updates
278
+
279
+ The same statement-size pattern works for large updates:
280
+
281
+ ```sql
282
+ DO $$
283
+ DECLARE
284
+ rows_updated int;
285
+ BEGIN
286
+ LOOP
287
+ UPDATE orders
288
+ SET status = 'archived'
289
+ WHERE id IN (
290
+ SELECT id FROM orders
291
+ WHERE status = 'completed'
292
+ AND created_at < now() - interval '2 years'
293
+ LIMIT 10000
294
+ FOR UPDATE SKIP LOCKED
295
+ );
296
+ GET DIAGNOSTICS rows_updated = ROW_COUNT;
297
+ EXIT WHEN rows_updated = 0;
298
+ END LOOP;
299
+ END $$;
300
+ ```
301
+
302
+ As with the DELETE loop, the `DO` block commits only once. Drive batches from the client or a transaction-controlling procedure invoked outside an explicit transaction when each batch must commit independently.
303
+
304
+ ### Partition Drop Instead of Delete
305
+
306
+ If data is partitioned by time, dropping a partition is instant vs. a slow DELETE:
307
+
308
+ ```sql
309
+ -- Instant: drop old partition
310
+ ALTER TABLE events DETACH PARTITION events_2023_q1 CONCURRENTLY;
311
+ DROP TABLE events_2023_q1;
312
+
313
+ -- vs. slow: delete rows
314
+ -- DELETE FROM events WHERE occurred_at < '2024-01-01'; -- don't do this
315
+ ```