In-Cluster Database and Cache
From NetBox Enterprise 2.3.0, a multi-node HA cluster can run its PostgreSQL and Redis tiers in-cluster instead of depending on external services. This page covers what each tier guarantees, its placement and durability behavior, and the conditions that need operator attention.
Available in NetBox Enterprise 2.3.0
In-cluster HA for PostgreSQL and Redis is new in 2.3.0. On earlier releases, multi-node HA requires external PostgreSQL and Redis.
High availability needs every data tier to survive the loss of a node (see High Availability). From 2.3.0, the database and cache tiers can meet that requirement inside the cluster rather than from external services: on three or more nodes with the multi-node entitlement, the built-in PostgreSQL runs with quorum synchronous replication and the built-in Redis runs with a Sentinel quorum.
External PostgreSQL and Redis remain fully supported, and stay the stronger choice in one specific respect covered under PostgreSQL placement.
For the object-storage tier, see In-Cluster Object Storage.
When to use the in-cluster data tier
| External PostgreSQL / Redis | In-cluster | |
|---|---|---|
| Who runs it | A cloud provider, or you | NetBox Enterprise, on the cluster nodes |
| Making it HA | Your responsibility | Managed for you at 3+ nodes with the entitlement |
| Best fit | You already run managed database and cache services, or need a hard no-two-replicas-per-node guarantee | You want fewer external dependencies |
Both satisfy the HA requirement. The choice is operational — except for the placement guarantee noted below.
Requirements
Both tiers become HA-capable in place, with no configuration change, when all of the following hold:
- Three or more nodes. Each tier auto-scales its instance count to
min(node count, 3). - The multi-node entitlement (included in the Premium tier).
- The tier left in-cluster — that is, not pointed at an external endpoint.
Below three nodes a tier follows the same min(node count, 3) rule, so a two-node cluster runs two instances — enough to replicate, but not enough for the three-instance guarantees described below. Without the entitlement, a tier is capped at a single instance regardless of node count and is not HA. NetBox Enterprise reports both states rather than failing silently — see Conditions to watch.
PostgreSQL
Replication and data loss
At three or more instances, PostgreSQL runs Patroni quorum synchronous replication (synchronous_mode: quorum with synchronous_node_count: 1). With three instances — one primary and two standbys — every commit must be acknowledged by at least one standby before it returns to the client.
The result:
- Losing the primary promotes an in-sync standby with no acknowledged write lost — an RPO of approximately zero.
- Losing a single standby still leaves a second in-sync standby, so commits keep their synchronous guarantee.
The RPO ≈ 0 guarantee is availability-first, not absolute
Synchronous mode is deliberately non-strict. If every eligible standby is lost, Patroni keeps the primary writable by degrading to asynchronous replication rather than blocking writes. The RPO ≈ 0 guarantee therefore holds while a quorum standby is in sync — it is not an absolute promise across every failure sequence. This trades a narrow durability window for staying writable, which is the right default for most deployments but is worth knowing if your requirements say otherwise.
Two-instance clusters stay asynchronous by design. A single standby would pay synchronous-commit latency in normal operation and then drop straight to async the moment that standby restarted, buying no durability over plain async.
PostgreSQL placement
PostgreSQL replica placement is best-effort, not guaranteed. The scheduler is asked to spread instances across nodes as a preference, so under resource pressure two instances can land on the same node — which would make that node's loss more disruptive than the replication design implies.
If you need a guarantee that no two database replicas ever share a node, use external PostgreSQL. This is the one respect in which external remains stronger than in-cluster.
Backups
Database backups do not go to NetBox's object storage. The built-in PostgreSQL writes pgBackRest backups and WAL to their own dedicated volume, deliberately separate from the media and scripts bucket — so enabling in-cluster object storage does not put your database backups on the same store as your media.
As with every tier, replication is not a backup. Disaster recovery still requires an external backup target — see Backups.
Resources
The PostgreSQL Resources preset in the Admin Console defaults to Unlimited, which applies no CPU or memory constraints. That lets PostgreSQL use whatever the node has, and means it is not bounded if a node comes under pressure. On a multi-node HA cluster carrying three PostgreSQL instances alongside the other tiers, consider selecting a preset to bound it.
Redis
Failover
Redis runs with Sentinel for master discovery and automatic failover. Redis data pods scale to min(node count, 3) and are spread one per node.
Sentinel is deployed once the effective Redis size is greater than one — there is nothing to fail over to at a single data pod, so a single-instance tier runs no Sentinel at all. Above that it runs three pods for quorum consensus whatever the data-pod count, spread across nodes so that losing one node cannot take out quorum.
PodDisruptionBudgets cover both Redis and Sentinel with maxUnavailable: 1, so voluntary disruptions — a node drain or a rolling upgrade — cannot take down more than one pod of either set at a time, preserving a failover target. The Redis PDB applies once there are two or more replicas; a single-instance Redis has nothing to protect.
Redis placement
Unlike PostgreSQL, Redis and Sentinel get a hard one-pod-per-node placement constraint (DoNotSchedule) once the cluster has enough nodes, so no two pods of either set share a node.
There is one exception, and it needs operator action — see RedisSpreadHeld below.
Task queue durability
NetBox's background task queue (RQ) runs on Redis. Two defaults determine what happens to enqueued jobs when a Redis master is lost:
- Replication is asynchronous. A write acknowledged by the master may not have reached a replica yet.
- AOF (append-only file) persistence is disabled by default. On restart, Redis loads the compact RDB snapshot rather than replaying every write.
Together these mean enqueued background jobs can be lost when a Redis master fails over. Cached data and session state are rebuilt transparently; a queued job that was accepted but not yet run may simply not run. In practice that means a webhook, script, or report execution can be dropped by a failover.
You can enable AOF (redis.aofEnabled: true, or the AOF Mode setting in the Admin Console) to maximize write durability. Note the tradeoff documented under Redis configuration: with AOF enabled, a Redis that crashed on out-of-memory replays its log on restart and re-fills memory, which can produce a restart loop. AOF disabled avoids that loop.
Guidance pending
NetBox Labs has not yet published a recommended durability posture for the task queue. The behavior above is what ships by default. If losing an in-flight background job on failover is unacceptable for your deployment, raise it with your account team rather than inferring a recommendation from the default.
Resources
The Redis Resources preset defaults to Small — 250m CPU and 256Mi memory requested per data pod, with limits of 500m and 512Mi. Each data pod also takes a 1Gi persistent volume. At three nodes that is three data pods plus three Sentinel pods.
Conditions to watch
NetBox Enterprise reports data-tier HA problems as conditions on the NetBoxEnterprise resource, visible via kubectl describe netboxenterprise. Three are worth knowing.
On Embedded Cluster, get a shell with kubectl on it first — the appliance does not put one on your login PATH:
sudo /var/lib/embedded-cluster/bin/netbox-enterprise shellHANotEnabled
The cluster has three or more nodes but HA has not been enabled. Run netbox-enterprise enable-ha to complete the setup.
HAWithoutExternalData
HA is active, but at least one data tier cannot survive the loss of a node. The message names the specific tier or tiers that still need attention — for PostgreSQL and Redis, that means either pointing the tier at an external endpoint or supplying the multi-node entitlement so the in-cluster tier scales past a single instance.
This condition keys off each tier's actual scaled instance count rather than the raw entitlement, so it stays accurate in both directions: a tier explicitly pinned to one instance is flagged even on an entitled cluster, and a tier already scaled out stays unflagged through an entitlement lapse.
RedisSpreadHeld
Two or more in-cluster Redis pods share a node, and their ReadWriteOnce volumes pin them there. Applying the hard one-pod-per-node spread could not be satisfied without leaving a pod Pending, so it is held as a soft preference instead.
The tier serves normally, but it is not protected against losing that node — and this state is permanent until an operator acts. It typically arises on a cluster that started smaller and grew, leaving Redis pods bound to volumes on nodes they were originally scheduled onto.
To take the guarantee, first find out which pod is the master. The RedisReplication resource names it directly:
kubectl get redisreplication <cluster-name>-redis -n <namespace>
# NAME MASTER
# netbox-redis netbox-redis-1Then list the replicas with the node each one is on, and pick a replica that shares a node with another Redis pod:
kubectl get pods -n <namespace> -l redis-role=slave \
-o custom-columns='POD:.metadata.name,NODE:.spec.nodeName'Every Redis pod carries a redis-role label of either master or slave, kept current by the operator, so this listing excludes the master by construction. Cross-check against the MASTER value above before deleting anything.
With a co-located replica chosen:
- Delete that replica's PersistentVolumeClaim.
- Delete its pod, so it rebinds on a node with no Redis pod.
The operator hardens the spread on its own once the tier is one pod per node.
Delete a replica's volume, never the master's
The master's volume holds everything written since the last replica sync, so deleting the master's PVC loses that data. Confirm the pod you are about to delete appears in the redis-role=slave listing and is not the pod named as MASTER.
Note that the master can move between pods at any time — a failover reassigns the role — so check immediately before acting rather than relying on an earlier reading.
Limitations
- Best-effort PostgreSQL placement. Use external PostgreSQL where a no-two-replicas-per-node guarantee is required (see PostgreSQL placement).
- Task-queue jobs are not durable by default (see Task queue durability).
- HA only. These tiers become HA at three or more nodes with the multi-node entitlement. A two-node cluster runs two instances, which replicate but do not provide the three-instance guarantees above; without the entitlement, a tier is capped at one instance.
- Replication is not backup. An external backup target is still required for disaster recovery — see Backups.
Next steps
- High Availability — full HA topology, requirements, and failover behavior
- In-Cluster Object Storage — the third data tier
- External database guide — PostgreSQL and Redis configuration for external services
- Redis configuration — AOF, memory caps, and other Redis tunables
- Backups — disaster-recovery and manual backup procedures
High Availability Requirements
What high availability is in NetBox Enterprise, what it requires, and how a multi-node cluster behaves on node or availability-zone loss
Topology-Aware Node Labels
Tag Embedded Cluster nodes with topology labels (topology.kubernetes.io/zone) to enable zone-aware pod spreading and storage replication