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.
- package/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,745 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: timescaledb
|
|
3
|
+
description: "Expert TimescaleDB guide covering hypertable design, continuous aggregates, compression, retention, hybrid time-series/relational queries, migration from vanilla PostgreSQL, and common anti-patterns. Use when designing time-series data models, building metrics pipelines, or integrating time-ordered data with relational entities."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# TimescaleDB Expert Guide
|
|
8
|
+
|
|
9
|
+
> Use this skill when designing time-series data models, creating hypertables, building continuous aggregates, configuring compression and retention policies, writing hybrid time-series/relational queries, or migrating existing PostgreSQL tables to hypertables. This skill assumes TimescaleDB 2.x (the current major version) unless noted otherwise.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
- Storing time-ordered data: metrics, events, logs, sensor readings, IoT telemetry, financial ticks
|
|
14
|
+
- Building dashboards that aggregate data over time windows
|
|
15
|
+
- Designing retention and compression policies for cost-effective long-term storage
|
|
16
|
+
- Writing queries that join time-series data with relational entities (devices, users, organizations)
|
|
17
|
+
- Migrating an existing PostgreSQL table with a time column to a hypertable
|
|
18
|
+
|
|
19
|
+
## When NOT to Use This Skill
|
|
20
|
+
|
|
21
|
+
- Non-time-ordered data with no temporal dimension → use the primary relational store
|
|
22
|
+
- Graph relationships → use Neo4j
|
|
23
|
+
- Semantic search / embeddings → use a vector store (Qdrant, pgvector)
|
|
24
|
+
- Simple key-value caching → use Redis
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 1. Hypertable Design
|
|
29
|
+
|
|
30
|
+
### Creating a Hypertable
|
|
31
|
+
|
|
32
|
+
Every hypertable starts as a regular PostgreSQL table, then is converted:
|
|
33
|
+
|
|
34
|
+
```sql
|
|
35
|
+
-- Step 1: Create a regular table
|
|
36
|
+
CREATE TABLE metrics (
|
|
37
|
+
time TIMESTAMPTZ NOT NULL,
|
|
38
|
+
device_id TEXT NOT NULL,
|
|
39
|
+
temperature DOUBLE PRECISION,
|
|
40
|
+
humidity DOUBLE PRECISION,
|
|
41
|
+
battery_pct SMALLINT
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
-- Step 2: Convert to hypertable
|
|
45
|
+
SELECT create_hypertable('metrics', 'time');
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Time Column Requirements
|
|
49
|
+
|
|
50
|
+
**Always use `TIMESTAMPTZ`** — never `TIMESTAMP` without timezone:
|
|
51
|
+
|
|
52
|
+
```sql
|
|
53
|
+
-- GOOD: timezone-aware
|
|
54
|
+
time TIMESTAMPTZ NOT NULL
|
|
55
|
+
|
|
56
|
+
-- BAD: timezone-naive — leads to ambiguity across regions and DST transitions
|
|
57
|
+
time TIMESTAMP NOT NULL
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Why: TimescaleDB uses the time column for chunk partitioning. Timezone-naive timestamps cause incorrect chunk boundaries when the application and database are in different timezones.
|
|
61
|
+
|
|
62
|
+
### Chunk Time Interval
|
|
63
|
+
|
|
64
|
+
The `chunk_time_interval` determines how large each chunk is. This is the single most important tuning parameter.
|
|
65
|
+
|
|
66
|
+
**Rule of thumb:** Chunks should hold approximately 25% of available RAM for hot (recent) data.
|
|
67
|
+
|
|
68
|
+
| Data Granularity | Typical Interval | Rationale |
|
|
69
|
+
|-----------------|-----------------|-----------|
|
|
70
|
+
| Sub-second / second-level | `1 day` | High volume — 1 day keeps each chunk manageable |
|
|
71
|
+
| Minute-level | `1 week` | Moderate volume — 1 week gives good compression ratios |
|
|
72
|
+
| Hourly | `1 month` | Lower volume — 1 month balances chunk count vs size |
|
|
73
|
+
| Daily | `3 months` | Very low volume — larger chunks avoid excessive metadata |
|
|
74
|
+
|
|
75
|
+
```sql
|
|
76
|
+
-- Set chunk interval at creation
|
|
77
|
+
SELECT create_hypertable('metrics', 'time',
|
|
78
|
+
chunk_time_interval => INTERVAL '1 day'
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
-- Change interval for future chunks (does not affect existing chunks)
|
|
82
|
+
SELECT set_chunk_time_interval('metrics', INTERVAL '7 days');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Space Partitioning
|
|
86
|
+
|
|
87
|
+
For high-cardinality workloads, add a second partitioning dimension:
|
|
88
|
+
|
|
89
|
+
```sql
|
|
90
|
+
-- Partition by time AND device_id (hash-based)
|
|
91
|
+
SELECT create_hypertable('metrics', 'time',
|
|
92
|
+
chunk_time_interval => INTERVAL '1 day'
|
|
93
|
+
);
|
|
94
|
+
SELECT add_dimension('metrics', 'device_id', number_partitions => 4);
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**When to use space partitioning:**
|
|
98
|
+
|
|
99
|
+
- You have many distinct devices/tenants writing concurrently
|
|
100
|
+
- Queries almost always filter by `device_id` in addition to time
|
|
101
|
+
- You need to distribute write load across multiple disks/tablespaces
|
|
102
|
+
|
|
103
|
+
**When NOT to use space partitioning:**
|
|
104
|
+
|
|
105
|
+
- Low cardinality (< 100 devices) — chunk pruning by time alone is sufficient
|
|
106
|
+
- Queries rarely filter by the space dimension — the extra chunks add overhead without benefit
|
|
107
|
+
|
|
108
|
+
### Inspecting Chunks
|
|
109
|
+
|
|
110
|
+
```sql
|
|
111
|
+
-- List all chunks with sizes
|
|
112
|
+
SELECT
|
|
113
|
+
hypertable_name,
|
|
114
|
+
chunk_name,
|
|
115
|
+
range_start,
|
|
116
|
+
range_end,
|
|
117
|
+
before_compression_total_bytes,
|
|
118
|
+
after_compression_total_bytes
|
|
119
|
+
FROM timescaledb_information.chunks
|
|
120
|
+
WHERE hypertable_name = 'metrics'
|
|
121
|
+
ORDER BY range_start DESC
|
|
122
|
+
LIMIT 20;
|
|
123
|
+
|
|
124
|
+
-- Count total chunks
|
|
125
|
+
SELECT count(*)
|
|
126
|
+
FROM timescaledb_information.chunks
|
|
127
|
+
WHERE hypertable_name = 'metrics';
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 2. Continuous Aggregates
|
|
133
|
+
|
|
134
|
+
### What They Are
|
|
135
|
+
|
|
136
|
+
Continuous aggregates are materialized views that automatically keep pre-computed aggregations in sync with the underlying hypertable. Since TimescaleDB 2.x, they are **real-time by default** — queries combine materialized data with the latest raw data that hasn't been materialized yet.
|
|
137
|
+
|
|
138
|
+
### Creating a Continuous Aggregate
|
|
139
|
+
|
|
140
|
+
```sql
|
|
141
|
+
-- Pre-compute hourly averages
|
|
142
|
+
CREATE MATERIALIZED VIEW metrics_hourly
|
|
143
|
+
WITH (timescaledb.continuous) AS
|
|
144
|
+
SELECT
|
|
145
|
+
time_bucket('1 hour', time) AS bucket,
|
|
146
|
+
device_id,
|
|
147
|
+
avg(temperature) AS avg_temp,
|
|
148
|
+
max(temperature) AS max_temp,
|
|
149
|
+
min(temperature) AS min_temp,
|
|
150
|
+
avg(humidity) AS avg_humidity,
|
|
151
|
+
count(*) AS sample_count
|
|
152
|
+
FROM metrics
|
|
153
|
+
GROUP BY bucket, device_id
|
|
154
|
+
WITH NO DATA; -- Don't backfill immediately (do it with a policy or manual refresh)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### time_bucket Function
|
|
158
|
+
|
|
159
|
+
```sql
|
|
160
|
+
-- Standard buckets
|
|
161
|
+
time_bucket('5 minutes', time)
|
|
162
|
+
time_bucket('1 hour', time)
|
|
163
|
+
time_bucket('1 day', time)
|
|
164
|
+
time_bucket('1 week', time)
|
|
165
|
+
|
|
166
|
+
-- Offset bucket start (e.g., daily buckets starting at 06:00 UTC)
|
|
167
|
+
time_bucket('1 day', time, TIMESTAMPTZ '2020-01-01 06:00:00+00')
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Refresh Policies
|
|
171
|
+
|
|
172
|
+
```sql
|
|
173
|
+
-- Automatically refresh the aggregate
|
|
174
|
+
-- Refreshes data from 3 hours ago to 1 hour ago, every hour
|
|
175
|
+
SELECT add_continuous_aggregate_policy('metrics_hourly',
|
|
176
|
+
start_offset => INTERVAL '3 hours',
|
|
177
|
+
end_offset => INTERVAL '1 hour',
|
|
178
|
+
schedule_interval => INTERVAL '1 hour'
|
|
179
|
+
);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**Why `end_offset` is not zero:** In-progress time buckets (the current hour) may receive more data. Setting `end_offset => INTERVAL '1 hour'` ensures only fully complete buckets are materialized. The real-time aggregation feature automatically includes the latest data in query results.
|
|
183
|
+
|
|
184
|
+
### Manual Refresh
|
|
185
|
+
|
|
186
|
+
```sql
|
|
187
|
+
-- Backfill historical data
|
|
188
|
+
CALL refresh_continuous_aggregate('metrics_hourly',
|
|
189
|
+
'2024-01-01',
|
|
190
|
+
'2024-06-01'
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Real-Time Aggregates
|
|
195
|
+
|
|
196
|
+
Real-time aggregation is enabled by default in TimescaleDB 2.x. When a query hits a continuous aggregate:
|
|
197
|
+
|
|
198
|
+
1. Materialized data is read from the aggregate
|
|
199
|
+
2. Raw data newer than the last materialization is queried from the hypertable
|
|
200
|
+
3. Both are combined and returned as a single result
|
|
201
|
+
|
|
202
|
+
To disable (e.g., for strict performance guarantees at the cost of freshness):
|
|
203
|
+
|
|
204
|
+
```sql
|
|
205
|
+
ALTER MATERIALIZED VIEW metrics_hourly SET (timescaledb.materialized_only = true);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### When to Use Continuous Aggregates
|
|
209
|
+
|
|
210
|
+
| Scenario | Use Continuous Aggregate? |
|
|
211
|
+
|----------|--------------------------|
|
|
212
|
+
| Dashboard showing 30-day trends | ✅ Yes — avoids scanning 30 days of raw data on every page load |
|
|
213
|
+
| One-off ad-hoc analysis query | ❌ No — just query the raw hypertable directly |
|
|
214
|
+
| Real-time alerting on latest values | ❌ No — query raw data for sub-second freshness |
|
|
215
|
+
| Multi-resolution drill-down (hourly → daily → monthly) | ✅ Yes — create one aggregate per resolution |
|
|
216
|
+
|
|
217
|
+
### Hierarchical Continuous Aggregates
|
|
218
|
+
|
|
219
|
+
You can build aggregates on top of other aggregates:
|
|
220
|
+
|
|
221
|
+
```sql
|
|
222
|
+
-- Daily aggregate built from the hourly aggregate
|
|
223
|
+
CREATE MATERIALIZED VIEW metrics_daily
|
|
224
|
+
WITH (timescaledb.continuous) AS
|
|
225
|
+
SELECT
|
|
226
|
+
time_bucket('1 day', bucket) AS bucket,
|
|
227
|
+
device_id,
|
|
228
|
+
avg(avg_temp) AS avg_temp,
|
|
229
|
+
max(max_temp) AS max_temp,
|
|
230
|
+
min(min_temp) AS min_temp,
|
|
231
|
+
sum(sample_count) AS sample_count
|
|
232
|
+
FROM metrics_hourly
|
|
233
|
+
GROUP BY time_bucket('1 day', bucket), device_id
|
|
234
|
+
WITH NO DATA;
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 3. Compression Policy
|
|
240
|
+
|
|
241
|
+
### Enabling Compression
|
|
242
|
+
|
|
243
|
+
```sql
|
|
244
|
+
-- Configure compression settings
|
|
245
|
+
ALTER TABLE metrics SET (
|
|
246
|
+
timescaledb.compress,
|
|
247
|
+
timescaledb.compress_segmentby = 'device_id',
|
|
248
|
+
timescaledb.compress_orderby = 'time DESC'
|
|
249
|
+
);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**`compress_segmentby`** — columns that queries filter by. Data is grouped by segment before compression, so queries that filter by `device_id` only decompress the relevant segments.
|
|
253
|
+
|
|
254
|
+
**`compress_orderby`** — the sort order within each segment. Use `time DESC` for queries that read recent data first.
|
|
255
|
+
|
|
256
|
+
### Adding a Compression Policy
|
|
257
|
+
|
|
258
|
+
```sql
|
|
259
|
+
-- Compress chunks older than 7 days
|
|
260
|
+
SELECT add_compression_policy('metrics', INTERVAL '7 days');
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Compression Ratios
|
|
264
|
+
|
|
265
|
+
Typical compression ratios for time-series data:
|
|
266
|
+
|
|
267
|
+
| Data Type | Expected Ratio |
|
|
268
|
+
|-----------|---------------|
|
|
269
|
+
| Numeric metrics (temperature, counts) | 10–20× |
|
|
270
|
+
| Mixed numeric + text | 5–15× |
|
|
271
|
+
| High-cardinality string columns | 3–8× |
|
|
272
|
+
| Already-compressed or random data | 1–3× |
|
|
273
|
+
|
|
274
|
+
### Checking Compression Status
|
|
275
|
+
|
|
276
|
+
```sql
|
|
277
|
+
-- Compression stats per hypertable
|
|
278
|
+
SELECT
|
|
279
|
+
hypertable_name,
|
|
280
|
+
sum(before_compression_total_bytes) AS total_uncompressed,
|
|
281
|
+
sum(after_compression_total_bytes) AS total_compressed,
|
|
282
|
+
round(
|
|
283
|
+
sum(before_compression_total_bytes)::numeric /
|
|
284
|
+
NULLIF(sum(after_compression_total_bytes), 0)::numeric,
|
|
285
|
+
1
|
|
286
|
+
) AS compression_ratio
|
|
287
|
+
FROM timescaledb_information.chunks
|
|
288
|
+
WHERE is_compressed = true
|
|
289
|
+
GROUP BY hypertable_name;
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Decompressing for Schema Changes
|
|
293
|
+
|
|
294
|
+
Compressed chunks are read-only. To alter the schema or backfill data:
|
|
295
|
+
|
|
296
|
+
```sql
|
|
297
|
+
-- Decompress a specific chunk
|
|
298
|
+
SELECT decompress_chunk('_timescaledb_internal._hyper_1_42_chunk');
|
|
299
|
+
|
|
300
|
+
-- Decompress all chunks in a time range
|
|
301
|
+
SELECT decompress_chunk(c.chunk_name)
|
|
302
|
+
FROM timescaledb_information.chunks c
|
|
303
|
+
WHERE c.hypertable_name = 'metrics'
|
|
304
|
+
AND c.is_compressed = true
|
|
305
|
+
AND c.range_start >= '2024-01-01'
|
|
306
|
+
AND c.range_end <= '2024-02-01';
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
After making changes, re-compress:
|
|
310
|
+
|
|
311
|
+
```sql
|
|
312
|
+
SELECT compress_chunk(c.chunk_name)
|
|
313
|
+
FROM timescaledb_information.chunks c
|
|
314
|
+
WHERE c.hypertable_name = 'metrics'
|
|
315
|
+
AND c.is_compressed = false
|
|
316
|
+
AND c.range_end < NOW() - INTERVAL '7 days';
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 4. Retention Policy
|
|
322
|
+
|
|
323
|
+
### Automated Data Expiry
|
|
324
|
+
|
|
325
|
+
```sql
|
|
326
|
+
-- Drop chunks older than 90 days
|
|
327
|
+
SELECT add_retention_policy('metrics', INTERVAL '90 days');
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
This physically deletes entire chunks (not individual rows), making it extremely fast.
|
|
331
|
+
|
|
332
|
+
### Tiered Storage
|
|
333
|
+
|
|
334
|
+
TimescaleDB supports moving cold chunks to object storage (e.g., S3) instead of deleting them:
|
|
335
|
+
|
|
336
|
+
```sql
|
|
337
|
+
-- Move chunks older than 30 days to the tiered storage (TimescaleDB Cloud with tiering)
|
|
338
|
+
SELECT add_tiering_policy('metrics', INTERVAL '30 days');
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Tiered chunks remain queryable (slower reads) but do not consume local disk space.
|
|
342
|
+
|
|
343
|
+
### Continuous Aggregates Outlive Raw Data
|
|
344
|
+
|
|
345
|
+
A continuous aggregate can retain summarized data even after the raw data is dropped:
|
|
346
|
+
|
|
347
|
+
```
|
|
348
|
+
Raw data: [-----retained-----][---dropped---]
|
|
349
|
+
|<--- 90 days ----->|
|
|
350
|
+
Hourly aggregate: [--retained for 1 year--]
|
|
351
|
+
Daily aggregate: [--retained for 5 years--]
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Set separate retention policies per aggregate:
|
|
355
|
+
|
|
356
|
+
```sql
|
|
357
|
+
-- Raw data: 90 days
|
|
358
|
+
SELECT add_retention_policy('metrics', INTERVAL '90 days');
|
|
359
|
+
|
|
360
|
+
-- Hourly aggregate: 1 year
|
|
361
|
+
SELECT add_retention_policy('metrics_hourly', INTERVAL '365 days');
|
|
362
|
+
|
|
363
|
+
-- Daily aggregate: 5 years
|
|
364
|
+
SELECT add_retention_policy('metrics_daily', INTERVAL '1825 days');
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Cost vs Debuggability Tradeoff
|
|
368
|
+
|
|
369
|
+
| Approach | Cost | Debuggability |
|
|
370
|
+
|----------|------|---------------|
|
|
371
|
+
| Keep all raw data | High storage cost | Full replay and drill-down capability |
|
|
372
|
+
| 90-day raw + 1-year hourly | Moderate | Can investigate recent issues in detail; older issues only at hourly resolution |
|
|
373
|
+
| 30-day raw + 1-year daily | Low | Recent debugging OK; older issues require daily-level clues |
|
|
374
|
+
| Aggregate-only (no raw retention) | Minimal | Cannot investigate individual events |
|
|
375
|
+
|
|
376
|
+
**Recommendation:** Start with 90-day raw + 1-year hourly aggregate. Adjust based on actual storage costs and debugging needs after the first month of production data.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## 5. Hybrid Queries
|
|
381
|
+
|
|
382
|
+
### TimescaleDB IS PostgreSQL
|
|
383
|
+
|
|
384
|
+
TimescaleDB is a PostgreSQL extension — all Postgres features work:
|
|
385
|
+
|
|
386
|
+
- Common Table Expressions (CTEs)
|
|
387
|
+
- Window functions
|
|
388
|
+
- Lateral joins
|
|
389
|
+
- Row-Level Security (RLS)
|
|
390
|
+
- JSONB columns and operators
|
|
391
|
+
- Foreign keys to regular tables
|
|
392
|
+
- Triggers and functions
|
|
393
|
+
|
|
394
|
+
### Joining Hypertables with Regular Tables
|
|
395
|
+
|
|
396
|
+
The most common pattern: join a `metrics` hypertable with a `devices` regular table to enrich time-series rows with device metadata.
|
|
397
|
+
|
|
398
|
+
```sql
|
|
399
|
+
-- Regular table: device metadata
|
|
400
|
+
CREATE TABLE devices (
|
|
401
|
+
device_id TEXT PRIMARY KEY,
|
|
402
|
+
device_name TEXT NOT NULL,
|
|
403
|
+
location TEXT NOT NULL,
|
|
404
|
+
owner_id UUID REFERENCES users(id),
|
|
405
|
+
installed_at TIMESTAMPTZ NOT NULL
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
-- Hypertable: device metrics
|
|
409
|
+
CREATE TABLE metrics (
|
|
410
|
+
time TIMESTAMPTZ NOT NULL,
|
|
411
|
+
device_id TEXT NOT NULL REFERENCES devices(device_id),
|
|
412
|
+
temperature DOUBLE PRECISION,
|
|
413
|
+
humidity DOUBLE PRECISION
|
|
414
|
+
);
|
|
415
|
+
SELECT create_hypertable('metrics', 'time');
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Query: Latest reading per device with metadata
|
|
419
|
+
|
|
420
|
+
```sql
|
|
421
|
+
SELECT DISTINCT ON (d.device_id)
|
|
422
|
+
d.device_id,
|
|
423
|
+
d.device_name,
|
|
424
|
+
d.location,
|
|
425
|
+
m.time AS last_reading_at,
|
|
426
|
+
m.temperature,
|
|
427
|
+
m.humidity
|
|
428
|
+
FROM devices d
|
|
429
|
+
JOIN metrics m ON m.device_id = d.device_id
|
|
430
|
+
WHERE m.time >= NOW() - INTERVAL '1 hour'
|
|
431
|
+
ORDER BY d.device_id, m.time DESC;
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
### Query: Hourly averages for a specific location
|
|
435
|
+
|
|
436
|
+
```sql
|
|
437
|
+
SELECT
|
|
438
|
+
time_bucket('1 hour', m.time) AS hour,
|
|
439
|
+
d.location,
|
|
440
|
+
avg(m.temperature) AS avg_temp,
|
|
441
|
+
avg(m.humidity) AS avg_humidity,
|
|
442
|
+
count(*) AS readings
|
|
443
|
+
FROM metrics m
|
|
444
|
+
JOIN devices d ON d.device_id = m.device_id
|
|
445
|
+
WHERE d.location = 'Building A - Floor 3'
|
|
446
|
+
AND m.time >= NOW() - INTERVAL '24 hours'
|
|
447
|
+
GROUP BY hour, d.location
|
|
448
|
+
ORDER BY hour DESC;
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Query: Window function — detect temperature spikes
|
|
452
|
+
|
|
453
|
+
```sql
|
|
454
|
+
WITH readings AS (
|
|
455
|
+
SELECT
|
|
456
|
+
time,
|
|
457
|
+
device_id,
|
|
458
|
+
temperature,
|
|
459
|
+
lag(temperature) OVER (
|
|
460
|
+
PARTITION BY device_id ORDER BY time
|
|
461
|
+
) AS prev_temp
|
|
462
|
+
FROM metrics
|
|
463
|
+
WHERE time >= NOW() - INTERVAL '1 hour'
|
|
464
|
+
)
|
|
465
|
+
SELECT
|
|
466
|
+
time,
|
|
467
|
+
device_id,
|
|
468
|
+
temperature,
|
|
469
|
+
prev_temp,
|
|
470
|
+
temperature - prev_temp AS delta
|
|
471
|
+
FROM readings
|
|
472
|
+
WHERE abs(temperature - prev_temp) > 5.0
|
|
473
|
+
ORDER BY abs(temperature - prev_temp) DESC;
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Query: Lateral join — top 3 recent readings per device
|
|
477
|
+
|
|
478
|
+
```sql
|
|
479
|
+
SELECT d.device_id, d.device_name, latest.*
|
|
480
|
+
FROM devices d,
|
|
481
|
+
LATERAL (
|
|
482
|
+
SELECT time, temperature, humidity
|
|
483
|
+
FROM metrics m
|
|
484
|
+
WHERE m.device_id = d.device_id
|
|
485
|
+
ORDER BY m.time DESC
|
|
486
|
+
LIMIT 3
|
|
487
|
+
) AS latest
|
|
488
|
+
ORDER BY d.device_id, latest.time DESC;
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## 6. Migration from Vanilla PostgreSQL
|
|
494
|
+
|
|
495
|
+
### Converting an Existing Table
|
|
496
|
+
|
|
497
|
+
If the table already has data, use `migrate_data`:
|
|
498
|
+
|
|
499
|
+
```sql
|
|
500
|
+
-- Table already exists with data
|
|
501
|
+
SELECT create_hypertable('existing_metrics', 'time',
|
|
502
|
+
migrate_data => true
|
|
503
|
+
);
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
> ⚠️ **This locks the table during migration.** For large tables, schedule during a maintenance window.
|
|
507
|
+
|
|
508
|
+
### Backfilling Data in Batches
|
|
509
|
+
|
|
510
|
+
For very large backfills, avoid a single massive `INSERT` — it creates one huge chunk:
|
|
511
|
+
|
|
512
|
+
```sql
|
|
513
|
+
-- BAD: Single bulk insert
|
|
514
|
+
INSERT INTO metrics_hypertable
|
|
515
|
+
SELECT * FROM metrics_old;
|
|
516
|
+
|
|
517
|
+
-- GOOD: Batch by time range
|
|
518
|
+
DO $$
|
|
519
|
+
DECLARE
|
|
520
|
+
batch_start TIMESTAMPTZ := '2023-01-01';
|
|
521
|
+
batch_end TIMESTAMPTZ;
|
|
522
|
+
BEGIN
|
|
523
|
+
WHILE batch_start < '2024-01-01' LOOP
|
|
524
|
+
batch_end := batch_start + INTERVAL '1 day';
|
|
525
|
+
|
|
526
|
+
INSERT INTO metrics_hypertable
|
|
527
|
+
SELECT * FROM metrics_old
|
|
528
|
+
WHERE time >= batch_start AND time < batch_end;
|
|
529
|
+
|
|
530
|
+
COMMIT;
|
|
531
|
+
batch_start := batch_end;
|
|
532
|
+
END LOOP;
|
|
533
|
+
END $$;
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
### Index Considerations Post-Conversion
|
|
537
|
+
|
|
538
|
+
When a regular table is converted to a hypertable:
|
|
539
|
+
|
|
540
|
+
- Existing indexes are preserved
|
|
541
|
+
- New chunk-level indexes are created automatically for each chunk
|
|
542
|
+
- The global index is replaced by per-chunk indexes (this is transparent to queries)
|
|
543
|
+
|
|
544
|
+
Review indexes after conversion:
|
|
545
|
+
|
|
546
|
+
```sql
|
|
547
|
+
-- List indexes on the hypertable
|
|
548
|
+
SELECT indexname, indexdef
|
|
549
|
+
FROM pg_indexes
|
|
550
|
+
WHERE tablename = 'metrics';
|
|
551
|
+
|
|
552
|
+
-- Check that frequently filtered columns are indexed
|
|
553
|
+
-- TimescaleDB automatically creates a time index, but device_id may need one
|
|
554
|
+
CREATE INDEX idx_metrics_device_id ON metrics (device_id, time DESC);
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### Pre-Migration Checklist
|
|
558
|
+
|
|
559
|
+
| Step | Action |
|
|
560
|
+
|------|--------|
|
|
561
|
+
| 1 | Verify the time column is `TIMESTAMPTZ` (not `TIMESTAMP`) |
|
|
562
|
+
| 2 | Choose `chunk_time_interval` based on data volume |
|
|
563
|
+
| 3 | Identify columns for `compress_segmentby` |
|
|
564
|
+
| 4 | Plan a maintenance window for `migrate_data` if the table is large |
|
|
565
|
+
| 5 | Test on a staging copy first |
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
## 7. Driver Setup
|
|
570
|
+
|
|
571
|
+
### No Special Client Needed
|
|
572
|
+
|
|
573
|
+
TimescaleDB uses the standard PostgreSQL wire protocol. Any PostgreSQL client library connects normally:
|
|
574
|
+
|
|
575
|
+
| Language | Library | Connection |
|
|
576
|
+
|----------|---------|-----------|
|
|
577
|
+
| JavaScript/TypeScript | `postgres` (postgres.js), `pg` | Standard Postgres DSN |
|
|
578
|
+
| Python | `psycopg2`, `asyncpg`, `sqlalchemy` | Standard Postgres DSN |
|
|
579
|
+
| Go | `pgx`, `database/sql` + `lib/pq` | Standard Postgres DSN |
|
|
580
|
+
| Rust | `tokio-postgres`, `sqlx` | Standard Postgres DSN |
|
|
581
|
+
| Java | JDBC (`org.postgresql.Driver`) | Standard Postgres JDBC URL |
|
|
582
|
+
|
|
583
|
+
### Connection String
|
|
584
|
+
|
|
585
|
+
```
|
|
586
|
+
postgresql://user:password@host:5432/dbname?sslmode=require
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
No TimescaleDB-specific parameters in the connection string.
|
|
590
|
+
|
|
591
|
+
### TimescaleDB-Specific Settings
|
|
592
|
+
|
|
593
|
+
```sql
|
|
594
|
+
-- Disable telemetry for privacy-sensitive deployments
|
|
595
|
+
ALTER SYSTEM SET timescaledb.telemetry_level = 'off';
|
|
596
|
+
SELECT pg_reload_conf();
|
|
597
|
+
|
|
598
|
+
-- Verify TimescaleDB is loaded
|
|
599
|
+
SHOW timescaledb.version;
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### ORM Compatibility
|
|
603
|
+
|
|
604
|
+
TimescaleDB works with any PostgreSQL-compatible ORM:
|
|
605
|
+
|
|
606
|
+
- **Drizzle ORM** — hypertables are regular tables; use raw SQL for `create_hypertable()` and policies
|
|
607
|
+
- **Prisma** — same; use `$executeRawUnsafe` for TimescaleDB-specific DDL
|
|
608
|
+
- **SQLAlchemy** — the `sqlalchemy-timescaledb` dialect adds hypertable support
|
|
609
|
+
|
|
610
|
+
**Rule:** Use the ORM for standard CRUD on regular tables. Use raw SQL for TimescaleDB-specific operations (hypertable creation, policies, continuous aggregates).
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## 8. Common Anti-Patterns
|
|
615
|
+
|
|
616
|
+
### 1. Wrong Chunk Interval
|
|
617
|
+
|
|
618
|
+
**Problem:** Chunk interval too small → too many chunks → slow metadata queries and planning overhead.
|
|
619
|
+
|
|
620
|
+
```sql
|
|
621
|
+
-- BAD: 1-minute chunks on a table with millions of rows per day
|
|
622
|
+
SELECT create_hypertable('metrics', 'time',
|
|
623
|
+
chunk_time_interval => INTERVAL '1 minute'
|
|
624
|
+
);
|
|
625
|
+
-- Results in 1,440 chunks per day, 43,800 per month — metadata queries become slow
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
**Problem:** Chunk interval too large → chunks cannot be pruned for range queries.
|
|
629
|
+
|
|
630
|
+
```sql
|
|
631
|
+
-- BAD: 1-year chunks
|
|
632
|
+
SELECT create_hypertable('metrics', 'time',
|
|
633
|
+
chunk_time_interval => INTERVAL '1 year'
|
|
634
|
+
);
|
|
635
|
+
-- A query for "last 1 hour" still scans a 1-year chunk
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
**Fix:** Use the rule-of-thumb table in Section 1. Start with `1 day` for high-frequency data, `1 week` for moderate, `1 month` for low-frequency. Monitor chunk sizes with `timescaledb_information.chunks` and adjust.
|
|
639
|
+
|
|
640
|
+
### 2. Missing Indexes on Non-Time Columns
|
|
641
|
+
|
|
642
|
+
**Problem:** Hypertable chunk pruning only works on the time column. Queries filtering by `device_id` without an index on that column scan the entire chunk.
|
|
643
|
+
|
|
644
|
+
```sql
|
|
645
|
+
-- Chunk pruning eliminates old chunks, but within the matching chunks,
|
|
646
|
+
-- every row is scanned because device_id has no index
|
|
647
|
+
SELECT * FROM metrics
|
|
648
|
+
WHERE time >= NOW() - INTERVAL '1 hour'
|
|
649
|
+
AND device_id = 'sensor-42';
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
**Fix:** Create a composite index on frequently filtered columns:
|
|
653
|
+
|
|
654
|
+
```sql
|
|
655
|
+
CREATE INDEX idx_metrics_device_time
|
|
656
|
+
ON metrics (device_id, time DESC);
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### 3. Not Using Continuous Aggregates for Expensive Recurring Queries
|
|
660
|
+
|
|
661
|
+
**Problem:** A dashboard computes 30-day aggregates on every page load by scanning raw data.
|
|
662
|
+
|
|
663
|
+
```sql
|
|
664
|
+
-- Every page load runs this — scanning 30 days of raw data
|
|
665
|
+
SELECT
|
|
666
|
+
time_bucket('1 day', time) AS day,
|
|
667
|
+
avg(temperature)
|
|
668
|
+
FROM metrics
|
|
669
|
+
WHERE time >= NOW() - INTERVAL '30 days'
|
|
670
|
+
GROUP BY day
|
|
671
|
+
ORDER BY day;
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
**Fix:** Create a continuous aggregate and query it instead:
|
|
675
|
+
|
|
676
|
+
```sql
|
|
677
|
+
-- One-time setup
|
|
678
|
+
CREATE MATERIALIZED VIEW metrics_daily ...;
|
|
679
|
+
SELECT add_continuous_aggregate_policy(...);
|
|
680
|
+
|
|
681
|
+
-- Dashboard query — reads pre-computed data
|
|
682
|
+
SELECT bucket, avg_temp FROM metrics_daily
|
|
683
|
+
WHERE bucket >= NOW() - INTERVAL '30 days'
|
|
684
|
+
ORDER BY bucket;
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
### 4. Querying Without a Time Filter
|
|
688
|
+
|
|
689
|
+
**Problem:** Omitting `WHERE time >= ...` prevents chunk exclusion — the query scans ALL chunks.
|
|
690
|
+
|
|
691
|
+
```sql
|
|
692
|
+
-- BAD: No time filter — scans every chunk in the hypertable
|
|
693
|
+
SELECT avg(temperature) FROM metrics WHERE device_id = 'sensor-42';
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
**Fix:** Always include a time filter, even if generous:
|
|
697
|
+
|
|
698
|
+
```sql
|
|
699
|
+
-- GOOD: Chunk exclusion kicks in
|
|
700
|
+
SELECT avg(temperature) FROM metrics
|
|
701
|
+
WHERE device_id = 'sensor-42'
|
|
702
|
+
AND time >= NOW() - INTERVAL '365 days';
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### 5. Storing Non-Time-Series Data in Hypertables
|
|
706
|
+
|
|
707
|
+
**Problem:** Converting tables without a meaningful time dimension to hypertables.
|
|
708
|
+
|
|
709
|
+
```sql
|
|
710
|
+
-- BAD: Device metadata has no time-series nature
|
|
711
|
+
CREATE TABLE devices (id TEXT, name TEXT, location TEXT, updated_at TIMESTAMPTZ);
|
|
712
|
+
SELECT create_hypertable('devices', 'updated_at');
|
|
713
|
+
-- updated_at is not a time-series dimension — it's a last-modified timestamp
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
**Fix:** Only convert tables where the time column represents continuous, append-only time-series data. Device metadata belongs in a regular PostgreSQL table.
|
|
717
|
+
|
|
718
|
+
### 6. Single Large INSERT for Backfill
|
|
719
|
+
|
|
720
|
+
**Problem:** Inserting millions of rows in a single statement creates pressure on WAL, locks, and memory.
|
|
721
|
+
|
|
722
|
+
```sql
|
|
723
|
+
-- BAD: 100M rows in one statement
|
|
724
|
+
INSERT INTO metrics SELECT * FROM old_metrics;
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
**Fix:** Batch by time range as shown in Section 6 (Migration from Vanilla PostgreSQL).
|
|
728
|
+
|
|
729
|
+
### 7. Not Verifying TimescaleDB Extension is Loaded
|
|
730
|
+
|
|
731
|
+
**Problem:** Running TimescaleDB-specific SQL on a vanilla PostgreSQL instance.
|
|
732
|
+
|
|
733
|
+
```sql
|
|
734
|
+
-- Fails silently or with cryptic errors if the extension isn't loaded
|
|
735
|
+
SELECT create_hypertable('metrics', 'time');
|
|
736
|
+
-- ERROR: function create_hypertable(unknown, unknown) does not exist
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
**Fix:** Always verify on application startup:
|
|
740
|
+
|
|
741
|
+
```sql
|
|
742
|
+
SELECT installed_version FROM pg_available_extensions WHERE name = 'timescaledb';
|
|
743
|
+
-- Should return a version like '2.14.2'
|
|
744
|
+
-- If NULL, the extension is not installed
|
|
745
|
+
```
|