How Do You Deploy Database-Backed AI Applications on Kubernetes?
You deploy a database-backed AI application on Kubernetes by packaging the database as a StatefulSet (or, more practically, via its official Helm chart) with persistent volumes for its data, running it as a multi-node cluster for high availability, and then connecting your application pods to it over an internal Kubernetes service — while separately configuring resource limits, health checks, TLS, access control, monitoring, and backups so the database survives node failures, upgrades, and real production traffic rather than just working in a demo. Weaviate is a solid option if the “database” in question is a vector database for the AI side of the stack, since it ships an official Helm chart built specifically for this kind of Kubernetes deployment — but everything below applies to database-backed deployments on Kubernetes generally, whichever database you’re running.

Why Databases Need Different Treatment on Kubernetes Than Stateless Apps
Kubernetes was originally designed with stateless workloads in mind: a web server pod can be killed and rescheduled anywhere in the cluster because it holds no important state of its own. A database is the opposite of that. It holds the one thing you can’t afford to lose or duplicate incorrectly — your data — which means every deployment decision has to account for identity, storage, and ordering in a way a stateless app never has to worry about.
This is why databases are deployed as StatefulSets rather than Deployments in Kubernetes. A StatefulSet gives each replica a stable, predictable network identity and its own dedicated storage that follows it even if the pod is rescheduled onto a different physical node. Without that guarantee, a database pod restarting could come back up attached to the wrong volume, or lose track of which node it was supposed to be in a cluster with — either of which is catastrophic for data integrity.
Installing the Database
In practice, almost nobody hand-writes StatefulSet manifests for a production database from scratch. The standard approach is to use the database’s official Helm chart, which packages the StatefulSet, its associated services, config maps, and default resource settings into a single installable unit you can customize with a values file rather than raw YAML.
helm repo add weaviate https://weaviate.github.io/weaviate-helm
helm install my-weaviate weaviate/weaviate
Persistent Storage
Every database pod needs a PersistentVolumeClaim (PVC) so its data survives pod restarts, node failures, and version upgrades. The claim requests storage from whatever storage class your Kubernetes cluster provides — cloud block storage, a networked filesystem, or local disks — and Kubernetes binds it to an actual volume behind the scenes.
One detail that’s easy to overlook until you hit it in production: pick a storage class that supports volume expansion. Databases grow, and if your storage class can’t be resized in place, growing past your initial allocation means a much more disruptive migration later instead of a simple resize operation.
storage:
size: 10Gi
storageClassName: ""
High Availability Through Clustering
A single database pod, no matter how well configured, is a single point of failure. Production deployments run the database as a multi-node cluster with data replicated across nodes, so that losing any one node doesn’t mean losing availability or data.

Two decisions matter most here:
- Node count and spread: a minimum of three nodes, ideally spread across different availability zones, is the common baseline — it’s enough nodes to tolerate one failure while still maintaining quorum, and spreading across zones protects against an entire zone going down.
- Replication factor: setting replication so that each piece of data exists on multiple nodes (commonly three copies) means a node failure doesn’t cause data loss or a gap in query results — another replica already has the data.
replicaCount: 3
If the database shards its data (splits it into partitions distributed across nodes rather than replicating the whole dataset everywhere), the number of shards is often fixed at collection or table creation time and can’t be casually changed afterward. This means it’s worth deliberately over-provisioning shard count relative to your current node count when you first create a collection, specifically so you have room to add nodes and spread existing shards further later without a disruptive full re-partition.
Resource Requests and Limits
Kubernetes needs to know how much CPU and memory each database pod actually needs, both to schedule it onto a node with enough capacity and to prevent it from either starving other workloads or getting starved itself. Requests tell the scheduler what a pod needs guaranteed; limits cap what it’s allowed to consume even under load.
resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "4Gi"
For databases written in garbage-collected languages, it’s also worth tuning the language runtime’s own memory behavior — for example setting an explicit soft memory limit like Go’s GOMEMLIMIT — so the runtime’s own garbage collector doesn’t wait until it’s dangerously close to the Kubernetes memory limit before it starts freeing memory aggressively, which can otherwise cause latency spikes or the pod getting killed for exceeding its limit.
Networking, TLS, and Access Control
A database backing an AI application is rarely meant to be reachable from outside the cluster directly. Traffic typically enters through an Ingress controller, which should be paired with a certificate manager to automatically issue and renew TLS certificates, encrypting both the database’s standard API traffic and any high-performance protocol like gRPC it exposes for lower-latency queries.

Just as important is restricting who can do what once they’re connected. Role-based access control, or a simpler admin allow-list depending on the database, ensures that only specific authenticated identities can perform administrative operations, while application-level access can be scoped more narrowly.
authorization:
rbac:
enabled: true
root_users:
- admin_user1
- admin_user2
Zero-Downtime Updates
Production AI applications generally can’t tolerate a maintenance window every time the underlying database gets a version bump. Configuring a rolling update strategy lets Kubernetes replace old pods with new ones incrementally — bringing up a new pod before tearing down an old one, rather than tearing everything down first — so the cluster keeps serving traffic throughout the upgrade.
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
This only works safely if Kubernetes actually knows when a pod is healthy enough to receive traffic and when it’s still starting up. That’s what liveness and readiness probes are for: a liveness probe tells Kubernetes when to restart a pod that’s stuck, and a readiness probe tells it when a pod is genuinely ready to serve requests, so traffic isn’t routed to a node that’s still loading its index or replaying its write-ahead log after a restart.
Monitoring and Disaster Recovery
None of the above matters if you find out about a problem only after users do. Exposing metrics — query latency, resource usage, error rates — to a monitoring system like Prometheus, and scraping them on a regular interval, turns “something feels slow” into an actual, diagnosable signal.
serviceMonitor:
enabled: true
interval: 30s
scrapeTimeout: 10s
And finally, replication protects you against a node failing — it does not protect you against someone deleting the wrong collection, a bad migration corrupting data, or an entire cluster being lost. That’s what backups are for: automated, scheduled exports of your data to durable external storage such as cloud object storage, with a defined retention policy, so you have a real recovery path that doesn’t depend on the cluster you’re trying to recover being intact in the first place.
Bringing It Together
None of these pieces — StatefulSets, persistent volumes, replication, resource limits, TLS, RBAC, rolling updates, monitoring, and backups — are optional extras bolted onto a “real” deployment. Together, they are what separates a database that happens to be running inside a Kubernetes cluster from a database that’s actually production-ready on Kubernetes. For an AI application, where the database is often on the critical path for every single request the application serves, getting this foundation right isn’t a nice-to-have; it’s what determines whether the application stays up when a node fails, a version needs upgrading, or traffic spikes unexpectedly.