cfsa-antigravity 1.0.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 (378) hide show
  1. package/bin/cli.mjs +324 -0
  2. package/package.json +34 -0
  3. package/template/.agent/instructions/commands.md +48 -0
  4. package/template/.agent/instructions/patterns.md +61 -0
  5. package/template/.agent/instructions/structure.md +29 -0
  6. package/template/.agent/instructions/tech-stack.md +43 -0
  7. package/template/.agent/instructions/workflow.md +41 -0
  8. package/template/.agent/kit-sync.md +15 -0
  9. package/template/.agent/rules/boundary-not-placeholder.md +146 -0
  10. package/template/.agent/rules/completion-checklist.md +48 -0
  11. package/template/.agent/rules/decision-classification.md +103 -0
  12. package/template/.agent/rules/extensibility.md +47 -0
  13. package/template/.agent/rules/question-vs-command.md +81 -0
  14. package/template/.agent/rules/security-first.md +43 -0
  15. package/template/.agent/rules/specificity-standards.md +54 -0
  16. package/template/.agent/rules/tdd-contract-first.md +57 -0
  17. package/template/.agent/rules/vertical-slices.md +42 -0
  18. package/template/.agent/skill-library/MANIFEST.md +480 -0
  19. package/template/.agent/skill-library/README.md +38 -0
  20. package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
  21. package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
  22. package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
  23. package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
  24. package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
  25. package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
  26. package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
  27. package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
  28. package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
  29. package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
  30. package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
  31. package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
  32. package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
  33. package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
  34. package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
  35. package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
  36. package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
  37. package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
  38. package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
  39. package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
  40. package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
  41. package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
  42. package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
  43. package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
  44. package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
  45. package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
  46. package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
  47. package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
  48. package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
  49. package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
  50. package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
  51. package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
  52. package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
  53. package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
  54. package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
  55. package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
  56. package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
  57. package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
  58. package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
  59. package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
  60. package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
  61. package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
  62. package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
  63. package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
  64. package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
  65. package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
  66. package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
  67. package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
  68. package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
  69. package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
  70. package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
  71. package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
  72. package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
  73. package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
  74. package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
  75. package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
  76. package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
  77. package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
  78. package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
  79. package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
  80. package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
  81. package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
  82. package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
  83. package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
  84. package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
  85. package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
  86. package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
  87. package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
  88. package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
  89. package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
  90. package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
  91. package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
  92. package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
  93. package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
  94. package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
  95. package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
  96. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
  97. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
  98. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
  99. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
  100. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
  101. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
  102. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
  103. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
  104. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
  105. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
  106. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
  107. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
  108. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
  109. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
  110. package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
  111. package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
  112. package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
  113. package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
  114. package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
  115. package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
  116. package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
  117. package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
  118. package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
  119. package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
  120. package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
  121. package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
  122. package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
  123. package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
  124. package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
  125. package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
  126. package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
  127. package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
  128. package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
  129. package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
  130. package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
  131. package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
  132. package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
  133. package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
  134. package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
  135. package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
  136. package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
  137. package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
  138. package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
  139. package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
  140. package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
  141. package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
  142. package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
  143. package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
  144. package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
  145. package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
  146. package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
  147. package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
  148. package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
  149. package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
  150. package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
  151. package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
  152. package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
  153. package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
  154. package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
  155. package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
  156. package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
  157. package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
  158. package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
  159. package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
  160. package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
  161. package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
  162. package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
  163. package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
  164. package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
  165. package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
  166. package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
  167. package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
  168. package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
  169. package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
  170. package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
  171. package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
  172. package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
  173. package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
  174. package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
  175. package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
  176. package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
  177. package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
  178. package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
  179. package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
  180. package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
  181. package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
  182. package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
  183. package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
  184. package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
  185. package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
  186. package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
  187. package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
  188. package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
  189. package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
  190. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
  191. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
  192. package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
  193. package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
  194. package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
  195. package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
  196. package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
  197. package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
  198. package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
  199. package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
  200. package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
  201. package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
  202. package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
  203. package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
  204. package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
  205. package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
  206. package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
  207. package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
  208. package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
  209. package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
  210. package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
  211. package/template/.agent/skills/accessibility/SKILL.md +522 -0
  212. package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
  213. package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
  214. package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
  215. package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
  216. package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
  217. package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  218. package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
  219. package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  220. package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
  221. package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
  222. package/template/.agent/skills/api-versioning/SKILL.md +420 -0
  223. package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
  224. package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
  225. package/template/.agent/skills/brainstorming/SKILL.md +236 -0
  226. package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
  227. package/template/.agent/skills/clean-code/SKILL.md +94 -0
  228. package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
  229. package/template/.agent/skills/concise-planning/SKILL.md +68 -0
  230. package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
  231. package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
  232. package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
  233. package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
  234. package/template/.agent/skills/design-direction/SKILL.md +45 -0
  235. package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
  236. package/template/.agent/skills/find-skills/SKILL.md +145 -0
  237. package/template/.agent/skills/git-advanced/SKILL.md +972 -0
  238. package/template/.agent/skills/git-workflow/SKILL.md +420 -0
  239. package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
  240. package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
  241. package/template/.agent/skills/migration-management/SKILL.md +384 -0
  242. package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
  243. package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
  244. package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
  245. package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
  246. package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
  247. package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
  248. package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
  249. package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
  250. package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
  251. package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
  252. package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
  253. package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
  254. package/template/.agent/skills/prd-templates/SKILL.md +88 -0
  255. package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
  256. package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
  257. package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
  258. package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
  259. package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
  260. package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
  261. package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
  262. package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
  263. package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
  264. package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
  265. package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
  266. package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
  267. package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
  268. package/template/.agent/skills/prompt-engineer/README.md +659 -0
  269. package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
  270. package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
  271. package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
  272. package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
  273. package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
  274. package/template/.agent/skills/session-continuity/SKILL.md +730 -0
  275. package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
  276. package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
  277. package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
  278. package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
  279. package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
  280. package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
  281. package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
  282. package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
  283. package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
  284. package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
  285. package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
  286. package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
  287. package/template/.agent/skills/skill-creator/README.md +270 -0
  288. package/template/.agent/skills/skill-creator/SKILL.md +590 -0
  289. package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
  290. package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
  291. package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
  292. package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
  293. package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
  294. package/template/.agent/skills/spec-writing/SKILL.md +110 -0
  295. package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
  296. package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
  297. package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  298. package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
  299. package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
  300. package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
  301. package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
  302. package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
  303. package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
  304. package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
  305. package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
  306. package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
  307. package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
  308. package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
  309. package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
  310. package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
  311. package/template/.agent/skills/technical-writer/SKILL.md +242 -0
  312. package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
  313. package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
  314. package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
  315. package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
  316. package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
  317. package/template/.agent/workflows/audit-ambiguity.md +64 -0
  318. package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
  319. package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
  320. package/template/.agent/workflows/bootstrap-agents.md +66 -0
  321. package/template/.agent/workflows/create-prd-architecture.md +119 -0
  322. package/template/.agent/workflows/create-prd-compile.md +138 -0
  323. package/template/.agent/workflows/create-prd-design-system.md +135 -0
  324. package/template/.agent/workflows/create-prd-security.md +113 -0
  325. package/template/.agent/workflows/create-prd-stack.md +91 -0
  326. package/template/.agent/workflows/create-prd.md +168 -0
  327. package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
  328. package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
  329. package/template/.agent/workflows/decompose-architecture.md +111 -0
  330. package/template/.agent/workflows/evolve-contract.md +98 -0
  331. package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
  332. package/template/.agent/workflows/evolve-feature-classify.md +116 -0
  333. package/template/.agent/workflows/evolve-feature.md +56 -0
  334. package/template/.agent/workflows/ideate-discover.md +144 -0
  335. package/template/.agent/workflows/ideate-extract.md +129 -0
  336. package/template/.agent/workflows/ideate-validate.md +117 -0
  337. package/template/.agent/workflows/ideate.md +113 -0
  338. package/template/.agent/workflows/implement-slice-setup.md +113 -0
  339. package/template/.agent/workflows/implement-slice-tdd.md +198 -0
  340. package/template/.agent/workflows/implement-slice.md +50 -0
  341. package/template/.agent/workflows/plan-phase.md +202 -0
  342. package/template/.agent/workflows/propagate-decision-apply.md +135 -0
  343. package/template/.agent/workflows/propagate-decision-scan.md +147 -0
  344. package/template/.agent/workflows/propagate-decision.md +56 -0
  345. package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
  346. package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
  347. package/template/.agent/workflows/remediate-pipeline.md +55 -0
  348. package/template/.agent/workflows/resolve-ambiguity.md +82 -0
  349. package/template/.agent/workflows/sync-kit.md +209 -0
  350. package/template/.agent/workflows/update-architecture-map.md +74 -0
  351. package/template/.agent/workflows/validate-phase.md +219 -0
  352. package/template/.agent/workflows/verify-infrastructure.md +207 -0
  353. package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
  354. package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
  355. package/template/.agent/workflows/write-architecture-spec.md +63 -0
  356. package/template/.agent/workflows/write-be-spec-classify.md +165 -0
  357. package/template/.agent/workflows/write-be-spec-write.md +98 -0
  358. package/template/.agent/workflows/write-be-spec.md +76 -0
  359. package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
  360. package/template/.agent/workflows/write-fe-spec-write.md +94 -0
  361. package/template/.agent/workflows/write-fe-spec.md +71 -0
  362. package/template/AGENTS.md +176 -0
  363. package/template/GEMINI.md +177 -0
  364. package/template/docs/README.md +187 -0
  365. package/template/docs/audits/.gitkeep +0 -0
  366. package/template/docs/audits/README.md +10 -0
  367. package/template/docs/plans/.gitkeep +0 -0
  368. package/template/docs/plans/README.md +21 -0
  369. package/template/docs/plans/be/.gitkeep +0 -0
  370. package/template/docs/plans/be/README.md +11 -0
  371. package/template/docs/plans/fe/.gitkeep +0 -0
  372. package/template/docs/plans/fe/README.md +11 -0
  373. package/template/docs/plans/ia/.gitkeep +0 -0
  374. package/template/docs/plans/ia/README.md +17 -0
  375. package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
  376. package/template/docs/plans/ia/deep-dives/README.md +5 -0
  377. package/template/docs/plans/phases/.gitkeep +0 -0
  378. package/template/docs/plans/phases/README.md +11 -0
@@ -0,0 +1,1079 @@
1
+ ---
2
+ name: redis
3
+ description: "Expert Redis development guide covering data structures (strings, hashes, lists, sets, sorted sets, streams, JSON), caching patterns (cache-aside, write-through, write-behind), pub/sub, Lua scripting, transactions (MULTI/EXEC), pipelining, Redis Stack (Search, JSON, TimeSeries, Bloom), key naming, TTL strategies, memory management, eviction policies, Redis Cluster, Sentinel, client libraries (ioredis, redis-py), and rate limiting."
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # Redis Expert
8
+
9
+ ## 1. Data Structures
10
+
11
+ ### Strings
12
+
13
+ The most basic type. Stores text, integers, floats, or binary data up to 512 MB.
14
+
15
+ ```redis
16
+ # Basic key-value
17
+ SET user:1001:name "Alice Johnson"
18
+ GET user:1001:name
19
+
20
+ # With expiration
21
+ SET session:abc123 "{\"userId\":\"1001\"}" EX 3600 # Expires in 1 hour
22
+ SET session:abc123 "{\"userId\":\"1001\"}" PX 60000 # Expires in 60 seconds (ms)
23
+
24
+ # Set only if key does not exist (distributed lock primitive)
25
+ SET lock:order:5001 "worker-1" NX EX 30 # Acquire lock for 30 seconds
26
+
27
+ # Set only if key exists (update, not create)
28
+ SET user:1001:name "Alice Smith" XX
29
+
30
+ # Atomic counters
31
+ INCR page:views:home # Increment by 1
32
+ INCRBY user:1001:score 50 # Increment by 50
33
+ DECR inventory:product:301 # Decrement by 1
34
+ INCRBYFLOAT account:1001:balance 19.99
35
+
36
+ # Bit operations (compact boolean flags)
37
+ SETBIT user:1001:features 0 1 # Feature 0 enabled
38
+ SETBIT user:1001:features 1 0 # Feature 1 disabled
39
+ GETBIT user:1001:features 0 # Returns 1
40
+ BITCOUNT user:1001:features # Count enabled features
41
+ ```
42
+
43
+ ### Hashes
44
+
45
+ Field-value maps. Ideal for representing objects. More memory-efficient than separate string keys.
46
+
47
+ ```redis
48
+ # Set fields
49
+ HSET user:1001 name "Alice" email "alice@example.com" age 28 active 1
50
+ HMSET user:1001 city "Portland" country "US"
51
+
52
+ # Get fields
53
+ HGET user:1001 name # "Alice"
54
+ HMGET user:1001 name email age # ["Alice", "alice@example.com", "28"]
55
+ HGETALL user:1001 # All fields and values
56
+
57
+ # Atomic field operations
58
+ HINCRBY user:1001 login_count 1
59
+ HINCRBYFLOAT user:1001 balance 19.99
60
+
61
+ # Check existence
62
+ HEXISTS user:1001 email # 1 (exists)
63
+ HLEN user:1001 # Number of fields
64
+
65
+ # Delete fields
66
+ HDEL user:1001 temporary_field
67
+
68
+ # Get only keys or values
69
+ HKEYS user:1001
70
+ HVALS user:1001
71
+ ```
72
+
73
+ ### Lists
74
+
75
+ Ordered sequences. Support push/pop from both ends. Good for queues, activity feeds, and recent items.
76
+
77
+ ```redis
78
+ # Push items
79
+ LPUSH queue:emails "{\"to\":\"alice@example.com\",\"subject\":\"Welcome\"}"
80
+ RPUSH activity:user:1001 "logged_in" "viewed_product" "added_to_cart"
81
+
82
+ # Pop items (queue pattern: LPUSH + RPOP or RPUSH + LPOP)
83
+ RPOP queue:emails # Pop from right (FIFO with LPUSH)
84
+ LPOP queue:emails # Pop from left
85
+
86
+ # Blocking pop (waits for data, great for worker queues)
87
+ BRPOP queue:emails 30 # Block up to 30 seconds
88
+ BLPOP queue:high queue:low 10 # Priority queues: check high first
89
+
90
+ # Range queries
91
+ LRANGE activity:user:1001 0 9 # Last 10 items
92
+ LRANGE activity:user:1001 0 -1 # All items
93
+
94
+ # Trim (keep only recent items)
95
+ LTRIM activity:user:1001 0 99 # Keep only the 100 most recent
96
+
97
+ # Length
98
+ LLEN queue:emails
99
+
100
+ # Move between lists (atomic)
101
+ LMOVE queue:processing queue:completed LEFT RIGHT
102
+ ```
103
+
104
+ ### Sets
105
+
106
+ Unordered collections of unique strings. Ideal for tags, unique visitors, membership tracking.
107
+
108
+ ```redis
109
+ # Add members
110
+ SADD tags:product:301 "electronics" "sale" "featured"
111
+ SADD online:users "user:1001" "user:1002" "user:1003"
112
+
113
+ # Check membership
114
+ SISMEMBER online:users "user:1001" # 1 (member)
115
+ SISMEMBER online:users "user:9999" # 0 (not a member)
116
+
117
+ # Get all members
118
+ SMEMBERS tags:product:301
119
+
120
+ # Set operations
121
+ SADD interests:alice "music" "movies" "coding" "hiking"
122
+ SADD interests:bob "movies" "gaming" "coding" "cooking"
123
+
124
+ SINTER interests:alice interests:bob # {"movies", "coding"}
125
+ SUNION interests:alice interests:bob # All unique interests
126
+ SDIFF interests:alice interests:bob # {"music", "hiking"} (in alice, not in bob)
127
+
128
+ # Random members
129
+ SRANDMEMBER tags:product:301 2 # 2 random tags
130
+ SPOP online:users # Remove and return random member
131
+
132
+ # Cardinality
133
+ SCARD online:users # Count of members
134
+ ```
135
+
136
+ ### Sorted Sets
137
+
138
+ Sets with a score for each member. Sorted by score. Perfect for leaderboards, ranking, time-based data.
139
+
140
+ ```redis
141
+ # Add members with scores
142
+ ZADD leaderboard 1500 "alice" 1200 "bob" 1800 "carol" 900 "dave"
143
+
144
+ # Get by rank (ascending score)
145
+ ZRANGE leaderboard 0 9 # Top 10 (lowest scores)
146
+ ZRANGE leaderboard 0 9 REV # Top 10 (highest scores)
147
+ ZRANGE leaderboard 0 9 REV WITHSCORES # With scores
148
+
149
+ # Get by score range
150
+ ZRANGEBYSCORE leaderboard 1000 2000 # Scores between 1000 and 2000
151
+ ZRANGEBYSCORE leaderboard "-inf" "+inf" # All members
152
+
153
+ # Rank of a member
154
+ ZRANK leaderboard "alice" # Rank (0-indexed, ascending)
155
+ ZREVRANK leaderboard "alice" # Rank (0-indexed, descending)
156
+
157
+ # Score of a member
158
+ ZSCORE leaderboard "alice" # 1500
159
+
160
+ # Increment score
161
+ ZINCRBY leaderboard 100 "alice" # Alice now has 1600
162
+
163
+ # Count members in score range
164
+ ZCOUNT leaderboard 1000 2000
165
+
166
+ # Remove members
167
+ ZREM leaderboard "dave"
168
+ ZREMRANGEBYSCORE leaderboard "-inf" 500 # Remove low scorers
169
+ ZREMRANGEBYRANK leaderboard 0 -11 # Keep only top 10
170
+ ```
171
+
172
+ ### Streams
173
+
174
+ Append-only log data structure. Best for event sourcing, message queues, and real-time feeds.
175
+
176
+ ```redis
177
+ # Add entries (auto-generated ID with *)
178
+ XADD events:orders * action "created" orderId "5001" userId "1001" total "59.99"
179
+ XADD events:orders * action "paid" orderId "5001" paymentMethod "card"
180
+
181
+ # Read entries
182
+ XRANGE events:orders - + # All entries
183
+ XRANGE events:orders - + COUNT 10 # First 10
184
+ XRANGE events:orders 1700000000000-0 + # From timestamp
185
+
186
+ # Read new entries (blocking, consumer pattern)
187
+ XREAD COUNT 10 BLOCK 5000 STREAMS events:orders $ # Wait for new entries
188
+
189
+ # Consumer groups (parallel processing with acknowledgment)
190
+ XGROUP CREATE events:orders order-processors $ MKSTREAM
191
+
192
+ # Read as consumer in group
193
+ XREADGROUP GROUP order-processors worker-1 COUNT 1 BLOCK 5000 STREAMS events:orders >
194
+
195
+ # Acknowledge processed entry
196
+ XACK events:orders order-processors 1700000000001-0
197
+
198
+ # Check pending entries (not yet acknowledged)
199
+ XPENDING events:orders order-processors - + 10
200
+
201
+ # Claim stuck entries (when a worker dies)
202
+ XCLAIM events:orders order-processors worker-2 60000 1700000000001-0
203
+
204
+ # Trim stream length
205
+ XTRIM events:orders MAXLEN ~ 10000 # Keep approximately 10000 entries
206
+ ```
207
+
208
+ ---
209
+
210
+ ## 2. Caching Patterns
211
+
212
+ ### Cache-Aside (Lazy Loading)
213
+
214
+ ```typescript
215
+ import Redis from "ioredis";
216
+
217
+ const redis = new Redis(process.env.REDIS_URL);
218
+
219
+ async function getUser(userId: string): Promise<User> {
220
+ const cacheKey = `user:${userId}`;
221
+
222
+ // 1. Check cache
223
+ const cached = await redis.get(cacheKey);
224
+ if (cached !== null) {
225
+ return JSON.parse(cached) as User;
226
+ }
227
+
228
+ // 2. Cache miss: fetch from database
229
+ const user = await db.users.findById(userId);
230
+ if (!user) {
231
+ throw new Error("User not found");
232
+ }
233
+
234
+ // 3. Populate cache with TTL
235
+ await redis.set(cacheKey, JSON.stringify(user), "EX", 3600);
236
+
237
+ return user;
238
+ }
239
+
240
+ // Invalidate on write
241
+ async function updateUser(userId: string, data: Partial<User>): Promise<User> {
242
+ const user = await db.users.updateById(userId, data);
243
+ await redis.del(`user:${userId}`); // Invalidate cache
244
+ return user;
245
+ }
246
+ ```
247
+
248
+ ### Write-Through
249
+
250
+ ```typescript
251
+ // Write to cache AND database on every write
252
+ async function saveProduct(product: Product): Promise<void> {
253
+ // Write to database
254
+ await db.products.upsert(product);
255
+
256
+ // Write to cache (cache is always fresh)
257
+ await redis.set(
258
+ `product:${product.id}`,
259
+ JSON.stringify(product),
260
+ "EX",
261
+ 7200
262
+ );
263
+ }
264
+ ```
265
+
266
+ ### Write-Behind (Write-Back)
267
+
268
+ ```typescript
269
+ // Write to cache immediately, flush to database asynchronously
270
+ async function recordPageView(pageId: string): Promise<void> {
271
+ // Increment in Redis (fast)
272
+ await redis.hincrby(`pageviews:pending`, pageId, 1);
273
+ }
274
+
275
+ // Periodic flush to database (run every 30 seconds)
276
+ async function flushPageViews(): Promise<void> {
277
+ const pending = await redis.hgetall("pageviews:pending");
278
+ if (Object.keys(pending).length === 0) return;
279
+
280
+ // Batch update database
281
+ const updates = Object.entries(pending).map(([pageId, count]) =>
282
+ db.pages.increment(pageId, "views", parseInt(count, 10))
283
+ );
284
+ await Promise.all(updates);
285
+
286
+ // Clear pending counts
287
+ await redis.del("pageviews:pending");
288
+ }
289
+ ```
290
+
291
+ ### Cache Stampede Prevention
292
+
293
+ ```typescript
294
+ // Problem: many requests arrive simultaneously for an expired key
295
+ // All of them miss cache and hit the database at once
296
+
297
+ // Solution 1: Locking (only one request rebuilds cache)
298
+ async function getWithLock(key: string, fetchFn: () => Promise<string>, ttl: number): Promise<string> {
299
+ const cached = await redis.get(key);
300
+ if (cached !== null) return cached;
301
+
302
+ const lockKey = `lock:${key}`;
303
+ const acquired = await redis.set(lockKey, "1", "NX", "EX", 10);
304
+
305
+ if (acquired) {
306
+ try {
307
+ const value = await fetchFn();
308
+ await redis.set(key, value, "EX", ttl);
309
+ return value;
310
+ } finally {
311
+ await redis.del(lockKey);
312
+ }
313
+ }
314
+
315
+ // Wait briefly and retry
316
+ await new Promise((resolve) => setTimeout(resolve, 100));
317
+ return getWithLock(key, fetchFn, ttl);
318
+ }
319
+
320
+ // Solution 2: Stale-while-revalidate (serve stale, refresh in background)
321
+ async function getStaleWhileRevalidate(key: string, fetchFn: () => Promise<string>, ttl: number, staleTTL: number): Promise<string | null> {
322
+ const cached = await redis.get(key);
323
+ const staleMarker = await redis.get(`stale:${key}`);
324
+
325
+ if (cached !== null) {
326
+ if (staleMarker === null) {
327
+ // Data is stale, refresh in background
328
+ fetchFn().then(async (value) => {
329
+ await redis.set(key, value, "EX", ttl + staleTTL);
330
+ await redis.set(`stale:${key}`, "1", "EX", ttl);
331
+ });
332
+ }
333
+ return cached;
334
+ }
335
+
336
+ // Full cache miss
337
+ const value = await fetchFn();
338
+ await redis.set(key, value, "EX", ttl + staleTTL);
339
+ await redis.set(`stale:${key}`, "1", "EX", ttl);
340
+ return value;
341
+ }
342
+ ```
343
+
344
+ ---
345
+
346
+ ## 3. Pub/Sub
347
+
348
+ ```typescript
349
+ import Redis from "ioredis";
350
+
351
+ const publisher = new Redis(process.env.REDIS_URL);
352
+ const subscriber = new Redis(process.env.REDIS_URL);
353
+
354
+ // Subscribe to channels
355
+ subscriber.subscribe("orders:created", "orders:updated", (err, count) => {
356
+ if (err) throw err;
357
+ console.log(`Subscribed to ${count} channels`);
358
+ });
359
+
360
+ // Handle messages
361
+ subscriber.on("message", (channel, message) => {
362
+ const data = JSON.parse(message);
363
+ switch (channel) {
364
+ case "orders:created":
365
+ handleNewOrder(data);
366
+ break;
367
+ case "orders:updated":
368
+ handleOrderUpdate(data);
369
+ break;
370
+ }
371
+ });
372
+
373
+ // Pattern subscribe (wildcard)
374
+ subscriber.psubscribe("events:*", (err) => {
375
+ if (err) throw err;
376
+ });
377
+
378
+ subscriber.on("pmessage", (pattern, channel, message) => {
379
+ console.log(`Pattern ${pattern}, channel ${channel}: ${message}`);
380
+ });
381
+
382
+ // Publish
383
+ await publisher.publish("orders:created", JSON.stringify({
384
+ orderId: "5001",
385
+ userId: "1001",
386
+ total: 59.99,
387
+ }));
388
+ ```
389
+
390
+ ### Pub/Sub Limitations
391
+
392
+ ```
393
+ - Messages are fire-and-forget: if no subscriber is listening, the message is lost
394
+ - No message persistence or replay
395
+ - No consumer groups (use Streams for this)
396
+ - Subscriber connections cannot run other commands
397
+ - All subscribers get all messages (no load balancing)
398
+
399
+ Use Streams instead when you need:
400
+ - Message durability
401
+ - Consumer groups (parallel processing)
402
+ - Message acknowledgment
403
+ - Replay from a specific point
404
+ ```
405
+
406
+ ---
407
+
408
+ ## 4. Lua Scripting
409
+
410
+ Lua scripts execute atomically on the Redis server. No other command runs during script execution.
411
+
412
+ ```typescript
413
+ // Rate limiter using Lua (atomic check-and-increment)
414
+ const rateLimitScript = `
415
+ local key = KEYS[1]
416
+ local limit = tonumber(ARGV[1])
417
+ local window = tonumber(ARGV[2])
418
+
419
+ local current = redis.call('GET', key)
420
+ if current and tonumber(current) >= limit then
421
+ return 0
422
+ end
423
+
424
+ current = redis.call('INCR', key)
425
+ if tonumber(current) == 1 then
426
+ redis.call('EXPIRE', key, window)
427
+ end
428
+
429
+ return 1
430
+ `;
431
+
432
+ // Usage
433
+ const allowed = await redis.eval(
434
+ rateLimitScript,
435
+ 1, // Number of KEYS
436
+ `ratelimit:${userId}`, // KEYS[1]
437
+ "100", // ARGV[1]: max requests
438
+ "60" // ARGV[2]: window in seconds
439
+ );
440
+
441
+ if (!allowed) {
442
+ throw new Error("Rate limit exceeded");
443
+ }
444
+
445
+ // Sliding window rate limiter with sorted sets
446
+ const slidingWindowScript = `
447
+ local key = KEYS[1]
448
+ local now = tonumber(ARGV[1])
449
+ local window = tonumber(ARGV[2])
450
+ local limit = tonumber(ARGV[3])
451
+ local member = ARGV[4]
452
+
453
+ local windowStart = now - window
454
+ redis.call('ZREMRANGEBYSCORE', key, '-inf', windowStart)
455
+
456
+ local count = redis.call('ZCARD', key)
457
+ if count >= limit then
458
+ return 0
459
+ end
460
+
461
+ redis.call('ZADD', key, now, member)
462
+ redis.call('EXPIRE', key, window)
463
+ return 1
464
+ `;
465
+
466
+ // Load script for repeated use (avoids sending full script each time)
467
+ const sha = await redis.script("LOAD", rateLimitScript);
468
+ const result = await redis.evalsha(sha, 1, `ratelimit:${userId}`, "100", "60");
469
+ ```
470
+
471
+ ---
472
+
473
+ ## 5. Transactions (MULTI/EXEC)
474
+
475
+ ```typescript
476
+ // MULTI/EXEC: all commands execute atomically
477
+ const pipeline = redis.multi();
478
+ pipeline.set("account:1001:balance", "500");
479
+ pipeline.set("account:1002:balance", "300");
480
+ pipeline.incrby("account:1001:balance", -100);
481
+ pipeline.incrby("account:1002:balance", 100);
482
+ const results = await pipeline.exec();
483
+ // results: [[null, "OK"], [null, "OK"], [null, 400], [null, 400]]
484
+
485
+ // WATCH for optimistic locking (CAS -- check-and-set)
486
+ async function transferFunds(fromId: string, toId: string, amount: number): Promise<boolean> {
487
+ const fromKey = `account:${fromId}:balance`;
488
+ const toKey = `account:${toId}:balance`;
489
+
490
+ // Watch keys for changes
491
+ await redis.watch(fromKey, toKey);
492
+
493
+ const balance = parseInt(await redis.get(fromKey) || "0", 10);
494
+ if (balance < amount) {
495
+ await redis.unwatch();
496
+ return false;
497
+ }
498
+
499
+ // If any watched key changed since WATCH, EXEC returns null
500
+ const result = await redis.multi()
501
+ .decrby(fromKey, amount)
502
+ .incrby(toKey, amount)
503
+ .exec();
504
+
505
+ return result !== null; // null means a watched key was modified
506
+ }
507
+ ```
508
+
509
+ ---
510
+
511
+ ## 6. Pipelining
512
+
513
+ ```typescript
514
+ // Pipelining: send multiple commands without waiting for individual responses
515
+ // Reduces round trips from N to 1
516
+
517
+ const pipeline = redis.pipeline();
518
+ for (let i = 0; i < 1000; i++) {
519
+ pipeline.set(`key:${i}`, `value:${i}`);
520
+ }
521
+ const results = await pipeline.exec();
522
+ // All 1000 commands sent in a single round trip
523
+
524
+ // Read pipeline
525
+ const readPipeline = redis.pipeline();
526
+ const userIds = ["1001", "1002", "1003", "1004", "1005"];
527
+ for (const id of userIds) {
528
+ readPipeline.hgetall(`user:${id}`);
529
+ }
530
+ const users = await readPipeline.exec();
531
+ // users: [[null, { name: "Alice", ... }], [null, { name: "Bob", ... }], ...]
532
+ ```
533
+
534
+ ### Pipeline vs MULTI
535
+
536
+ ```
537
+ Pipeline:
538
+ - Commands sent in batch (1 round trip)
539
+ - Commands may interleave with other clients' commands
540
+ - No atomicity guarantee
541
+ - Use for performance when atomicity is not needed
542
+
543
+ MULTI/EXEC:
544
+ - Commands queued and executed atomically
545
+ - No other command runs between them
546
+ - Slightly more overhead
547
+ - Use when atomicity matters
548
+
549
+ Pipeline + MULTI: combine for atomic batch operations in 1 round trip
550
+ ```
551
+
552
+ ---
553
+
554
+ ## 7. Redis Stack Modules
555
+
556
+ ### RedisJSON
557
+
558
+ ```redis
559
+ # Store JSON documents natively
560
+ JSON.SET user:1001 $ '{"name":"Alice","age":28,"address":{"city":"Portland","state":"OR"},"tags":["premium","early-adopter"]}'
561
+
562
+ # Get specific path
563
+ JSON.GET user:1001 $.name # "Alice"
564
+ JSON.GET user:1001 $.address.city # "Portland"
565
+ JSON.GET user:1001 $.tags[0] # "premium"
566
+
567
+ # Update nested value
568
+ JSON.SET user:1001 $.address.city '"Seattle"'
569
+
570
+ # Numeric operations
571
+ JSON.NUMINCRBY user:1001 $.age 1 # 29
572
+
573
+ # Array operations
574
+ JSON.ARRAPPEND user:1001 $.tags '"vip"' # Add to array
575
+ JSON.ARRLEN user:1001 $.tags # Array length
576
+ JSON.ARRPOP user:1001 $.tags # Pop last element
577
+
578
+ # Type checking
579
+ JSON.TYPE user:1001 $.name # string
580
+ JSON.TYPE user:1001 $.age # integer
581
+ ```
582
+
583
+ ### RediSearch
584
+
585
+ ```redis
586
+ # Create a search index on hashes
587
+ FT.CREATE idx:products ON HASH PREFIX 1 "product:"
588
+ SCHEMA
589
+ name TEXT WEIGHT 5.0
590
+ description TEXT
591
+ category TAG
592
+ price NUMERIC SORTABLE
593
+ in_stock TAG
594
+
595
+ # Search
596
+ FT.SEARCH idx:products "wireless headphones" LIMIT 0 10
597
+
598
+ # Filtered search
599
+ FT.SEARCH idx:products "@category:{electronics} @price:[50 200]"
600
+
601
+ # Autocomplete
602
+ FT.SUGADD autocomplete:products "Wireless Bluetooth Headphones" 100
603
+ FT.SUGGET autocomplete:products "wire" FUZZY MAX 5
604
+
605
+ # Aggregation
606
+ FT.AGGREGATE idx:products "*"
607
+ GROUPBY 1 @category
608
+ REDUCE COUNT 0 AS product_count
609
+ REDUCE AVG 1 @price AS avg_price
610
+ SORTBY 2 @product_count DESC
611
+ LIMIT 0 10
612
+ ```
613
+
614
+ ### RedisTimeSeries
615
+
616
+ ```redis
617
+ # Create a time series
618
+ TS.CREATE temperature:sensor-1 RETENTION 86400000 LABELS sensor_id "1" location "warehouse-a"
619
+
620
+ # Add data points
621
+ TS.ADD temperature:sensor-1 * 22.5 # Auto timestamp
622
+ TS.ADD temperature:sensor-1 1700000000 23.1 # Explicit timestamp
623
+
624
+ # Range query
625
+ TS.RANGE temperature:sensor-1 1700000000 1700003600
626
+
627
+ # Aggregation over time buckets
628
+ TS.RANGE temperature:sensor-1 - + AGGREGATION avg 3600000 # Hourly averages
629
+ TS.RANGE temperature:sensor-1 - + AGGREGATION max 86400000 # Daily maximums
630
+
631
+ # Multi-series query by labels
632
+ TS.MRANGE - + FILTER location="warehouse-a" AGGREGATION avg 3600000
633
+ ```
634
+
635
+ ### Bloom Filter
636
+
637
+ ```redis
638
+ # Create and add to a Bloom filter (probabilistic: no false negatives, possible false positives)
639
+ BF.ADD seen:emails "alice@example.com"
640
+ BF.ADD seen:emails "bob@example.com"
641
+
642
+ # Check membership (fast, memory-efficient)
643
+ BF.EXISTS seen:emails "alice@example.com" # 1 (definitely exists)
644
+ BF.EXISTS seen:emails "unknown@example.com" # 0 (definitely does not exist)
645
+
646
+ # Reserve with specific error rate and capacity
647
+ BF.RESERVE seen:emails 0.001 1000000 # 0.1% false positive rate, 1M capacity
648
+
649
+ # Use case: prevent duplicate processing
650
+ # Before processing an event, check if we have seen it before
651
+ # If BF.EXISTS returns 0, we know for certain it is new
652
+ ```
653
+
654
+ ---
655
+
656
+ ## 8. Key Naming Conventions
657
+
658
+ ```
659
+ Pattern: object-type:id:field
660
+
661
+ Examples:
662
+ user:1001 -- Hash of user data
663
+ user:1001:sessions -- Set of active session IDs
664
+ user:1001:notifications -- List of notifications
665
+ session:abc123 -- Session data (string or hash)
666
+ cache:api:products:list -- Cached API response
667
+ lock:order:5001 -- Distributed lock
668
+ ratelimit:ip:192.168.1.1 -- Rate limit counter
669
+ queue:emails -- Email processing queue
670
+ leaderboard:global -- Sorted set leaderboard
671
+ counter:page:views:home -- Page view counter
672
+ temp:import:batch-42 -- Temporary data with TTL
673
+
674
+ Conventions:
675
+ - Use colons (:) as separators
676
+ - Keep keys short but descriptive
677
+ - Prefix by data domain or application name in shared environments
678
+ - Use consistent patterns across the codebase
679
+ - Avoid very long keys (network overhead) but do not sacrifice clarity
680
+ ```
681
+
682
+ ---
683
+
684
+ ## 9. TTL Strategies
685
+
686
+ ```typescript
687
+ // Tier-based TTL
688
+ const TTL = {
689
+ SESSION: 24 * 60 * 60, // 24 hours
690
+ CACHE_API: 5 * 60, // 5 minutes
691
+ CACHE_DB: 60 * 60, // 1 hour
692
+ CACHE_STATIC: 24 * 60 * 60, // 24 hours
693
+ RATE_LIMIT: 60, // 1 minute window
694
+ LOCK: 30, // 30 seconds
695
+ TEMP: 10 * 60, // 10 minutes
696
+ } as const;
697
+
698
+ // Jittered TTL (prevent cache stampede from synchronized expiry)
699
+ function jitteredTTL(baseTTL: number): number {
700
+ const jitter = Math.floor(Math.random() * baseTTL * 0.1); // +/- 10%
701
+ return baseTTL + jitter;
702
+ }
703
+
704
+ await redis.set("cache:products:list", data, "EX", jitteredTTL(3600));
705
+
706
+ // Sliding expiration (reset TTL on access)
707
+ async function getWithSlidingExpiry(key: string, ttl: number): Promise<string | null> {
708
+ const value = await redis.get(key);
709
+ if (value !== null) {
710
+ await redis.expire(key, ttl); // Reset TTL on access
711
+ }
712
+ return value;
713
+ }
714
+
715
+ // Check remaining TTL
716
+ const remaining = await redis.ttl("session:abc123");
717
+ // -2: key does not exist
718
+ // -1: key exists but has no expiration
719
+ // N: seconds until expiration
720
+ ```
721
+
722
+ ---
723
+
724
+ ## 10. Memory Management
725
+
726
+ ### Eviction Policies
727
+
728
+ ```
729
+ # Set in redis.conf or at runtime
730
+ CONFIG SET maxmemory 2gb
731
+ CONFIG SET maxmemory-policy allkeys-lru
732
+
733
+ Policies:
734
+ noeviction -- Return errors when memory limit is reached (default)
735
+ allkeys-lru -- Evict least recently used keys (best for general caching)
736
+ allkeys-lfu -- Evict least frequently used keys (better for skewed access)
737
+ volatile-lru -- Evict LRU keys that have a TTL set
738
+ volatile-lfu -- Evict LFU keys that have a TTL set
739
+ volatile-ttl -- Evict keys with the shortest TTL first
740
+ allkeys-random -- Evict random keys
741
+ volatile-random -- Evict random keys that have a TTL set
742
+
743
+ Recommendations:
744
+ - Cache-only workloads: allkeys-lru or allkeys-lfu
745
+ - Mixed workloads (cache + persistent): volatile-lru
746
+ - Session stores: volatile-ttl
747
+ - Never use noeviction for cache workloads (causes write failures)
748
+ ```
749
+
750
+ ### Memory Optimization
751
+
752
+ ```redis
753
+ # Check memory usage
754
+ INFO memory
755
+ MEMORY USAGE user:1001 # Bytes used by a specific key
756
+ MEMORY DOCTOR # Diagnostic suggestions
757
+
758
+ # Optimize small hashes (ziplist encoding)
759
+ # When a hash has few fields and small values, Redis uses a compact encoding
760
+ CONFIG SET hash-max-ziplist-entries 128 # Max fields for ziplist
761
+ CONFIG SET hash-max-ziplist-value 64 # Max value size for ziplist
762
+
763
+ # Optimize small sorted sets
764
+ CONFIG SET zset-max-ziplist-entries 128
765
+ CONFIG SET zset-max-ziplist-value 64
766
+
767
+ # Optimize small lists
768
+ CONFIG SET list-max-ziplist-size -2 # 8 KB per node
769
+
770
+ # Scan for large keys
771
+ redis-cli --bigkeys
772
+
773
+ # Check key count and memory by pattern
774
+ redis-cli --memkeys --pattern "cache:*"
775
+ ```
776
+
777
+ ---
778
+
779
+ ## 11. Redis Cluster
780
+
781
+ ### Cluster Architecture
782
+
783
+ ```
784
+ - Data is split across 16384 hash slots
785
+ - Each primary node owns a range of hash slots
786
+ - Each primary can have one or more replicas
787
+ - Clients route commands to the correct node based on the key's hash slot
788
+ - Minimum: 3 primary nodes + 3 replicas (6 nodes total)
789
+ ```
790
+
791
+ ### Hash Tags (Force Keys to Same Slot)
792
+
793
+ ```redis
794
+ # Keys with the same hash tag go to the same slot
795
+ # Hash tag is the content between the first { and first }
796
+ SET {user:1001}:profile "..."
797
+ SET {user:1001}:settings "..."
798
+ SET {user:1001}:cart "..."
799
+
800
+ # These all hash on "user:1001" and land on the same node
801
+ # Multi-key commands (MGET, transactions) require same-slot keys
802
+
803
+ # Without hash tags, these could be on different nodes:
804
+ SET user:1001:profile "..." # Hashes on "user:1001:profile"
805
+ SET user:1001:settings "..." # Hashes on "user:1001:settings"
806
+ # MGET on these would fail in cluster mode
807
+ ```
808
+
809
+ ### ioredis Cluster Client
810
+
811
+ ```typescript
812
+ import Redis from "ioredis";
813
+
814
+ const cluster = new Redis.Cluster([
815
+ { host: "node1.example.com", port: 6379 },
816
+ { host: "node2.example.com", port: 6379 },
817
+ { host: "node3.example.com", port: 6379 },
818
+ ], {
819
+ redisOptions: {
820
+ password: process.env.REDIS_PASSWORD,
821
+ tls: {}, // Enable TLS for production
822
+ },
823
+ scaleReads: "slave", // Read from replicas
824
+ maxRedirections: 16, // Max MOVED/ASK redirections
825
+ retryDelayOnMoved: 100, // Delay on MOVED response (ms)
826
+ retryDelayOnCloverdown: 300, // Delay when cluster is down
827
+ enableReadyCheck: true,
828
+ natMap: {}, // NAT mapping for cloud environments
829
+ });
830
+
831
+ cluster.on("error", (err) => console.error("Cluster error:", err));
832
+ cluster.on("ready", () => console.log("Cluster ready"));
833
+ ```
834
+
835
+ ---
836
+
837
+ ## 12. Sentinel (High Availability)
838
+
839
+ ```typescript
840
+ // Sentinel monitors primary nodes and performs automatic failover
841
+ const redis = new Redis({
842
+ sentinels: [
843
+ { host: "sentinel1.example.com", port: 26379 },
844
+ { host: "sentinel2.example.com", port: 26379 },
845
+ { host: "sentinel3.example.com", port: 26379 },
846
+ ],
847
+ name: "mymaster", // Sentinel master name
848
+ password: process.env.REDIS_PASSWORD,
849
+ sentinelPassword: process.env.SENTINEL_PASSWORD,
850
+ db: 0,
851
+ role: "master", // Connect to master
852
+ // role: "slave", // Connect to a replica for reads
853
+ });
854
+
855
+ redis.on("error", (err) => console.error("Redis error:", err));
856
+ redis.on("reconnecting", () => console.log("Reconnecting to Redis..."));
857
+ redis.on("ready", () => console.log("Redis ready"));
858
+ ```
859
+
860
+ ### Cluster vs Sentinel
861
+
862
+ ```
863
+ Sentinel:
864
+ - Single primary with replicas
865
+ - Automatic failover on primary failure
866
+ - All data fits on one node
867
+ - Simpler setup and operations
868
+ - Use when data fits in a single node's memory
869
+
870
+ Cluster:
871
+ - Multiple primaries, each owning a slice of data
872
+ - Horizontal scaling (add nodes to add capacity)
873
+ - Data sharded across nodes
874
+ - More complex operations (resharding, rebalancing)
875
+ - Use when data exceeds single node memory or you need write scaling
876
+ ```
877
+
878
+ ---
879
+
880
+ ## 13. Client Libraries
881
+
882
+ ### ioredis (Node.js)
883
+
884
+ ```typescript
885
+ import Redis from "ioredis";
886
+
887
+ const redis = new Redis({
888
+ host: process.env.REDIS_HOST || "localhost",
889
+ port: parseInt(process.env.REDIS_PORT || "6379", 10),
890
+ password: process.env.REDIS_PASSWORD,
891
+ db: 0,
892
+ maxRetriesPerRequest: 3,
893
+ retryStrategy(times: number): number | null {
894
+ if (times > 10) return null; // Stop retrying after 10 attempts
895
+ return Math.min(times * 200, 2000); // Exponential backoff, max 2s
896
+ },
897
+ enableReadyCheck: true,
898
+ lazyConnect: true, // Connect on first command
899
+ keepAlive: 30000, // TCP keepalive (ms)
900
+ connectTimeout: 10000, // Connection timeout (ms)
901
+ commandTimeout: 5000, // Command timeout (ms)
902
+ });
903
+
904
+ // Error handling
905
+ redis.on("error", (err) => {
906
+ console.error("Redis connection error:", err);
907
+ });
908
+
909
+ redis.on("connect", () => {
910
+ console.log("Connected to Redis");
911
+ });
912
+
913
+ redis.on("ready", () => {
914
+ console.log("Redis is ready");
915
+ });
916
+
917
+ // Graceful shutdown
918
+ async function shutdown(): Promise<void> {
919
+ await redis.quit();
920
+ }
921
+ ```
922
+
923
+ ### redis-py (Python)
924
+
925
+ ```python
926
+ import redis
927
+ import json
928
+ from datetime import timedelta
929
+
930
+ # Connection pool (reuse connections across requests)
931
+ pool = redis.ConnectionPool(
932
+ host="localhost",
933
+ port=6379,
934
+ password="your_password",
935
+ db=0,
936
+ max_connections=50,
937
+ decode_responses=True, # Return strings instead of bytes
938
+ socket_timeout=5,
939
+ socket_connect_timeout=5,
940
+ retry_on_timeout=True,
941
+ )
942
+
943
+ r = redis.Redis(connection_pool=pool)
944
+
945
+ # Basic operations
946
+ r.set("key", "value", ex=3600)
947
+ value = r.get("key")
948
+
949
+ # Pipeline
950
+ pipe = r.pipeline(transaction=False) # Non-transactional pipeline
951
+ for i in range(1000):
952
+ pipe.set(f"key:{i}", f"value:{i}")
953
+ pipe.execute()
954
+
955
+ # Pub/Sub
956
+ pubsub = r.pubsub()
957
+ pubsub.subscribe("channel")
958
+ for message in pubsub.listen():
959
+ if message["type"] == "message":
960
+ data = json.loads(message["data"])
961
+ process(data)
962
+ ```
963
+
964
+ ---
965
+
966
+ ## 14. Rate Limiting with Sorted Sets
967
+
968
+ ```typescript
969
+ // Sliding window rate limiter
970
+ async function isRateLimited(
971
+ identifier: string,
972
+ maxRequests: number,
973
+ windowSeconds: number
974
+ ): Promise<{ limited: boolean; remaining: number; resetAt: number }> {
975
+ const key = `ratelimit:${identifier}`;
976
+ const now = Date.now();
977
+ const windowStart = now - windowSeconds * 1000;
978
+
979
+ // Atomic operation using pipeline
980
+ const pipeline = redis.pipeline();
981
+ pipeline.zremrangebyscore(key, "-inf", windowStart); // Remove old entries
982
+ pipeline.zadd(key, now, `${now}-${Math.random()}`); // Add current request
983
+ pipeline.zcard(key); // Count requests in window
984
+ pipeline.expire(key, windowSeconds); // Set key expiry
985
+
986
+ const results = await pipeline.exec();
987
+ const requestCount = results[2][1] as number;
988
+
989
+ return {
990
+ limited: requestCount > maxRequests,
991
+ remaining: Math.max(0, maxRequests - requestCount),
992
+ resetAt: now + windowSeconds * 1000,
993
+ };
994
+ }
995
+
996
+ // Usage
997
+ const { limited, remaining } = await isRateLimited("user:1001", 100, 60);
998
+ if (limited) {
999
+ return new Response("Too Many Requests", {
1000
+ status: 429,
1001
+ headers: { "X-RateLimit-Remaining": String(remaining) },
1002
+ });
1003
+ }
1004
+ ```
1005
+
1006
+ ---
1007
+
1008
+ ## 15. Common Anti-Patterns
1009
+
1010
+ ### Using KEYS in Production
1011
+
1012
+ ```redis
1013
+ # BAD: KEYS blocks the server, scans all keys
1014
+ KEYS user:*
1015
+
1016
+ # GOOD: Use SCAN for iterating keys (non-blocking, cursor-based)
1017
+ SCAN 0 MATCH user:* COUNT 100
1018
+ ```
1019
+
1020
+ ### Storing Large Values
1021
+
1022
+ ```
1023
+ # BAD: Storing 10 MB JSON blobs in a single key
1024
+ # Causes network latency, memory fragmentation, slow serialization
1025
+
1026
+ # GOOD: Break into smaller pieces
1027
+ # Store summary in a hash, details in separate keys
1028
+ # Use RedisJSON for nested document access without full deserialization
1029
+ ```
1030
+
1031
+ ### No TTL on Cache Keys
1032
+
1033
+ ```typescript
1034
+ // BAD: Cache without expiration (memory leak)
1035
+ await redis.set("cache:data", value);
1036
+
1037
+ // GOOD: Always set TTL on cache entries
1038
+ await redis.set("cache:data", value, "EX", 3600);
1039
+ ```
1040
+
1041
+ ### Hot Keys
1042
+
1043
+ ```
1044
+ # BAD: Single key receiving massive traffic (e.g., global counter)
1045
+ INCR global:page_views
1046
+
1047
+ # GOOD: Shard the hot key
1048
+ INCR global:page_views:{shard_id} # shard_id = hash(request_id) % N
1049
+ # Periodically aggregate shards
1050
+ ```
1051
+
1052
+ ---
1053
+
1054
+ ## 16. Critical Reminders
1055
+
1056
+ ### ALWAYS
1057
+
1058
+ - Set `maxmemory` and an eviction policy in production
1059
+ - Use connection pooling (never create a connection per request)
1060
+ - Set TTL on all cache keys
1061
+ - Use `SCAN` instead of `KEYS` for iteration
1062
+ - Use pipelining for batch operations
1063
+ - Handle connection errors and implement retry logic
1064
+ - Use Lua scripts for operations that must be atomic
1065
+ - Use hash tags in Cluster mode for multi-key operations
1066
+ - Monitor memory usage, hit rate, and slow log
1067
+ - Close connections gracefully on application shutdown
1068
+
1069
+ ### NEVER
1070
+
1071
+ - Use `KEYS *` in production (blocks the server)
1072
+ - Store values larger than 1 MB in a single key without good reason
1073
+ - Use Redis as a primary database without persistence configuration
1074
+ - Forget to handle `MOVED` and `ASK` redirections in Cluster mode
1075
+ - Use `FLUSHALL` or `FLUSHDB` in production without extreme caution
1076
+ - Leave `maxmemory` unset in production (Redis will use all available RAM)
1077
+ - Assume pub/sub messages are durable (they are fire-and-forget)
1078
+ - Use blocking commands (`BLPOP`, `BRPOP`) without timeouts
1079
+ - Store secrets or sensitive data without encryption