diff --git a/braintrust/README.md b/braintrust/README.md index 0b32372..30ff6b9 100644 --- a/braintrust/README.md +++ b/braintrust/README.md @@ -179,6 +179,14 @@ You may have to adjust your helm values.yaml overrides if you have adjusted any Also if you have custom readiness checks, please unset these customizations and use our new default readiness checks. There is a bug in the dataplane where the endpoint we were using for readiness checks, would never recover if it failed. +### Version 6 + +This version introduces opt-in no-PG mode, allowing Brainstore to store objects directly without PostgreSQL. The new `skipPgForBrainstoreObjects` value defaults to `""` (disabled), so upgrading to v6 makes no behavioral change unless you explicitly set it. + +> **⚠️ WARNING: This is a one-way operation.** Once an object type has been migrated off PostgreSQL, it cannot be un-migrated without downtime. + +See [UPGRADE.md](UPGRADE.md#v600---no-pg-brainstore-objects) for prerequisites and full migration instructions. + ## Example Values Files Example values files for different cloud providers and configurations are located in the `examples/` folder. diff --git a/braintrust/UPGRADE.md b/braintrust/UPGRADE.md index 35877ac..edebfdc 100644 --- a/braintrust/UPGRADE.md +++ b/braintrust/UPGRADE.md @@ -2,6 +2,52 @@ This document outlines breaking changes and required configuration updates for major releases. +## v6.0.0 - No-PG Brainstore Objects + +This release introduces the ability to store Brainstore objects (such as project logs) directly in Brainstore, bypassing PostgreSQL entirely. This is an **opt-in** feature — upgrading to v6 makes no behavioral change unless you explicitly set `skipPgForBrainstoreObjects`. + +> **⚠️ WARNING: This is a one-way operation.** Once an object type has been migrated off PostgreSQL, it cannot be un-migrated without downtime. Do not enable this unless you are ready to commit. + +### Requirements to migrate + +Before enabling no-pg mode, you must: + +1. **Upgrade your data plane to version 1.1.32 or higher.** + +2. **Verify all Brainstore configuration checks pass** on your organization's Data Plane settings page: + + ![Brainstore prerequisites](images/no-pg-prereqs.png) + + The following checks are expected to be incomplete at this stage and can be ignored: + - `Brainstore direct writes` — this will pass once the migration below is complete + - `Response cache URI` and `Code Bundle URI` — these are part of a separate Topics configuration + +### Enabling no-pg mode + +Set the `skipPgForBrainstoreObjects` value in your `values.yaml`: + +```yaml +# Skip PostgreSQL for all object types (recommended for new deployments) +skipPgForBrainstoreObjects: "all" + +# OR: skip for specific objects only +skipPgForBrainstoreObjects: "include:project_logs:5ad850f0-3a1a-4980-b889-d21d4116b5d7,project_logs:45b3aed2-3dde-4f0d-a22c-9af69ee8508e" + +# OR: skip for all objects except specific ones +skipPgForBrainstoreObjects: "exclude:project_logs:5ad850f0-3a1a-4980-b889-d21d4116b5d7" +``` + +When set, the following environment variables are automatically configured: + +- **API**: `BRAINSTORE_WAL_USE_EFFICIENT_FORMAT=true`, `SKIP_PG_FOR_BRAINSTORE_OBJECTS=` +- **Brainstore** (reader, writer, fastreader): `BRAINSTORE_ASYNC_SCORING_OBJECTS=`, `BRAINSTORE_LOG_AUTOMATIONS_OBJECTS=` + +### No rollback + +Unlike previous major version upgrades, there is **no rollback path** for this change. Once objects are migrated off PostgreSQL, reverting requires downtime and manual intervention. Reach out to the Braintrust team on Slack before enabling this if you have concerns. + +--- + ## v2.0.0 - Brainstore Reader/Writer Split This release introduces a significant architectural change that splits the Brainstore service into separate reader and writer services for improved scalability and performance. diff --git a/braintrust/images/no-pg-prereqs.png b/braintrust/images/no-pg-prereqs.png new file mode 100644 index 0000000..e2fbf06 Binary files /dev/null and b/braintrust/images/no-pg-prereqs.png differ diff --git a/braintrust/templates/api-configmap.yaml b/braintrust/templates/api-configmap.yaml index f6414a8..bc0fd30 100644 --- a/braintrust/templates/api-configmap.yaml +++ b/braintrust/templates/api-configmap.yaml @@ -51,5 +51,9 @@ data: BRAINSTORE_INSERT_ROW_REFS: "true" # Logs v2 table. Requires pg_partman extension (default enabled in our TF modules) INSERT_LOGS2: "true" - ALLOW_INVALID_BASE64: {{ .Values.api.allowInvalidBase64 | default "false" | quote }} + ALLOW_INVALID_BASE64: {{ .Values.api.allowInvalidBase64 | default "false" | quote }} NODE_MEMORY_PERCENT: {{ .Values.api.nodeMemoryPercent | default "80" | quote }} + {{- if .Values.skipPgForBrainstoreObjects }} + BRAINSTORE_WAL_USE_EFFICIENT_FORMAT: "true" + SKIP_PG_FOR_BRAINSTORE_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + {{- end }} diff --git a/braintrust/templates/brainstore-fastreader-configmap.yaml b/braintrust/templates/brainstore-fastreader-configmap.yaml index 0faec08..b994299 100644 --- a/braintrust/templates/brainstore-fastreader-configmap.yaml +++ b/braintrust/templates/brainstore-fastreader-configmap.yaml @@ -45,3 +45,7 @@ data: {{- end }} BRAINSTORE_CONTROL_PLANE_TELEMETRY: {{ .Values.global.controlPlaneTelemetry | quote }} NO_COLOR: "1" + {{- if .Values.skipPgForBrainstoreObjects }} + BRAINSTORE_ASYNC_SCORING_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + BRAINSTORE_LOG_AUTOMATIONS_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + {{- end }} diff --git a/braintrust/templates/brainstore-reader-configmap.yaml b/braintrust/templates/brainstore-reader-configmap.yaml index 049cc36..8804085 100644 --- a/braintrust/templates/brainstore-reader-configmap.yaml +++ b/braintrust/templates/brainstore-reader-configmap.yaml @@ -44,4 +44,8 @@ data: {{- end }} {{- end }} BRAINSTORE_CONTROL_PLANE_TELEMETRY: {{ .Values.global.controlPlaneTelemetry | quote }} - NO_COLOR: "1" \ No newline at end of file + NO_COLOR: "1" + {{- if .Values.skipPgForBrainstoreObjects }} + BRAINSTORE_ASYNC_SCORING_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + BRAINSTORE_LOG_AUTOMATIONS_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + {{- end }} \ No newline at end of file diff --git a/braintrust/templates/brainstore-writer-configmap.yaml b/braintrust/templates/brainstore-writer-configmap.yaml index 890d95c..98a9e14 100644 --- a/braintrust/templates/brainstore-writer-configmap.yaml +++ b/braintrust/templates/brainstore-writer-configmap.yaml @@ -44,4 +44,8 @@ data: {{- end }} {{- end }} BRAINSTORE_CONTROL_PLANE_TELEMETRY: {{ .Values.global.controlPlaneTelemetry | quote }} - NO_COLOR: "1" \ No newline at end of file + NO_COLOR: "1" + {{- if .Values.skipPgForBrainstoreObjects }} + BRAINSTORE_ASYNC_SCORING_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + BRAINSTORE_LOG_AUTOMATIONS_OBJECTS: {{ .Values.skipPgForBrainstoreObjects | quote }} + {{- end }} \ No newline at end of file diff --git a/braintrust/tests/api-configmap_test.yaml b/braintrust/tests/api-configmap_test.yaml index e546c32..5723020 100644 --- a/braintrust/tests/api-configmap_test.yaml +++ b/braintrust/tests/api-configmap_test.yaml @@ -188,3 +188,56 @@ tests: - equal: path: data.BRAINSTORE_BACKFILL_DISABLE_NONHISTORICAL value: "true" + + - it: should not include no-pg vars when skipPgForBrainstoreObjects is not set + values: + - __fixtures__/base-values.yaml + release: + namespace: "braintrust" + asserts: + - isNull: + path: data.BRAINSTORE_WAL_USE_EFFICIENT_FORMAT + - isNull: + path: data.SKIP_PG_FOR_BRAINSTORE_OBJECTS + + - it: should include no-pg vars when skipPgForBrainstoreObjects is "all" + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "all" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_WAL_USE_EFFICIENT_FORMAT + value: "true" + - equal: + path: data.SKIP_PG_FOR_BRAINSTORE_OBJECTS + value: "all" + + - it: should pass through include-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "include:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_WAL_USE_EFFICIENT_FORMAT + value: "true" + - equal: + path: data.SKIP_PG_FOR_BRAINSTORE_OBJECTS + value: "include:project_logs:abc123" + + - it: should pass through exclude-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "exclude:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.SKIP_PG_FOR_BRAINSTORE_OBJECTS + value: "exclude:project_logs:abc123" diff --git a/braintrust/tests/brainstore-fastreader-configmap_test.yaml b/braintrust/tests/brainstore-fastreader-configmap_test.yaml index 3bc9e11..0ede35f 100644 --- a/braintrust/tests/brainstore-fastreader-configmap_test.yaml +++ b/braintrust/tests/brainstore-fastreader-configmap_test.yaml @@ -32,3 +32,59 @@ tests: - equal: path: metadata.annotations["custom-annotation"] value: value + + - it: should not include no-pg vars when skipPgForBrainstoreObjects is not set + values: + - __fixtures__/base-values.yaml + release: + namespace: "braintrust" + asserts: + - isNull: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + - isNull: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + + - it: should include no-pg vars when skipPgForBrainstoreObjects is "all" + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "all" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "all" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "all" + + - it: should pass through include-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "include:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "include:project_logs:abc123" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "include:project_logs:abc123" + + - it: should pass through exclude-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "exclude:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "exclude:project_logs:abc123" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "exclude:project_logs:abc123" diff --git a/braintrust/tests/brainstore-reader-configmap_test.yaml b/braintrust/tests/brainstore-reader-configmap_test.yaml index 7626c76..2362693 100644 --- a/braintrust/tests/brainstore-reader-configmap_test.yaml +++ b/braintrust/tests/brainstore-reader-configmap_test.yaml @@ -182,3 +182,59 @@ tests: - equal: path: metadata.annotations["custom-annotation"] value: value + + - it: should not include no-pg vars when skipPgForBrainstoreObjects is not set + values: + - __fixtures__/base-values.yaml + release: + namespace: "braintrust" + asserts: + - isNull: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + - isNull: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + + - it: should include no-pg vars when skipPgForBrainstoreObjects is "all" + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "all" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "all" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "all" + + - it: should pass through include-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "include:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "include:project_logs:abc123" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "include:project_logs:abc123" + + - it: should pass through exclude-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "exclude:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "exclude:project_logs:abc123" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "exclude:project_logs:abc123" diff --git a/braintrust/tests/brainstore-writer-configmap_test.yaml b/braintrust/tests/brainstore-writer-configmap_test.yaml index 0de94d4..af6a0f0 100644 --- a/braintrust/tests/brainstore-writer-configmap_test.yaml +++ b/braintrust/tests/brainstore-writer-configmap_test.yaml @@ -182,3 +182,59 @@ tests: - equal: path: metadata.annotations["custom-annotation"] value: value + + - it: should not include no-pg vars when skipPgForBrainstoreObjects is not set + values: + - __fixtures__/base-values.yaml + release: + namespace: "braintrust" + asserts: + - isNull: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + - isNull: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + + - it: should include no-pg vars when skipPgForBrainstoreObjects is "all" + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "all" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "all" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "all" + + - it: should pass through include-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "include:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "include:project_logs:abc123" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "include:project_logs:abc123" + + - it: should pass through exclude-style skipPgForBrainstoreObjects value + values: + - __fixtures__/base-values.yaml + set: + skipPgForBrainstoreObjects: "exclude:project_logs:abc123" + release: + namespace: "braintrust" + asserts: + - equal: + path: data.BRAINSTORE_ASYNC_SCORING_OBJECTS + value: "exclude:project_logs:abc123" + - equal: + path: data.BRAINSTORE_LOG_AUTOMATIONS_OBJECTS + value: "exclude:project_logs:abc123" diff --git a/braintrust/values.yaml b/braintrust/values.yaml index 544b4aa..8073b2a 100644 --- a/braintrust/values.yaml +++ b/braintrust/values.yaml @@ -334,6 +334,18 @@ azureKeyVaultDriver: keyVaultSecretType: "secret" kubernetesSecretKey: "AZURE_STORAGE_CONNECTION_STRING" +# No-PG mode: controls which object types bypass PostgreSQL and use Brainstore directly. +# WARNING: This is a one-way operation. Once migrated off Postgres, objects cannot be +# un-migrated without downtime. +# Options: +# - "" (default): disabled, PostgreSQL used as normal +# - "all": skip PostgreSQL for all object types +# - "include::,...": skip for specific objects only +# e.g. "include:project_logs:5ad850f0-...,project_logs:45b3aed2-..." +# - "exclude::,...": skip for all objects except specific ones +# e.g. "exclude:project_logs:5ad850f0-..." +skipPgForBrainstoreObjects: "" + # Istio VirtualService configuration (optional) # Enable this to create an Istio VirtualService for the API virtualService: