vybekiit 0.7.26 → 0.7.27
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/dist/bin.js +3891 -1301
- package/dist/global-skills/aws-cdk/SKILL.md +19 -5
- package/dist/global-skills/aws-cdk/references/fast-deployments.md +191 -0
- package/dist/global-skills/aws-cdk/references/troubleshooting-deployment.md +16 -0
- package/dist/global-skills/aws-cloudformation/SKILL.md +16 -26
- package/dist/global-skills/aws-cloudformation/references/check-cloudformation-template-compliance.script.md +7 -3
- package/dist/global-skills/aws-cloudformation/references/cloudformation-language-server.md +177 -0
- package/dist/global-skills/aws-cloudformation/references/cloudformation-pre-deploy-validation.script.md +8 -2
- package/dist/global-skills/aws-cloudformation/references/persist-template-context.script.md +5 -8
- package/dist/global-skills/aws-cloudformation/references/retrieve-template-context.script.md +1 -1
- package/dist/global-skills/aws-cloudformation/references/security-considerations.md +51 -0
- package/dist/global-skills/aws-cloudformation/references/troubleshoot-failed-stack.script.md +138 -0
- package/dist/global-skills/aws-cloudformation/references/{validate-cloudformation-template.script.md → validate-with-cfn-lint.script.md} +15 -27
- package/dist/global-skills/aws-cloudformation/references/validate-with-cloudformation-validate.script.md +181 -0
- package/dist/global-skills/aws-cloudformation/references/validation-tool-selection.md +44 -0
- package/dist/global-skills/aws-serverless/SKILL.md +9 -1
- package/dist/global-skills/aws-serverless/references/architecture.md +3 -1
- package/dist/global-skills/aws-serverless/references/lambda.md +3 -1
- package/dist/global-skills/aws-serverless/references/orchestration.md +1 -0
- package/dist/global-skills/better-auth-best-practices/SKILL.md +18 -8
- package/dist/global-skills/eas-app-stores/SKILL.md +31 -15
- package/dist/global-skills/eas-app-stores/agents/openai.yaml +2 -2
- package/dist/global-skills/eas-app-stores/references/ios-app-store.md +37 -32
- package/dist/global-skills/eas-app-stores/references/native-ios.md +167 -0
- package/dist/global-skills/eas-app-stores/references/play-store.md +3 -7
- package/dist/global-skills/eas-app-stores/references/testflight.md +39 -35
- package/dist/global-skills/eas-simulator/SKILL.md +48 -26
- package/dist/global-skills/eas-simulator/references/controllers.md +32 -3
- package/dist/global-skills/eas-simulator/references/run-your-app.md +34 -4
- package/dist/global-skills/eas-simulator/references/troubleshooting.md +8 -4
- package/dist/global-skills/eas-update/SKILL.md +146 -0
- package/dist/global-skills/eas-update/agents/openai.yaml +4 -0
- package/dist/global-skills/expo-animation/RECIPES.md +2 -2
- package/dist/global-skills/expo-animation/SKILL.md +9 -2
- package/dist/global-skills/expo-brownfield/SKILL.md +18 -11
- package/dist/global-skills/expo-brownfield/agents/openai.yaml +2 -2
- package/dist/global-skills/expo-brownfield/references/brownfield-integrated.md +94 -69
- package/dist/global-skills/expo-brownfield/references/brownfield-isolated.md +40 -42
- package/dist/global-skills/expo-brownfield/references/comparison.md +5 -5
- package/dist/global-skills/expo-brownfield/references/feature-integration.md +163 -0
- package/dist/global-skills/expo-brownfield/references/troubleshooting.md +17 -17
- package/dist/global-skills/expo-brownfield/references/version-compatibility.md +40 -0
- package/dist/global-skills/expo-data-fetching/SKILL.md +27 -6
- package/dist/global-skills/expo-design-system/SKILL.md +27 -7
- package/dist/global-skills/expo-design-system/references/audit.md +7 -2
- package/dist/global-skills/expo-design-system/references/native-slop.md +74 -0
- package/dist/global-skills/expo-examples/SKILL.md +0 -1
- package/dist/global-skills/expo-examples/references/catalog.md +1 -1
- package/dist/global-skills/expo-migrate-module/SKILL.md +21 -10
- package/dist/global-skills/expo-migrate-module/references/compatibility.md +80 -23
- package/dist/global-skills/expo-migrate-module/references/migration-map.md +162 -11
- package/dist/global-skills/expo-native-ui/SKILL.md +25 -16
- package/dist/global-skills/expo-native-ui/agents/openai.yaml +2 -2
- package/dist/global-skills/expo-native-ui/references/controls.md +5 -46
- package/dist/global-skills/expo-native-ui/references/icons.md +21 -2
- package/dist/global-skills/expo-native-ui/references/media.md +15 -20
- package/dist/global-skills/expo-native-ui/references/visual-effects.md +12 -11
- package/dist/global-skills/expo-overview/SKILL.md +17 -12
- package/dist/global-skills/expo-router/SKILL.md +5 -3
- package/dist/global-skills/expo-router/references/tabs.md +5 -5
- package/dist/global-skills/expo-upgrade/SKILL.md +3 -1
- package/dist/global-skills/expo-web-to-native/references/false-friends.md +2 -2
- package/dist/global-skills/expo-web-to-native/references/native-patterns.md +1 -1
- package/dist/global-skills/firebase-ai-logic-basics/SKILL.md +13 -16
- package/dist/global-skills/firebase-ai-logic-basics/references/ios_setup.md +4 -5
- package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_android.md +4 -4
- package/dist/global-skills/firebase-ai-logic-basics/references/usage_patterns_web.md +3 -3
- package/dist/global-skills/firebase-auth-basics/SKILL.md +11 -6
- package/dist/global-skills/firebase-auth-basics/references/client_sdk_android.md +4 -5
- package/dist/global-skills/firebase-auth-basics/references/client_sdk_web.md +3 -3
- package/dist/global-skills/firebase-auth-basics/references/flutter_setup.md +24 -25
- package/dist/global-skills/firebase-auth-basics/references/security_rules.md +4 -2
- package/dist/global-skills/firebase-crashlytics/references/android_setup.md +7 -4
- package/dist/global-skills/firebase-crashlytics/references/ios_setup.md +2 -3
- package/dist/global-skills/firebase-data-connect/SKILL.md +2 -1
- package/dist/global-skills/firebase-data-connect/examples.md +4 -4
- package/dist/global-skills/firebase-data-connect/reference/config.md +5 -4
- package/dist/global-skills/firebase-data-connect/reference/realtime.md +1 -2
- package/dist/global-skills/firebase-data-connect/reference/sdk_flutter.md +2 -2
- package/dist/global-skills/firebase-data-connect/reference/sdk_ios.md +2 -2
- package/dist/global-skills/firebase-data-connect/reference/sdk_web.md +17 -6
- package/dist/global-skills/firebase-data-connect/reference/security.md +5 -5
- package/dist/global-skills/firebase-data-connect/templates.md +2 -1
- package/dist/global-skills/firebase-firestore/SKILL.md +20 -8
- package/dist/global-skills/firebase-firestore/references/enterprise/android_sdk_usage.md +5 -4
- package/dist/global-skills/firebase-firestore/references/enterprise/data_model.md +12 -3
- package/dist/global-skills/firebase-firestore/references/enterprise/indexes.md +16 -18
- package/dist/global-skills/firebase-firestore/references/enterprise/provisioning.md +1 -1
- package/dist/global-skills/firebase-firestore/references/enterprise/python_sdk_usage.md +5 -1
- package/dist/global-skills/firebase-firestore/references/enterprise/web_sdk_usage.md +7 -7
- package/dist/global-skills/firebase-firestore/references/standard/android_sdk_usage.md +5 -5
- package/dist/global-skills/firebase-firestore/references/standard/flutter_setup.md +4 -4
- package/dist/global-skills/firebase-firestore/references/standard/indexes.md +16 -18
- package/dist/global-skills/firebase-firestore/references/standard/provisioning.md +1 -1
- package/dist/global-skills/firebase-remote-config-basics/SKILL.md +0 -5
- package/dist/global-skills/firebase-remote-config-basics/references/android_setup.md +36 -8
- package/dist/global-skills/firebase-remote-config-basics/references/ios_setup.md +1 -7
- package/dist/global-skills/firebase-security-rules-auditor/SKILL.md +17 -6
- package/dist/global-skills/{firebase-firestore/references/standard/security_rules.md → firestore-rules-creation/SKILL.md} +24 -13
- package/dist/global-skills/grow-my-customers/SKILL.md +23 -0
- package/dist/global-skills/instrument-feature-flags/SKILL.md +25 -25
- package/dist/global-skills/instrument-feature-flags/references/adding-feature-flag-code.md +141 -285
- package/dist/global-skills/instrument-feature-flags/references/android.md +6 -15
- package/dist/global-skills/instrument-feature-flags/references/api.md +4 -11
- package/dist/global-skills/instrument-feature-flags/references/best-practices.md +1 -13
- package/dist/global-skills/instrument-feature-flags/references/django.md +14 -27
- package/dist/global-skills/instrument-feature-flags/references/dotnet.md +20 -79
- package/dist/global-skills/instrument-feature-flags/references/elixir.md +1 -9
- package/dist/global-skills/instrument-feature-flags/references/flask.md +13 -13
- package/dist/global-skills/instrument-feature-flags/references/flutter.md +3 -24
- package/dist/global-skills/instrument-feature-flags/references/go.md +3 -15
- package/dist/global-skills/instrument-feature-flags/references/ios.md +4 -17
- package/dist/global-skills/instrument-feature-flags/references/java.md +5 -13
- package/dist/global-skills/instrument-feature-flags/references/laravel.md +13 -17
- package/dist/global-skills/instrument-feature-flags/references/next-js.md +25 -32
- package/dist/global-skills/instrument-feature-flags/references/nodejs.md +8 -15
- package/dist/global-skills/instrument-feature-flags/references/php.md +1 -15
- package/dist/global-skills/instrument-feature-flags/references/python.md +2 -15
- package/dist/global-skills/instrument-feature-flags/references/react-native.md +13 -15
- package/dist/global-skills/instrument-feature-flags/references/react.md +17 -21
- package/dist/global-skills/instrument-feature-flags/references/ruby-on-rails.md +37 -83
- package/dist/global-skills/instrument-feature-flags/references/ruby.md +2 -15
- package/dist/global-skills/instrument-feature-flags/references/rust.md +13 -25
- package/dist/global-skills/instrument-feature-flags/references/usage.md +14 -63
- package/dist/global-skills/instrument-feature-flags/references/web.md +9 -14
- package/dist/global-skills/instrument-product-analytics/SKILL.md +29 -29
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-hybrid.md +3 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-ssr.md +3 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-static.md +3 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-astro-view-transitions.md +3 -1
- package/dist/global-skills/instrument-product-analytics/references/EXAMPLE-ruby-on-rails.md +3 -1
- package/dist/global-skills/instrument-product-analytics/references/android.md +72 -107
- package/dist/global-skills/instrument-product-analytics/references/angular.md +26 -28
- package/dist/global-skills/instrument-product-analytics/references/astro.md +13 -24
- package/dist/global-skills/instrument-product-analytics/references/configuration.md +45 -63
- package/dist/global-skills/instrument-product-analytics/references/django.md +14 -27
- package/dist/global-skills/instrument-product-analytics/references/dotnet.md +20 -79
- package/dist/global-skills/instrument-product-analytics/references/elixir.md +47 -49
- package/dist/global-skills/instrument-product-analytics/references/flask.md +13 -13
- package/dist/global-skills/instrument-product-analytics/references/flutter.md +60 -90
- package/dist/global-skills/instrument-product-analytics/references/go.md +17 -56
- package/dist/global-skills/instrument-product-analytics/references/identify-users.md +15 -15
- package/dist/global-skills/instrument-product-analytics/references/ios.md +11 -15
- package/dist/global-skills/instrument-product-analytics/references/laravel.md +13 -17
- package/dist/global-skills/instrument-product-analytics/references/next-js.md +25 -32
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js-3-6.md +13 -27
- package/dist/global-skills/instrument-product-analytics/references/nuxt-js.md +14 -28
- package/dist/global-skills/instrument-product-analytics/references/php.md +33 -84
- package/dist/global-skills/instrument-product-analytics/references/posthog-python.md +229 -9
- package/dist/global-skills/instrument-product-analytics/references/python.md +415 -106
- package/dist/global-skills/instrument-product-analytics/references/react-native.md +161 -155
- package/dist/global-skills/instrument-product-analytics/references/react-router-v6.md +12 -33
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-data-mode.md +15 -33
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-declarative-mode.md +12 -33
- package/dist/global-skills/instrument-product-analytics/references/react-router-v7-framework-mode.md +26 -41
- package/dist/global-skills/instrument-product-analytics/references/ruby-on-rails.md +37 -83
- package/dist/global-skills/instrument-product-analytics/references/ruby.md +48 -108
- package/dist/global-skills/instrument-product-analytics/references/svelte.md +18 -24
- package/dist/global-skills/instrument-product-analytics/references/tanstack-start.md +17 -19
- package/dist/global-skills/instrument-product-analytics/references/usage.md +14 -63
- package/dist/global-skills/instrument-product-analytics/references/vue-js.md +29 -28
- package/dist/global-skills/manifest.json +8 -2
- package/dist/global-skills/mongodb-search-and-ai/SKILL.md +28 -37
- package/dist/global-skills/mongodb-search-and-ai/references/automated-embedding.md +438 -0
- package/dist/global-skills/mongodb-search-and-ai/references/hybrid-search.md +60 -4
- package/dist/global-skills/mongodb-search-and-ai/references/vector-search.md +46 -108
- package/dist/global-skills/neon/SKILL.md +207 -213
- package/dist/global-skills/neon/references/auth.md +12 -0
- package/dist/global-skills/neon/references/claimable-neon.md +10 -14
- package/dist/global-skills/neon/references/function-triggers.md +53 -0
- package/dist/global-skills/neon/references/logs-loki.md +61 -0
- package/dist/global-skills/neon/references/parse-env.md +32 -0
- package/dist/global-skills/neon/references/sdk.md +7 -0
- package/dist/global-skills/neon-ai-gateway/SKILL.md +14 -16
- package/dist/global-skills/neon-auth/SKILL.md +155 -0
- package/dist/global-skills/neon-auth/references/managed-auth.md +173 -0
- package/dist/global-skills/neon-auth/references/self-managed.md +25 -0
- package/dist/global-skills/neon-functions/SKILL.md +159 -84
- package/dist/global-skills/neon-functions/references/ai-sdk.md +4 -6
- package/dist/global-skills/neon-functions/references/function-triggers.md +249 -0
- package/dist/global-skills/neon-functions/references/mastra-studio.md +3 -3
- package/dist/global-skills/neon-functions/references/mcp.md +1 -1
- package/dist/global-skills/neon-functions/references/production-hardening.md +340 -0
- package/dist/global-skills/neon-functions/references/sse.md +8 -5
- package/dist/global-skills/neon-object-storage/SKILL.md +10 -11
- package/dist/global-skills/neon-postgres/SKILL.md +120 -17
- package/dist/global-skills/neon-postgres/references/full-text-search.md +99 -0
- package/dist/global-skills/neon-postgres/references/hybrid-search.md +90 -0
- package/dist/global-skills/neon-postgres/references/lakebase-search-drizzle.md +172 -0
- package/dist/global-skills/neon-postgres/references/vector-search.md +137 -0
- package/dist/global-skills/neon-postgres-branches/SKILL.md +3 -3
- package/dist/global-skills/neon-postgres-egress-optimizer/SKILL.md +1 -1
- package/dist/global-skills/onboarding/SKILL.md +8 -6
- package/dist/global-skills/resend/SKILL.md +4 -2
- package/dist/global-skills/resend/references/broadcasts.md +6 -1
- package/dist/global-skills/resend/references/receiving.md +29 -10
- package/dist/global-skills/resend/references/sending/email-management.md +14 -4
- package/dist/global-skills/resend/references/topics.md +9 -6
- package/dist/global-skills/resend/references/usage.md +117 -0
- package/dist/global-skills/resend/references/webhooks.md +59 -2
- package/dist/global-skills/stripe-best-practices/SKILL.md +35 -29
- package/dist/global-skills/stripe-best-practices/references/billing.md +9 -2
- package/dist/global-skills/stripe-best-practices/references/payments.md +4 -2
- package/dist/global-skills/stripe-best-practices/references/security.md +3 -1
- package/dist/global-skills/stripe-best-practices/references/tax.md +39 -20
- package/dist/global-skills/supabase/SKILL.md +6 -0
- package/dist/global-skills/use-railway/SKILL.md +42 -22
- package/dist/global-skills/use-railway/references/analyze-db.md +7 -6
- package/dist/global-skills/use-railway/references/cloud-agents.md +70 -0
- package/dist/global-skills/use-railway/references/configure.md +17 -2
- package/dist/global-skills/use-railway/references/databases.md +107 -0
- package/dist/global-skills/use-railway/references/deploy.md +5 -5
- package/dist/global-skills/use-railway/references/feature-flags.md +25 -13
- package/dist/global-skills/use-railway/references/iac.md +66 -77
- package/dist/global-skills/use-railway/references/operate.md +26 -3
- package/dist/global-skills/use-railway/references/request.md +31 -23
- package/dist/global-skills/use-railway/references/setup.md +16 -5
- package/dist/global-skills/use-railway/references/tracing.md +261 -0
- package/dist/global-skills/use-railway/references/usage.md +52 -0
- package/dist/global-skills/validate-my-idea/SKILL.md +54 -0
- package/dist/global-skills/{feedback → vybekiit-feedback}/SKILL.md +16 -12
- package/dist/global-skills/watch-my-app/SKILL.md +53 -0
- package/dist/global-skills/workers-best-practices/SKILL.md +36 -103
- package/dist/global-skills/workers-best-practices/references/configuration.md +139 -0
- package/dist/global-skills/workers-best-practices/references/platform-apis.md +51 -0
- package/dist/global-skills/workers-best-practices/references/{rules.md → runtime-patterns.md} +13 -137
- package/dist/global-skills/wrangler/SKILL.md +48 -901
- package/dist/global-skills/xcode-project-setup/scripts/xcode_spm_setup/Sources/main.swift +19 -15
- package/package.json +9 -8
- package/dist/global-skills/expo-native-ui/references/animations.md +0 -220
- package/dist/global-skills/firebase-firestore/references/enterprise/security_rules.md +0 -577
- package/dist/global-skills/workers-best-practices/references/review.md +0 -174
|
@@ -22,12 +22,12 @@ metadata:
|
|
|
22
22
|
If the `neon` skill is not installed, fetch it from https://neon.com/docs/ai/skills/neon/SKILL.md or install it with:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
|
|
25
|
+
neon skills -s neon -y
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
# Neon Object Storage
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Currently available in `aws-us-east-2`, `aws-us-east-1`, `aws-eu-central-1`, and `aws-ap-southeast-1`.
|
|
31
31
|
|
|
32
32
|
Neon Object Storage is S3-compatible object storage that branches with your projects: every branch gets its own isolated storage state, so files and database rows stay in sync across dev, preview, staging, and production.
|
|
33
33
|
|
|
@@ -53,7 +53,7 @@ If the files in question ship with the app itself — HTML, JS bundles, CSS, the
|
|
|
53
53
|
|
|
54
54
|
## Availability
|
|
55
55
|
|
|
56
|
-
Check this precondition before setting anything up: Neon Object Storage is
|
|
56
|
+
Check this precondition before setting anything up: Neon Object Storage is currently available in `aws-us-east-2`, `aws-us-east-1`, `aws-eu-central-1`, and `aws-ap-southeast-1`. Confirm the user's Neon project is in one of these regions before proceeding. Region coverage: https://neon.com/docs/get-started/backend-overview.md
|
|
57
57
|
|
|
58
58
|
## Architecture: Where Object Storage Fits
|
|
59
59
|
|
|
@@ -64,18 +64,16 @@ Neon (Object Storage included) is **backend primitives, not full-stack app hosti
|
|
|
64
64
|
|
|
65
65
|
## Setup
|
|
66
66
|
|
|
67
|
-
Object storage is part of the `neon.ts` infrastructure-as-code config (see the `neon` skill for the branch-first workflow, `link`/`checkout`, and `neon.ts` basics). Declare buckets under `
|
|
67
|
+
Object storage is part of the `neon.ts` infrastructure-as-code config (see the `neon` skill for the branch-first workflow, `link`/`checkout`, and `neon.ts` basics). Declare buckets under `buckets`, keyed by bucket name:
|
|
68
68
|
|
|
69
69
|
```typescript
|
|
70
70
|
// neon.ts
|
|
71
71
|
import { defineConfig } from "@neon/config/v1";
|
|
72
72
|
|
|
73
73
|
export default defineConfig({
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"public-assets": { access: "public_read" },
|
|
78
|
-
},
|
|
74
|
+
buckets: {
|
|
75
|
+
images: {}, // private by default
|
|
76
|
+
"public-assets": { access: "public_read" },
|
|
79
77
|
},
|
|
80
78
|
});
|
|
81
79
|
```
|
|
@@ -88,7 +86,7 @@ neon deploy # alias for `neon config apply`
|
|
|
88
86
|
|
|
89
87
|
## Neon Infrastructure as Code (`neon.ts`)
|
|
90
88
|
|
|
91
|
-
The `
|
|
89
|
+
The `buckets` block above is part of `neon.ts`, Neon's infrastructure-as-code file — one TypeScript file declares your buckets alongside every other service the branch should have (see the `neon` skill for the full reference). Reconcile the declaration against a branch the Terraform way:
|
|
92
90
|
|
|
93
91
|
```bash
|
|
94
92
|
neon config status # print the branch's live config (which buckets exist)
|
|
@@ -100,7 +98,7 @@ Buckets are **branch-scoped**: when a `neon.ts` is present, `neon checkout` appl
|
|
|
100
98
|
|
|
101
99
|
## Environment Variables
|
|
102
100
|
|
|
103
|
-
When `
|
|
101
|
+
When `buckets` is declared, Neon injects **AWS-standard** S3 env vars so the AWS SDKs work from the environment with zero extra config. Inside a deployed Neon Function these are injected automatically; locally, pull them onto disk (or inject them at runtime) via the CLI:
|
|
104
102
|
|
|
105
103
|
```bash
|
|
106
104
|
neon env pull # writes the branch's vars into .env (or .env.local)
|
|
@@ -218,6 +216,7 @@ The Neon documentation is the source of truth and Object Storage is evolving rap
|
|
|
218
216
|
|
|
219
217
|
## Further Reading
|
|
220
218
|
|
|
219
|
+
- https://neon.com/docs/get-started/backend-overview.md
|
|
221
220
|
- https://neon.com/docs/storage/overview.md
|
|
222
221
|
- https://neon.com/docs/storage/get-started.md
|
|
223
222
|
- https://neon.com/docs/storage/buckets.md
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: neon-postgres
|
|
3
3
|
description: >-
|
|
4
|
-
Guides and best practices for working with Lakebase Postgres
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"Neon connection pooling", or "schema migrations".
|
|
4
|
+
Guides and best practices for working with Lakebase Postgres on Neon:
|
|
5
|
+
connections, pooled vs direct, schema migrations, branching, autoscaling,
|
|
6
|
+
scale-to-zero, instant restore, read replicas, IP allow lists, logical
|
|
7
|
+
replication, and Lakebase Search. Use when the work is an existing
|
|
8
|
+
DATABASE_URL, SQL, schema, inspect, or search. New backends, Auth, files,
|
|
9
|
+
Functions, and LLM calls go to the parent `neon` skill. Also use for
|
|
10
|
+
"@neondatabase/serverless", "@neondatabase/neon-js", "neon inspect db",
|
|
11
|
+
"semantic search", "vector search", "full-text search", "BM25", or
|
|
12
|
+
"hybrid search".
|
|
14
13
|
metadata:
|
|
15
14
|
parent: neon
|
|
16
15
|
source: https://github.com/neondatabase/agent-skills/tree/main/skills/neon-postgres
|
|
@@ -21,7 +20,7 @@ metadata:
|
|
|
21
20
|
If the `neon` skill is not installed, fetch it from https://neon.com/docs/ai/skills/neon/SKILL.md or install it with:
|
|
22
21
|
|
|
23
22
|
```bash
|
|
24
|
-
|
|
23
|
+
neon skills -s neon -y
|
|
25
24
|
```
|
|
26
25
|
|
|
27
26
|
# Lakebase Postgres
|
|
@@ -30,15 +29,21 @@ Lakebase Postgres is the database at the core of Neon. It runs on the lakebase a
|
|
|
30
29
|
|
|
31
30
|
It is the same database whether you reach it through Neon or through Databricks; this skill covers the Neon access path.
|
|
32
31
|
|
|
32
|
+
Login, users, sessions, and `@neondatabase/auth` belong in `neon-auth`.
|
|
33
|
+
|
|
33
34
|
## Setup Flow
|
|
34
35
|
|
|
35
36
|
### 1. Select the organization and project
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
If a `DATABASE_URL` is already supplied (prompt, environment, or repo) or a `.neon` file points at a project, use it. Do not list organizations or create a second project for schema work.
|
|
39
|
+
|
|
40
|
+
Otherwise use the CLI (default) or MCP server to list organizations and projects. Let the user select an existing project or create a new one.
|
|
38
41
|
|
|
39
42
|
### 2. Get the connection string
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
If a `DATABASE_URL` is already supplied, use it. Do not fetch another through the CLI or MCP.
|
|
45
|
+
|
|
46
|
+
Otherwise use the CLI (default), `neon env pull`, or the MCP server to get the connection string. Store it in `.env` as `DATABASE_URL`. Read the file first before modifying it, to avoid overwriting existing values.
|
|
42
47
|
|
|
43
48
|
#### When to use pooled vs direct connections
|
|
44
49
|
|
|
@@ -54,11 +59,10 @@ Use the CLI (default), `neon env pull`, or the MCP server to get the connection
|
|
|
54
59
|
|
|
55
60
|
### 3. Pick the connection method and driver
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
Preserve the existing ORM and driver. For new TypeScript schema work with no established choice, Drizzle is a suggestion: https://neon.com/docs/guides/drizzle.md. Refer to the connection methods guide to pick the correct driver based on how the runtime treats your code: https://neon.com/docs/connect/choose-connection.md.
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
Driver notes:
|
|
60
65
|
|
|
61
|
-
- Drizzle as ORM (see https://neon.com/docs/guides/drizzle.md)
|
|
62
66
|
- On Vercel, use `node-postgres` (`npm install pg`) with Vercel Fluid compute and `import { attachDatabasePool } from "@vercel/functions";`
|
|
63
67
|
- On Cloudflare, use `node-postgres` with Cloudflare Hyperdrive
|
|
64
68
|
- On Neon Functions, use `node-postgres`, as the functions are long-running and reuse the pool across requests.
|
|
@@ -85,7 +89,7 @@ Link: https://neon.com/docs/introduction/branching.md
|
|
|
85
89
|
For detailed branch creation workflows (normal vs schema-only branches, reset-from-parent, CLI/MCP selection), use the `neon-postgres-branches` skill. If it isn't installed, fetch it from https://neon.com/docs/ai/skills/neon-postgres-branches/SKILL.md or install it with:
|
|
86
90
|
|
|
87
91
|
```bash
|
|
88
|
-
|
|
92
|
+
neon skills -s neon-postgres-branches -y
|
|
89
93
|
```
|
|
90
94
|
|
|
91
95
|
## Migrations
|
|
@@ -94,6 +98,90 @@ Test a migration on a branch of production, against production-like data, before
|
|
|
94
98
|
|
|
95
99
|
Use a **direct (non-pooled)** connection string when you run the migration, not a pooled one. `neon connection-string` returns the direct string by default; make sure the hostname does not include the `-pooler` suffix.
|
|
96
100
|
|
|
101
|
+
## Troubleshooting and Neon-Specific Performance
|
|
102
|
+
|
|
103
|
+
Use Neon's predefined, read-only diagnostics before writing catalog queries by hand. The Neon CLI `neon inspect db` subcommands and the Neon MCP server's `inspect_database` tool run the same checks.
|
|
104
|
+
|
|
105
|
+
This section covers Neon-specific diagnostic tools, compute cache behavior, and platform signals. When the evidence points to generic Postgres work such as rewriting a query, choosing an index, changing a schema, or interpreting plan nodes, load the [`postgres-best-practices`](https://github.com/neondatabase/postgres-skills/tree/main/skills/postgres-best-practices) skill and carry the diagnostic evidence into that workflow.
|
|
106
|
+
|
|
107
|
+
Docs:
|
|
108
|
+
|
|
109
|
+
- CLI: https://neon.com/docs/cli/inspect.md
|
|
110
|
+
- Query performance: https://neon.com/docs/postgresql/query-performance.md
|
|
111
|
+
- `pg_stat_statements`: https://neon.com/docs/extensions/pg_stat_statements.md
|
|
112
|
+
- Neon Local File Cache: https://neon.com/docs/extensions/neon.md
|
|
113
|
+
|
|
114
|
+
### Choose CLI or MCP
|
|
115
|
+
|
|
116
|
+
Prefer the Neon CLI when terminal access and authentication are available:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
neon inspect db <check>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The CLI resolves the project and branch from the current Neon context. Use `--project-id`, `--branch`, and `--database-name` to override it. Omit `--database-name` to inspect every database on the branch. Use `--db-url` only when inspecting a Postgres database directly instead of resolving it through the Neon API.
|
|
123
|
+
|
|
124
|
+
When using Neon MCP, call `inspect_database` with `projectId` and one `check`. Pass `branchId`, `databaseName`, or `computeId` only when needed. Omit `databaseName` to inspect all databases on the branch. Increase `limit` only when the result says it was truncated.
|
|
125
|
+
|
|
126
|
+
### Pick the Diagnostic
|
|
127
|
+
|
|
128
|
+
| Symptom or question | Checks |
|
|
129
|
+
| ---------------------------------------------- | ------------------------------------ |
|
|
130
|
+
| Which relations consume storage? | `table-sizes`, `index-sizes` |
|
|
131
|
+
| Is an index unused or a table scanned heavily? | `unused-indexes`, `seq-scans` |
|
|
132
|
+
| What has run for 5+ minutes or holds locks? | `long-running-queries`, `locks` |
|
|
133
|
+
| Which queries consume the most total time? | `outliers` |
|
|
134
|
+
| Which queries run most often? | `calls` |
|
|
135
|
+
| Does the active data fit in compute cache? | `lfc-hit-rate`, `working-set` |
|
|
136
|
+
| Is autovacuum behind or is space wasted? | `vacuum-stats`, `bloat` |
|
|
137
|
+
| Is logical replication healthy? | `replication-slots`, `subscriptions` |
|
|
138
|
+
|
|
139
|
+
Do not confuse these checks:
|
|
140
|
+
|
|
141
|
+
- `long-running-queries` reports statements running **right now** for more than five minutes.
|
|
142
|
+
- `outliers` ranks the top queries by cumulative execution time since statistics were reset. It does not rank by mean latency.
|
|
143
|
+
- `calls` ranks by execution count over the same statistics history.
|
|
144
|
+
|
|
145
|
+
`outliers` and `calls` require `pg_stat_statements`. `lfc-hit-rate` and `working-set` require the `neon` extension. If a check reports a missing extension, ask before running the suggested `CREATE EXTENSION` statement because installing an extension modifies the database.
|
|
146
|
+
|
|
147
|
+
### Interpret Results Safely
|
|
148
|
+
|
|
149
|
+
- Treat `unused-indexes` as a candidate list, not permission to drop indexes. Confirm the observation window, constraints, and workload before removal.
|
|
150
|
+
- A sequential scan can be correct for a small table or a query reading much of a table. Check table size, selectivity, and the query plan before adding an index.
|
|
151
|
+
- `bloat` is a statistical estimate. Confirm the impact and plan locks or maintenance before `VACUUM FULL`, `REINDEX`, or similar remediation.
|
|
152
|
+
- Cache and Postgres statistics reset when compute restarts, including scale-to-zero suspension. Run a representative workload before interpreting fresh `lfc-hit-rate`, `working-set`, `vacuum-stats`, or `pg_stat_statements` results.
|
|
153
|
+
- Compute-wide checks (`lfc-hit-rate`, `working-set`, and `replication-slots`) run once even when inspecting every database.
|
|
154
|
+
- One failing database can fail an all-databases inspection; retry the relevant check with an explicit `databaseName` to isolate it.
|
|
155
|
+
|
|
156
|
+
### Inspect Neon Cache Behavior Per Query
|
|
157
|
+
|
|
158
|
+
Standard `EXPLAIN (ANALYZE, BUFFERS)` reports Postgres shared-buffer activity, but it does not show Neon's Local File Cache (LFC) or page prefetching. For a safe read-only query, add Neon's `FILECACHE` and `PREFETCH` options:
|
|
159
|
+
|
|
160
|
+
```sql
|
|
161
|
+
EXPLAIN (ANALYZE, BUFFERS, PREFETCH, FILECACHE)
|
|
162
|
+
SELECT ...;
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
- `File cache: hits` counts pages found in the compute's LFC.
|
|
166
|
+
- `File cache: misses` counts pages not found in the LFC and fetched from database storage.
|
|
167
|
+
- `Prefetch: hits`, `misses`, `expired`, and `duplicates` show how effectively Neon fetched pages before the executor requested them.
|
|
168
|
+
|
|
169
|
+
`FILECACHE` and `PREFETCH` provide metrics for this query and do not require the `neon` extension. By contrast, `neon inspect db lfc-hit-rate` and `working-set` provide compute-wide statistics and do require the extension.
|
|
170
|
+
|
|
171
|
+
The MCP `explain_sql_statement` tool can produce a standard plan but does not expose `FILECACHE` or `PREFETCH` options. To collect those Neon-specific metrics through MCP, use `run_sql` with the explicit, read-only `EXPLAIN` statement above.
|
|
172
|
+
|
|
173
|
+
Because `ANALYZE` executes the statement, use it only when execution is safe; do not run it autonomously for mutating SQL. Compare cold- and warm-cache runs carefully because the first execution can populate the cache and materially change later results.
|
|
174
|
+
|
|
175
|
+
### Performance Workflow
|
|
176
|
+
|
|
177
|
+
1. Reproduce the symptom and note its time window.
|
|
178
|
+
2. Run the smallest relevant `inspect` checks from the table above.
|
|
179
|
+
3. Identify a specific query before changing schema or compute. Use MCP `explain_sql_statement` for a standard plan, or the Neon-specific `EXPLAIN` above when LFC or prefetch behavior matters.
|
|
180
|
+
4. If the bottleneck is query shape, indexing, schema, locking, or vacuum behavior, load `postgres-best-practices` and carry forward the inspection results and query plan. Keep Neon compute, cache, connection, and platform decisions in this skill.
|
|
181
|
+
5. Re-run the same check and workload to verify the change.
|
|
182
|
+
|
|
183
|
+
Use MCP `list_slow_queries` instead of `inspect_database` when the user specifically needs queries ranked by average execution time with a custom threshold and limit. Outside the explicit `EXPLAIN` case above, use `run_sql` only for read-only diagnostic SQL when the predefined checks do not answer the question.
|
|
184
|
+
|
|
97
185
|
## Autoscaling
|
|
98
186
|
|
|
99
187
|
Use this when the user needs compute to scale automatically with workload and wants guidance on CU sizing and runtime behavior.
|
|
@@ -165,6 +253,21 @@ Key points:
|
|
|
165
253
|
|
|
166
254
|
Link: https://neon.com/docs/guides/logical-replication-guide.md
|
|
167
255
|
|
|
256
|
+
## Lakebase Search
|
|
257
|
+
|
|
258
|
+
Use Lakebase Search for semantic, full-text, and hybrid search:
|
|
259
|
+
|
|
260
|
+
- For semantic search, read [Vector search](references/vector-search.md).
|
|
261
|
+
- For full-text search with BM25 ranking, read [Full-text search](references/full-text-search.md).
|
|
262
|
+
- For combining semantic and lexical results, read [Hybrid search](references/hybrid-search.md).
|
|
263
|
+
- For managing any of the above through Drizzle ORM, read [Managing Lakebase Search with Drizzle](references/lakebase-search-drizzle.md).
|
|
264
|
+
|
|
265
|
+
Links:
|
|
266
|
+
|
|
267
|
+
- [Get started with Lakebase Search](https://neon.com/docs/ai/lakebase-search-get-started)
|
|
268
|
+
- [`lakebase_vector` reference](https://neon.com/docs/extensions/lakebase-vector)
|
|
269
|
+
- [`lakebase_text` reference](https://neon.com/docs/extensions/lakebase-text)
|
|
270
|
+
|
|
168
271
|
## Gotchas
|
|
169
272
|
|
|
170
273
|
### Pooled vs direct connections: use the direct URL for migrations, dumps, and replication
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Full-Text Search with BM25 Ranking
|
|
2
|
+
|
|
3
|
+
Use `lakebase_text` for BM25 relevance ranking with PostgreSQL's standard `tsvector` type. The `lakebase_bm25` index adds corpus-aware ranking and top-K pushdown.
|
|
4
|
+
|
|
5
|
+
Lakebase Search requires Postgres 16 or later. Enable the extension before creating the index:
|
|
6
|
+
|
|
7
|
+
```sql
|
|
8
|
+
CREATE EXTENSION IF NOT EXISTS lakebase_text;
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`lakebase_text` has no extension dependency. It relies on a preloaded library that Neon enables by default; if the project customized its preloaded-library list, confirm the library remains enabled.
|
|
12
|
+
|
|
13
|
+
## Prepare and Index Text
|
|
14
|
+
|
|
15
|
+
Prefer a stored generated `tsvector` when search text comes from stable table columns:
|
|
16
|
+
|
|
17
|
+
```sql
|
|
18
|
+
CREATE TABLE documents (
|
|
19
|
+
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
20
|
+
title text NOT NULL,
|
|
21
|
+
body text NOT NULL,
|
|
22
|
+
body_tsv tsvector GENERATED ALWAYS AS
|
|
23
|
+
(to_tsvector('english', body)) STORED
|
|
24
|
+
);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Create the index after the initial corpus has been inserted so build-time corpus statistics are meaningful. BM25 scoring is tuned by two storage parameters set at index-build time:
|
|
28
|
+
|
|
29
|
+
- `k1` controls term-frequency saturation (default `1.2`, range `1.2`–`2.0`): higher values let repeated terms keep adding relevance.
|
|
30
|
+
|
|
31
|
+
- `b` controls document-length normalization (default `0.75`, range `0.0`–`1.0`): higher values penalize longer documents more.
|
|
32
|
+
|
|
33
|
+
Both can only be set in the `WITH` clause, and updating them rebuilds the index:
|
|
34
|
+
|
|
35
|
+
```sql
|
|
36
|
+
CREATE INDEX documents_body_bm25 ON documents
|
|
37
|
+
USING lakebase_bm25 (body_tsv)
|
|
38
|
+
WITH (k1 = 1.2, b = 0.75);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
After a large bulk load, run `VACUUM` to refresh the statistics used by BM25 scoring.
|
|
42
|
+
|
|
43
|
+
## Query and Interpret Scores
|
|
44
|
+
|
|
45
|
+
`to_bm25query` binds the query `tsvector` to the BM25 index whose corpus statistics should be used. The `<@>` operator returns a negative BM25 score, so lower (more negative) values are more relevant and must sort ascending:
|
|
46
|
+
|
|
47
|
+
```sql
|
|
48
|
+
SELECT
|
|
49
|
+
id,
|
|
50
|
+
title,
|
|
51
|
+
body_tsv <@> to_bm25query(
|
|
52
|
+
to_tsvector('english', $1),
|
|
53
|
+
'documents_body_bm25'::regclass
|
|
54
|
+
) AS score
|
|
55
|
+
FROM documents
|
|
56
|
+
ORDER BY score
|
|
57
|
+
LIMIT $2;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Use the same text-search configuration for document and query vectors. Select a language-specific or custom configuration that matches the corpus.
|
|
61
|
+
|
|
62
|
+
## Set the Candidate Limit
|
|
63
|
+
|
|
64
|
+
`lakebase_bm25.default_limit` controls how many rows the index returns before PostgreSQL applies the SQL `LIMIT`. Its default is `1000`; setting it close to the requested top-K avoids unnecessary scoring.
|
|
65
|
+
|
|
66
|
+
## Use Prefilter Selectively
|
|
67
|
+
|
|
68
|
+
Enable prefilter when a `WHERE` condition is strict or unpredictable and cheap to evaluate. It lets the index prune rows before BM25 scoring. A loose or expensive filter can be slower with prefilter enabled.
|
|
69
|
+
|
|
70
|
+
```sql
|
|
71
|
+
BEGIN;
|
|
72
|
+
SET LOCAL lakebase_bm25.default_limit = 20;
|
|
73
|
+
SET LOCAL lakebase_bm25.prefilter = on;
|
|
74
|
+
|
|
75
|
+
SELECT
|
|
76
|
+
id,
|
|
77
|
+
title,
|
|
78
|
+
body_tsv <@> to_bm25query(
|
|
79
|
+
to_tsvector('english', $1),
|
|
80
|
+
'documents_body_bm25'::regclass
|
|
81
|
+
) AS score
|
|
82
|
+
FROM documents
|
|
83
|
+
WHERE id % 1000 = 0
|
|
84
|
+
ORDER BY score
|
|
85
|
+
LIMIT $2;
|
|
86
|
+
COMMIT;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Set Parameters at Build Time or Per Query
|
|
90
|
+
|
|
91
|
+
Several BM25 parameters can be set in two places. As an index storage parameter in the `CREATE INDEX` `WITH` clause, a value is fed into the index as its build-time default. As a session GUC via `SET` (or `SET LOCAL`), it applies per query and takes precedence over the stored default when both are present.
|
|
92
|
+
|
|
93
|
+
- `default_limit` and `prefilter` exist in both forms: set an index default that fits the common case, then override it per query with a GUC without rebuilding.
|
|
94
|
+
- `k1` (default `1.2`) and `b` (default `0.75`) are storage parameters only. There is no GUC for them.
|
|
95
|
+
- `enable_scan` (default `on`) is a GUC only.
|
|
96
|
+
|
|
97
|
+
The examples use `SET LOCAL` so each override is scoped to its own transaction, which is required behind a connection pool or stateless driver.
|
|
98
|
+
|
|
99
|
+
Source: [`lakebase_text` documentation](https://neon.com/docs/extensions/lakebase-text).
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Hybrid Search
|
|
2
|
+
|
|
3
|
+
Use hybrid search when either semantic similarity or exact vocabulary can identify a relevant document. Lakebase Search does not provide a built-in hybrid function: run vector and BM25 retrieval separately, then combine their results with a fusion strategy suited to the workload.
|
|
4
|
+
|
|
5
|
+
Lakebase Search requires Postgres 16 or later. Hybrid search uses both extensions:
|
|
6
|
+
|
|
7
|
+
```sql
|
|
8
|
+
CREATE EXTENSION IF NOT EXISTS lakebase_vector CASCADE;
|
|
9
|
+
CREATE EXTENSION IF NOT EXISTS lakebase_text;
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`lakebase_vector` installs `pgvector` through `CASCADE`; `lakebase_text` has no extension dependency. Both rely on preloaded libraries that Neon enables by default. If the project customized its preloaded-library list, confirm both libraries remain enabled.
|
|
13
|
+
|
|
14
|
+
Prepare a table with both vector and text-search columns:
|
|
15
|
+
|
|
16
|
+
```sql
|
|
17
|
+
CREATE TABLE documents (
|
|
18
|
+
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
19
|
+
title text NOT NULL,
|
|
20
|
+
body text NOT NULL,
|
|
21
|
+
embedding vector(1536),
|
|
22
|
+
body_tsv tsvector GENERATED ALWAYS AS
|
|
23
|
+
(to_tsvector('english', body)) STORED
|
|
24
|
+
);
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Replace `1536` with the embedding model's dimension. Use the same model and preprocessing for stored-document and query embeddings, and choose a PostgreSQL text-search configuration appropriate for the corpus.
|
|
28
|
+
|
|
29
|
+
Create and validate each retriever independently before combining them. Follow [Vector search](vector-search.md) and [Full-text search](full-text-search.md) for their indexes, query operators, and tuning.
|
|
30
|
+
|
|
31
|
+
Reciprocal Rank Fusion (RRF) is the approach in the Lakebase Search get-started guide and a useful default because it combines ranks instead of incomparable raw distances and scores. It is not the only option: weighted rank fusion, normalized score fusion, or a reranker may fit applications with different relevance signals.
|
|
32
|
+
|
|
33
|
+
## RRF Example
|
|
34
|
+
|
|
35
|
+
For rank `r` and constant `k`, each retriever contributes `1 / (k + r)`. The documented starting point uses 40 candidates per retriever and `k = 60`; tune both for the corpus and workload.
|
|
36
|
+
|
|
37
|
+
Bind the query embedding as `$1`, query text as `$2`, and final result count as `$3`:
|
|
38
|
+
|
|
39
|
+
```sql
|
|
40
|
+
WITH vector_ranked AS (
|
|
41
|
+
SELECT id, RANK() OVER (ORDER BY distance) AS rank
|
|
42
|
+
FROM (
|
|
43
|
+
SELECT id, embedding <=> $1::vector AS distance
|
|
44
|
+
FROM documents
|
|
45
|
+
ORDER BY distance
|
|
46
|
+
FETCH FIRST 40 ROWS WITH TIES
|
|
47
|
+
) AS vector_candidates
|
|
48
|
+
),
|
|
49
|
+
keyword_ranked AS (
|
|
50
|
+
SELECT id, RANK() OVER (ORDER BY score) AS rank
|
|
51
|
+
FROM (
|
|
52
|
+
SELECT
|
|
53
|
+
id,
|
|
54
|
+
body_tsv <@> to_bm25query(
|
|
55
|
+
to_tsvector('english', $2),
|
|
56
|
+
'documents_body_bm25'::regclass
|
|
57
|
+
) AS score
|
|
58
|
+
FROM documents
|
|
59
|
+
ORDER BY score
|
|
60
|
+
FETCH FIRST 40 ROWS WITH TIES
|
|
61
|
+
) AS keyword_candidates
|
|
62
|
+
)
|
|
63
|
+
SELECT
|
|
64
|
+
d.id,
|
|
65
|
+
d.title,
|
|
66
|
+
COALESCE(1.0 / (60 + v.rank), 0) +
|
|
67
|
+
COALESCE(1.0 / (60 + k.rank), 0) AS rrf_score
|
|
68
|
+
FROM documents AS d
|
|
69
|
+
LEFT JOIN vector_ranked AS v ON v.id = d.id
|
|
70
|
+
LEFT JOIN keyword_ranked AS k ON k.id = d.id
|
|
71
|
+
WHERE v.id IS NOT NULL OR k.id IS NOT NULL
|
|
72
|
+
ORDER BY rrf_score DESC, d.id
|
|
73
|
+
LIMIT $3;
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`RANK()` gives tied retrieval scores the same rank. Sort by `rrf_score` descending and use the stable ID as a final tie-breaker.
|
|
77
|
+
|
|
78
|
+
`FETCH FIRST ... ROWS WITH TIES` keeps every candidate tied at the cutoff, so `RANK()` receives the complete boundary tie group. The candidate set can therefore exceed 40 rows. `lakebase_bm25.default_limit` defaults to `1000`; increase it only when the BM25 candidate set needs to exceed that value.
|
|
79
|
+
|
|
80
|
+
## Adapt the Hybrid Search
|
|
81
|
+
|
|
82
|
+
- Retrieve more candidates from each source than the final result count; otherwise one retriever can dominate before fusion has enough overlap. Keep `lakebase_bm25.default_limit` above the BM25 candidate target and allow room for boundary ties.
|
|
83
|
+
- Keep each retriever's operator and index configuration correct independently before tuning RRF.
|
|
84
|
+
- Tune candidate counts and the RRF constant with judged or behavioral relevance data, plus latency measurements.
|
|
85
|
+
- Add weights only when product evidence shows one retriever should contribute more. Weight the reciprocal-rank contributions, not the raw vector distance and negative BM25 score.
|
|
86
|
+
- Apply the same access-control and tenant filters to both candidate CTEs. If BM25 filters are strict and cheap, evaluate whether `lakebase_bm25.prefilter` improves the filtered query.
|
|
87
|
+
|
|
88
|
+
Source: [Lakebase Search get-started guide][lakebase-search-guide].
|
|
89
|
+
|
|
90
|
+
[lakebase-search-guide]: https://neon.com/docs/ai/lakebase-search-get-started#combine-results-with-hybrid-search
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Managing Lakebase Search with Drizzle
|
|
2
|
+
|
|
3
|
+
When the user wants Lakebase Search managed through Drizzle, treat the SQL in [Vector Search](vector-search.md), [Full-Text Search](full-text-search.md), and [Hybrid Search](hybrid-search.md) as the source of truth and apply it as below. Use Drizzle for all schema and migration management unless the user says otherwise.
|
|
4
|
+
|
|
5
|
+
Requires `drizzle-orm` 0.36+ and `drizzle-kit` 0.27+: the schema below returns its indexes as an array from the `pgTable` extra-config callback. Those versions also include generated-column support for the `tsvector` column, the custom-method `.using(...).op(...)` index API for `lakebase_ann`, the `vector` column type, and the `cosineDistance` helper.
|
|
6
|
+
|
|
7
|
+
Contents:
|
|
8
|
+
|
|
9
|
+
- [Config](#config): `drizzle.config.ts` and the migration connection
|
|
10
|
+
- [Extensions](#extensions): custom migration required to create extensions (Drizzle can't)
|
|
11
|
+
- [Schema](#schema): columns, generated `tsvector`, and the ANN index
|
|
12
|
+
- [BM25 Index](#bm25-index): created after the corpus is seeded
|
|
13
|
+
- [Query](#query): vector, BM25, and hybrid reads
|
|
14
|
+
- [Tune Per Query](#tune-per-query): per-query GUCs
|
|
15
|
+
|
|
16
|
+
Rules:
|
|
17
|
+
|
|
18
|
+
- Express everything Drizzle can in `schema.ts`: the columns, the generated `tsvector`, and the `lakebase_ann` index. Only `CREATE EXTENSION` and the post-seed `lakebase_bm25` index need custom migrations.
|
|
19
|
+
- Use `drizzle-kit generate` then `migrate`. Never run `drizzle-kit push` (it reconciles the database to `schema.ts`, so it drops the post-seed `lakebase_bm25` index and any other object not declared there)
|
|
20
|
+
- Run every migration over the direct (unpooled) connection.
|
|
21
|
+
- The extension must exist before the `vector` column and the `lakebase_ann` index that depend on it.
|
|
22
|
+
|
|
23
|
+
## Config
|
|
24
|
+
|
|
25
|
+
`drizzle-kit generate` and `migrate` read `drizzle.config.ts`. Point `dbCredentials.url` at the **direct (unpooled)** connection string:
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// drizzle.config.ts
|
|
29
|
+
import { defineConfig } from "drizzle-kit";
|
|
30
|
+
|
|
31
|
+
export default defineConfig({
|
|
32
|
+
schema: "./src/schema.ts",
|
|
33
|
+
out: "./drizzle",
|
|
34
|
+
dialect: "postgresql",
|
|
35
|
+
// Direct (unpooled) URL. Neon exposes it as DATABASE_URL_UNPOOLED.
|
|
36
|
+
dbCredentials: { url: process.env.DATABASE_URL_UNPOOLED },
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Extensions
|
|
41
|
+
|
|
42
|
+
Drizzle cannot express `CREATE EXTENSION`, and the `vector` column and `lakebase_ann` index below depend on `lakebase_vector`, so generate a custom migration for the extensions **first** so it runs before the schema migration:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npx drizzle-kit generate --custom --name=lakebase_extensions
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```sql
|
|
49
|
+
-- drizzle/0000_lakebase_extensions.sql
|
|
50
|
+
CREATE EXTENSION IF NOT EXISTS lakebase_vector CASCADE;
|
|
51
|
+
CREATE EXTENSION IF NOT EXISTS lakebase_text;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Schema
|
|
55
|
+
|
|
56
|
+
The columns, the generated `tsvector`, and the `lakebase_ann` index all go in `schema.ts`. `tsvector` has no built-in Drizzle type, so define it using the `customType`:
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
// src/schema.ts
|
|
60
|
+
import { pgTable, bigint, text, vector, index, customType } from "drizzle-orm/pg-core";
|
|
61
|
+
import { sql } from "drizzle-orm";
|
|
62
|
+
|
|
63
|
+
const tsvector = customType<{ data: string }>({
|
|
64
|
+
dataType() {
|
|
65
|
+
return "tsvector";
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export const documents = pgTable(
|
|
70
|
+
"documents",
|
|
71
|
+
{
|
|
72
|
+
id: bigint("id", { mode: "number" }).generatedByDefaultAsIdentity().primaryKey(),
|
|
73
|
+
title: text("title").notNull(),
|
|
74
|
+
body: text("body").notNull(),
|
|
75
|
+
embedding: vector("embedding", { dimensions: 1536 }),
|
|
76
|
+
bodyTsv: tsvector("body_tsv").generatedAlwaysAs(
|
|
77
|
+
sql`to_tsvector('english', "body")`,
|
|
78
|
+
),
|
|
79
|
+
},
|
|
80
|
+
(table) => [
|
|
81
|
+
index("documents_embedding_ann").using(
|
|
82
|
+
"lakebase_ann",
|
|
83
|
+
table.embedding.op("vector_cosine_ops"),
|
|
84
|
+
),
|
|
85
|
+
],
|
|
86
|
+
);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Set the dimension to match your embedding model. Postgres maintains `body_tsv`, so never write it from the app. Generate and apply the migration after the extensions migration above:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npx drizzle-kit generate --name=lakebase_search
|
|
93
|
+
npx drizzle-kit migrate
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## BM25 Index
|
|
97
|
+
|
|
98
|
+
Keep the `lakebase_bm25` index out of `schema.ts`. It must be built only after the initial corpus is loaded, so its build-time statistics are meaningful (see [Full-text search](full-text-search.md)) — a schema migration would build it against an empty table. Add it in a later custom migration that runs after seeding:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx drizzle-kit generate --custom --name=bm25_index
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```sql
|
|
105
|
+
-- drizzle/NNNN_bm25_index.sql, applied after the corpus is seeded
|
|
106
|
+
CREATE INDEX documents_body_bm25 ON documents USING lakebase_bm25 (body_tsv);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Query
|
|
110
|
+
|
|
111
|
+
Use the query builder with Drizzle's `cosineDistance` helper for vector search. It emits the `<=>` operator, so keep the index on `vector_cosine_ops`:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { cosineDistance } from "drizzle-orm";
|
|
115
|
+
import { documents } from "./schema";
|
|
116
|
+
|
|
117
|
+
// queryEmbedding: number[] from the same model used for stored documents
|
|
118
|
+
const distance = cosineDistance(documents.embedding, queryEmbedding);
|
|
119
|
+
|
|
120
|
+
const rows = await db
|
|
121
|
+
.select({ id: documents.id, title: documents.title, distance })
|
|
122
|
+
.from(documents)
|
|
123
|
+
.orderBy(distance)
|
|
124
|
+
.limit(k);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
BM25 has no Drizzle helper: `<@>` and `to_bm25query` require raw SQL. Reference the generated column by its `body_tsv` name. Bind user input as parameters through the `sql` template:
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
import { sql } from "drizzle-orm";
|
|
131
|
+
|
|
132
|
+
const rows = await db.execute(sql`
|
|
133
|
+
SELECT id, title,
|
|
134
|
+
body_tsv <@> to_bm25query(
|
|
135
|
+
to_tsvector('english', ${queryText}),
|
|
136
|
+
'documents_body_bm25'::regclass
|
|
137
|
+
) AS score
|
|
138
|
+
FROM documents
|
|
139
|
+
ORDER BY score
|
|
140
|
+
LIMIT ${k}
|
|
141
|
+
`);
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Run the [hybrid search](hybrid-search.md) RRF query the same way: raw SQL through `db.execute`.
|
|
145
|
+
|
|
146
|
+
## Tune Per Query
|
|
147
|
+
|
|
148
|
+
Per-query GUCs (`lakebase_ann.probes`, `lakebase_ann.epsilon`, `lakebase_bm25.default_limit`, `lakebase_bm25.prefilter`) must be set with `SET LOCAL` inside a transaction so they apply to the same pooled connection as the query:
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { cosineDistance, sql } from "drizzle-orm";
|
|
152
|
+
import { documents } from "./schema";
|
|
153
|
+
|
|
154
|
+
const distance = cosineDistance(documents.embedding, queryEmbedding);
|
|
155
|
+
|
|
156
|
+
const rows = await db.transaction(async (tx) => {
|
|
157
|
+
// SET LOCAL scopes the GUC to this transaction's connection; do not hoist it out.
|
|
158
|
+
// Keep probes at 'auto' unless an IVF `lists` layout exists: a numeric value must
|
|
159
|
+
// match the `lists` shape or it errors ("need 0 probes ..."). See vector-search.md.
|
|
160
|
+
await tx.execute(sql`SET LOCAL lakebase_ann.probes = 'auto'`);
|
|
161
|
+
return tx
|
|
162
|
+
.select({ id: documents.id, title: documents.title, distance })
|
|
163
|
+
.from(documents)
|
|
164
|
+
.orderBy(distance)
|
|
165
|
+
.limit(k);
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Sources:
|
|
170
|
+
|
|
171
|
+
- [Get started with Lakebase Search](https://neon.com/docs/ai/lakebase-search-get-started)
|
|
172
|
+
- [Schema migration with Lakebase Postgres and Drizzle ORM](https://neon.com/docs/guides/drizzle-migrations)
|