From 5f740134b546c577a97ec42da67de1280e739543 Mon Sep 17 00:00:00 2001 From: Kirill Ilin Date: Wed, 18 Mar 2026 22:33:35 +0500 Subject: [PATCH 1/2] fix(postgres): add lifecycle management for helm-managed databases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, removing a database from values.databases had no effect — the database and its associated roles persisted in PostgreSQL. This made it impossible to cleanly delete databases via Helm. Add two cleanup stages to the init script: - Delete databases that have the 'database managed by helm' comment but are no longer listed in values.databases - Delete orphaned roles (db_admin, db_readonly) with proper membership revocation before dropping This mirrors the existing user deletion logic and completes the declarative lifecycle for databases. Assisted-By: Claude AI Signed-off-by: Kirill Ilin --- .../apps/postgres/templates/init-script.yaml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/packages/apps/postgres/templates/init-script.yaml b/packages/apps/postgres/templates/init-script.yaml index 80f7c4c7..1a295034 100644 --- a/packages/apps/postgres/templates/init-script.yaml +++ b/packages/apps/postgres/templates/init-script.yaml @@ -66,6 +66,39 @@ stringData: EOT done + echo "== delete databases" + MANAGED_DBS=$(psql -v ON_ERROR_STOP=1 -t -A -c "SELECT datname FROM pg_database d JOIN pg_shdescription s ON d.oid = s.objoid WHERE s.description = 'database managed by helm'") + DEFINED_DBS="{{ join " " (keys .Values.databases) }}" + DELETE_DBS=$(for db in $MANAGED_DBS; do case " $DEFINED_DBS " in *" $db "*) :;; *) echo $db;; esac; done) + + echo "databases to delete: $DELETE_DBS" + for db in $DELETE_DBS; do + psql -v ON_ERROR_STOP=1 --echo-all -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$db' AND pid <> pg_backend_pid();" + psql -v ON_ERROR_STOP=1 --echo-all -c "DROP DATABASE IF EXISTS \"$db\";" + done + + echo "== delete orphaned managed roles" + MANAGED_ROLES=$(psql -v ON_ERROR_STOP=1 -t -A -c "SELECT rolname FROM pg_roles r JOIN pg_shdescription s ON r.oid = s.objoid WHERE s.description = 'role managed by helm'") + DEFINED_ROLES="{{ range $database, $d := .Values.databases }}{{ $database }}_admin {{ $database }}_readonly {{ end }}" + DELETE_ROLES=$(for role in $MANAGED_ROLES; do case " $DEFINED_ROLES " in *" $role "*) :;; *) echo $role;; esac; done) + + echo "roles to delete: $DELETE_ROLES" + for role in $DELETE_ROLES; do + psql -v ON_ERROR_STOP=1 --echo-all < Date: Wed, 25 Mar 2026 12:17:51 +0500 Subject: [PATCH 2/2] fix(postgres): use DROP DATABASE WITH (FORCE) to avoid race condition Replace separate pg_terminate_backend + DROP DATABASE calls with a single DROP DATABASE ... WITH (FORCE) statement. This eliminates the race window where new sessions could reconnect between termination and drop. Available since PostgreSQL 13. Assisted-By: Claude AI Signed-off-by: Kirill Ilin --- packages/apps/postgres/templates/init-script.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/apps/postgres/templates/init-script.yaml b/packages/apps/postgres/templates/init-script.yaml index 1a295034..500d54d4 100644 --- a/packages/apps/postgres/templates/init-script.yaml +++ b/packages/apps/postgres/templates/init-script.yaml @@ -73,8 +73,7 @@ stringData: echo "databases to delete: $DELETE_DBS" for db in $DELETE_DBS; do - psql -v ON_ERROR_STOP=1 --echo-all -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$db' AND pid <> pg_backend_pid();" - psql -v ON_ERROR_STOP=1 --echo-all -c "DROP DATABASE IF EXISTS \"$db\";" + psql -v ON_ERROR_STOP=1 --echo-all -c "DROP DATABASE IF EXISTS \"$db\" WITH (FORCE);" done echo "== delete orphaned managed roles"