[{"data":1,"prerenderedAt":756},["ShallowReactive",2],{"navigation":3,"\u002Fen\u002Fblog\u002Fpostgresql-helm-chart-kubernetes":4,"\u002Fen\u002Fblog\u002Fpostgresql-helm-chart-kubernetes-surround":745},[],{"id":5,"title":6,"authors":7,"badge":13,"body":14,"date":734,"description":735,"extension":736,"image":737,"lastUpdated":739,"meta":740,"navigation":159,"path":741,"published":159,"seo":742,"stem":743,"tags":13,"__hash__":744},"posts\u002Fen\u002F3.blog\u002F21.postgresql-helm-chart-kubernetes.md","PostgreSQL Helm Chart: How to Deploy Postgres on Kubernetes",[8],{"name":9,"to":10,"avatar":11},"Fabian Sander","\u002Fabout\u002Ffabiansander",{"src":12},"\u002Fimages\u002Fblog\u002Fauthors\u002Ffabian.png",null,{"type":15,"value":16,"toc":718},"minimark",[17,27,32,49,52,56,61,64,87,91,94,214,224,228,231,237,305,308,362,365,398,401,405,408,420,423,426,430,434,437,445,465,469,472,550,553,557,560,563,583,637,644,664,671,675,678,695,698,702,705,708,714],[18,19,20,21,26],"p",{},"Running PostgreSQL on ",[22,23,25],"a",{"href":24},"\u002Fen\u002Fblog\u002Fwhat-is-kubernetes","Kubernetes"," has become standard practice for many teams. Helm has established itself as the go-to tool for making these deployments reproducible. What's often underestimated: stateful workloads like databases are far less forgiving of configuration mistakes than stateless services — and those who have blindly relied on Bitnami charts now face an unexpected decision since 2025.",[28,29,31],"h2",{"id":30},"what-helm-actually-does-here","What Helm actually does here",[18,33,34,38,39,43,44,48],{},[22,35,37],{"href":36},"\u002Fen\u002Fblog\u002Fwhat-is-a-helm-chart","Helm is a package manager for Kubernetes",". A ",[40,41,42],"strong",{},"Helm Chart"," bundles all the Kubernetes manifests you need for a deployment. That includes Deployments, Services, ConfigMaps, Secrets, and PersistentVolumeClaims — all wrapped into a versioned, configurable package. Instead of manually maintaining dozens of YAML files, you define your deviations from the defaults in a ",[45,46,47],"code",{},"values.yaml"," and let the chart handle the rest.",[18,50,51],{},"For PostgreSQL, this means the chart takes care of StatefulSets, Headless Services for peer communication, Persistent Volume integration, and optional replication configurations. You don't need to reinvent the wheel — but you should understand what's happening under the hood.",[28,53,55],{"id":54},"postgresql-helm-chart-deployment-the-direct-path","PostgreSQL Helm Chart deployment — the direct path",[57,58,60],"h3",{"id":59},"prerequisites","Prerequisites",[18,62,63],{},"Before you deploy, make sure you have the following in place:",[65,66,67,71,77,84],"ul",{},[68,69,70],"li",{},"Helm 3.x installed",[68,72,73,76],{},[45,74,75],{},"kubectl"," access to your cluster",[68,78,79,80,83],{},"A ",[40,81,82],{},"StorageClass"," configured that can dynamically provision Persistent Volumes",[68,85,86],{},"A Kubernetes version compatible with the chosen chart",[57,88,90],{"id":89},"installing-the-chart","Installing the chart",[18,92,93],{},"Using a community-compatible chart (more on choosing one in the next section), the basic command looks like this:",[95,96,101],"pre",{"className":97,"code":98,"language":99,"meta":100,"style":100},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","helm repo add \u003Crepo-name> \u003Crepo-url>\nhelm repo update\n\nhelm install my-postgres \u003Crepo-name>\u002Fpostgresql \\\n  --namespace databases \\\n  --create-namespace \\\n  -f values.yaml\n","bash","",[45,102,103,144,154,161,186,197,205],{"__ignoreMap":100},[104,105,108,112,116,119,123,126,130,133,135,138,141],"span",{"class":106,"line":107},"line",1,[104,109,111],{"class":110},"sBMFI","helm",[104,113,115],{"class":114},"sfazB"," repo",[104,117,118],{"class":114}," add",[104,120,122],{"class":121},"sMK4o"," \u003C",[104,124,125],{"class":114},"repo-nam",[104,127,129],{"class":128},"sTEyZ","e",[104,131,132],{"class":121},">",[104,134,122],{"class":121},[104,136,137],{"class":114},"repo-ur",[104,139,140],{"class":128},"l",[104,142,143],{"class":121},">\n",[104,145,147,149,151],{"class":106,"line":146},2,[104,148,111],{"class":110},[104,150,115],{"class":114},[104,152,153],{"class":114}," update\n",[104,155,157],{"class":106,"line":156},3,[104,158,160],{"emptyLinePlaceholder":159},true,"\n",[104,162,164,166,169,172,174,176,178,180,183],{"class":106,"line":163},4,[104,165,111],{"class":110},[104,167,168],{"class":114}," install",[104,170,171],{"class":114}," my-postgres",[104,173,122],{"class":121},[104,175,125],{"class":114},[104,177,129],{"class":128},[104,179,132],{"class":121},[104,181,182],{"class":114},"\u002Fpostgresql",[104,184,185],{"class":128}," \\\n",[104,187,189,192,195],{"class":106,"line":188},5,[104,190,191],{"class":114},"  --namespace",[104,193,194],{"class":114}," databases",[104,196,185],{"class":128},[104,198,200,203],{"class":106,"line":199},6,[104,201,202],{"class":114},"  --create-namespace",[104,204,185],{"class":128},[104,206,208,211],{"class":106,"line":207},7,[104,209,210],{"class":114},"  -f",[104,212,213],{"class":114}," values.yaml\n",[18,215,216,217,220,221,223],{},"Rather than passing every parameter as ",[45,218,219],{},"--set"," flags, use a proper ",[45,222,47],{},". This keeps the deployment traceable, version-controlled, and reproducible.",[57,225,227],{"id":226},"key-configuration-parameters","Key configuration parameters",[18,229,230],{},"Three areas are most critical in practice:",[18,232,233,234,236],{},"Passwords don't belong directly in your ",[45,235,47],{},". Instead, create Kubernetes Secrets upfront and reference them in the chart:",[95,238,242],{"className":239,"code":240,"language":241,"meta":100,"style":100},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","auth:\n  existingSecret: 'my-postgres-secret'\n  secretKeys:\n    adminPasswordKey: 'postgres-password'\n    userPasswordKey: 'user-password'\n","yaml",[45,243,244,253,270,277,291],{"__ignoreMap":100},[104,245,246,250],{"class":106,"line":107},[104,247,249],{"class":248},"swJcz","auth",[104,251,252],{"class":121},":\n",[104,254,255,258,261,264,267],{"class":106,"line":146},[104,256,257],{"class":248},"  existingSecret",[104,259,260],{"class":121},":",[104,262,263],{"class":121}," '",[104,265,266],{"class":114},"my-postgres-secret",[104,268,269],{"class":121},"'\n",[104,271,272,275],{"class":106,"line":156},[104,273,274],{"class":248},"  secretKeys",[104,276,252],{"class":121},[104,278,279,282,284,286,289],{"class":106,"line":163},[104,280,281],{"class":248},"    adminPasswordKey",[104,283,260],{"class":121},[104,285,263],{"class":121},[104,287,288],{"class":114},"postgres-password",[104,290,269],{"class":121},[104,292,293,296,298,300,303],{"class":106,"line":188},[104,294,295],{"class":248},"    userPasswordKey",[104,297,260],{"class":121},[104,299,263],{"class":121},[104,301,302],{"class":114},"user-password",[104,304,269],{"class":121},[18,306,307],{},"The default persistence configuration works for testing but isn't suitable for production. Define size and StorageClass explicitly:",[95,309,311],{"className":239,"code":310,"language":241,"meta":100,"style":100},"primary:\n  persistence:\n    enabled: true\n    size: 50Gi\n    storageClass: 'fast-ssd'\n",[45,312,313,320,327,338,348],{"__ignoreMap":100},[104,314,315,318],{"class":106,"line":107},[104,316,317],{"class":248},"primary",[104,319,252],{"class":121},[104,321,322,325],{"class":106,"line":146},[104,323,324],{"class":248},"  persistence",[104,326,252],{"class":121},[104,328,329,332,334],{"class":106,"line":156},[104,330,331],{"class":248},"    enabled",[104,333,260],{"class":121},[104,335,337],{"class":336},"sfNiH"," true\n",[104,339,340,343,345],{"class":106,"line":163},[104,341,342],{"class":248},"    size",[104,344,260],{"class":121},[104,346,347],{"class":114}," 50Gi\n",[104,349,350,353,355,357,360],{"class":106,"line":188},[104,351,352],{"class":248},"    storageClass",[104,354,260],{"class":121},[104,356,263],{"class":121},[104,358,359],{"class":114},"fast-ssd",[104,361,269],{"class":121},[18,363,364],{},"If you need high availability, a read replica setup is worth considering:",[95,366,368],{"className":239,"code":367,"language":241,"meta":100,"style":100},"architecture: replication\nreadReplicas:\n  replicaCount: 2\n",[45,369,370,380,387],{"__ignoreMap":100},[104,371,372,375,377],{"class":106,"line":107},[104,373,374],{"class":248},"architecture",[104,376,260],{"class":121},[104,378,379],{"class":114}," replication\n",[104,381,382,385],{"class":106,"line":146},[104,383,384],{"class":248},"readReplicas",[104,386,252],{"class":121},[104,388,389,392,394],{"class":106,"line":156},[104,390,391],{"class":248},"  replicaCount",[104,393,260],{"class":121},[104,395,397],{"class":396},"sbssI"," 2\n",[18,399,400],{},"Without explicit replication configuration, you're deploying a single instance. That works — but it's not production-grade.",[28,402,404],{"id":403},"the-bitnami-problem-and-what-it-means-for-your-setup","The Bitnami problem and what it means for your setup",[18,406,407],{},"For years, Bitnami delivered the de facto standard for Helm Charts. Their charts were easy to use, well-documented, and backed by a broad community. That has changed.",[18,409,410,411,415,416,419],{},"Since VMware acquired Bitnami, the repository model has been gradually restructured — a concrete example of ",[22,412,414],{"href":413},"\u002Fen\u002Fblog\u002Fcloud-vendor-lock-in","vendor lock-in",". As of August 2025, direct access to the public Bitnami repository is restricted for commercial users. If you're running ",[45,417,418],{},"helm repo update"," in your CI\u002FCD pipeline without adjustments, you risk deployment failures — not because of a cluster issue, but because the chart repository is no longer accessible as expected.",[18,421,422],{},"For existing setups, this means: check which of your Helm Charts come from Bitnami. Determine whether you're affected — and if so, when your currently cached chart was last successfully pulled.",[18,424,425],{},"No reason to panic, but it does require concrete action.",[28,427,429],{"id":428},"alternatives-to-the-bitnami-postgresql-helm-chart","Alternatives to the Bitnami PostgreSQL Helm Chart",[57,431,433],{"id":432},"open-source-alternatives-at-a-glance","Open-source alternatives at a glance",[18,435,436],{},"There are fully functional alternatives that are actively maintained:",[18,438,439,440,444],{},"For a hands-on walkthrough of deploying PostgreSQL with the Cloudpirates Helm Chart on lowcloud, check out our ",[22,441,443],{"href":442},"\u002Fen\u002Fdocs\u002Fhelm-releases\u002Fdeploy-postgresql","step-by-step guide",".",[65,446,447,453,459],{},[68,448,449,452],{},[40,450,451],{},"Cloudpirates Open Source Helm Charts",": lowcloud provides its own open-source charts as a direct response to the Bitnami situation. The charts are designed with practical defaults and are actively maintained.",[68,454,455,458],{},[40,456,457],{},"Zalando Postgres Operator",": An operator approach controlled via CRDs. More powerful than a simple chart, but also more complex to set up.",[68,460,461,464],{},[40,462,463],{},"CloudNativePG Operator",": The CNCF-maintained Postgres operator with a strong focus on Kubernetes-native features like streaming replication, point-in-time recovery, and automatic failover.",[57,466,468],{"id":467},"criteria-for-choosing-the-right-chart","Criteria for choosing the right chart",[18,470,471],{},"The choice depends on your requirements:",[473,474,475,491],"table",{},[476,477,478],"thead",{},[479,480,481,485,488],"tr",{},[482,483,484],"th",{},"Criterion",[482,486,487],{},"Simple Chart",[482,489,490],{},"Operator Approach",[492,493,494,506,517,528,539],"tbody",{},[479,495,496,500,503],{},[497,498,499],"td",{},"Barrier to entry",[497,501,502],{},"Low",[497,504,505],{},"Medium to high",[479,507,508,511,514],{},[497,509,510],{},"Flexibility",[497,512,513],{},"Limited",[497,515,516],{},"High",[479,518,519,522,525],{},[497,520,521],{},"Automatic failover",[497,523,524],{},"Manually configured",[497,526,527],{},"Built-in",[479,529,530,533,536],{},[497,531,532],{},"Replication management",[497,534,535],{},"Static",[497,537,538],{},"Dynamic",[479,540,541,544,547],{},[497,542,543],{},"Production readiness",[497,545,546],{},"Good for small setups",[497,548,549],{},"Recommended for critical DBs",[18,551,552],{},"For teams running PostgreSQL in production with high-availability requirements, an operator is the more robust choice in the medium term. For smaller services or development environments, a well-configured chart is sufficient.",[28,554,556],{"id":555},"dont-forget-persistence-backups-and-monitoring","Don't forget persistence, backups, and monitoring",[18,558,559],{},"Once the deployment is running, the real operational work begins.",[18,561,562],{},"Make sure your PersistentVolumeClaim is bound to a StorageClass that actually delivers fast I\u002FO. Slow disks are a common PostgreSQL performance killer that only shows up under load.",[18,564,565,566,569,570,573,574,578,579,582],{},"For backups, ",[45,567,568],{},"pg_dump"," remains a valid solution for smaller databases. In Kubernetes-native setups, consider ",[40,571,572],{},"Velero"," for snapshot-based backups of the Persistent Volume on ",[22,575,577],{"href":576},"\u002Fen\u002Fblog\u002Fs3-compatible-object-storage","S3-compatible object storage",", or ",[40,580,581],{},"Barman"," for WAL archiving and point-in-time recovery.",[95,584,586],{"className":97,"code":585,"language":99,"meta":100,"style":100},"# Simple pg_dump from a running pod\nkubectl exec -it my-postgres-0 -n databases -- \\\n  pg_dump -U postgres mydb > backup.sql\n",[45,587,588,594,617],{"__ignoreMap":100},[104,589,590],{"class":106,"line":107},[104,591,593],{"class":592},"sHwdD","# Simple pg_dump from a running pod\n",[104,595,596,598,601,604,607,610,612,615],{"class":106,"line":146},[104,597,75],{"class":110},[104,599,600],{"class":114}," exec",[104,602,603],{"class":114}," -it",[104,605,606],{"class":114}," my-postgres-0",[104,608,609],{"class":114}," -n",[104,611,194],{"class":114},[104,613,614],{"class":114}," --",[104,616,185],{"class":128},[104,618,619,622,625,628,631,634],{"class":106,"line":156},[104,620,621],{"class":114},"  pg_dump",[104,623,624],{"class":114}," -U",[104,626,627],{"class":114}," postgres",[104,629,630],{"class":114}," mydb",[104,632,633],{"class":121}," >",[104,635,636],{"class":114}," backup.sql\n",[18,638,639,640,643],{},"For monitoring, ",[40,641,642],{},"postgres_exporter"," is the standard way to export PostgreSQL metrics to Prometheus. Key metrics to watch:",[65,645,646,652,658],{},[68,647,648,651],{},[45,649,650],{},"pg_stat_activity"," — active connections and running queries",[68,653,654,657],{},[45,655,656],{},"pg_replication_lag"," — replication delay for read replicas",[68,659,660,663],{},[45,661,662],{},"pg_database_size_bytes"," — database growth over time",[18,665,666,667,670],{},"A ready-made Grafana dashboard is available for import — search for Dashboard ID ",[45,668,669],{},"9628"," in the Grafana repository.",[28,672,674],{"id":673},"when-a-managed-approach-is-the-better-choice","When a managed approach is the better choice",[18,676,677],{},"Running PostgreSQL on Kubernetes is solvable, but it takes time. Someone has to update the charts, monitor backups, test failover scenarios, and ensure storage classes still work correctly after cluster upgrades.",[18,679,680,681,685,686,689,690,694],{},"For teams that want to focus on their application rather than database infrastructure, a ",[22,682,684],{"href":683},"\u002Fen\u002Fblog\u002Fdevops-as-a-service","DevOps as a Service platform"," like ",[40,687,688],{},"lowcloud"," is a pragmatic alternative. PostgreSQL is provided as a managed service — built on the same ",[22,691,693],{"href":692},"\u002Fen\u002Fblog\u002Fkubernetes-digital-sovereignty","sovereign Kubernetes infrastructure",", but without the operational overhead. You don't need to maintain your own Helm Charts, set up manual backup configurations, or build a monitoring setup from scratch.",[18,696,697],{},"This isn't a replacement for every use case. If you need specific PostgreSQL configurations, custom extensions, or full control over every parameter, self-hosting is the better path. For everything else, it's worth asking: is this really a differentiating advantage for your team, or just necessary overhead?",[28,699,701],{"id":700},"conclusion","Conclusion",[18,703,704],{},"Deploying PostgreSQL with Helm on Kubernetes works. The steps are manageable, the configuration options well-documented. What has changed: choosing the right chart is no longer a given. If you've been relying on Bitnami, you should review your CI\u002FCD pipeline and evaluate an alternative — whether that's a community chart, an operator, or a managed service depends on your own requirements.",[18,706,707],{},"The infrastructure decisions you make today directly impact maintainability twelve months from now.",[18,709,710,711,444],{},"To deploy PostgreSQL on lowcloud in minutes, follow our ",[22,712,713],{"href":442},"PostgreSQL guide in the documentation",[715,716,717],"style",{},"html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":100,"searchDepth":146,"depth":146,"links":719},[720,721,726,727,731,732,733],{"id":30,"depth":146,"text":31},{"id":54,"depth":146,"text":55,"children":722},[723,724,725],{"id":59,"depth":156,"text":60},{"id":89,"depth":156,"text":90},{"id":226,"depth":156,"text":227},{"id":403,"depth":146,"text":404},{"id":428,"depth":146,"text":429,"children":728},[729,730],{"id":432,"depth":156,"text":433},{"id":467,"depth":156,"text":468},{"id":555,"depth":146,"text":556},{"id":673,"depth":146,"text":674},{"id":700,"depth":146,"text":701},"2026-03-16","Learn how to deploy PostgreSQL with Helm on Kubernetes, why Bitnami charts have become problematic, and what alternatives are available.","md",{"src":738},"\u002Fimages\u002Fblog\u002Fpostgresql-helm-chart-kubernetes.jpg","2026-04-13",{},"\u002Fen\u002Fblog\u002Fpostgresql-helm-chart-kubernetes",{"title":6,"description":735},"en\u002F3.blog\u002F21.postgresql-helm-chart-kubernetes","ks0GplQqWS4R2ZkDrLtFdo1GAquLLqwBjrO_Yv_lLnY",[746,751],{"title":747,"path":748,"stem":749,"description":750,"children":-1},"The 7 Biggest DevOps Problems in SMBs – And How to Fix Them","\u002Fen\u002Fblog\u002Fdevops-problems-smb","en\u002F3.blog\u002F20.devops-problems-smb","DevOps in SMBs often fails for the same reasons: missing roles, manual deployments, no monitoring. Here is how to tackle the 7 most common pitfalls.",{"title":752,"path":753,"stem":754,"description":755,"children":-1},"Platform Engineering vs. DevOps – What","\u002Fen\u002Fblog\u002Fplatform-engineering-vs-devops","en\u002F3.blog\u002F22.platform-engineering-vs-devops","DevOps and Platform Engineering compared: key differences, overlap, and when it makes sense to invest in an Internal Developer Platform.",1776469309123]