Ceph nearfull: the 85% warning that decides whether the cluster can heal
OSD_NEARFULL or POOL_NEAR_FULL in ceph health detail means HEALTH_WARN. Clients are still reading and writing, and nothing looks broken yet. The nearfull ratio (default 0.85) is not a polite reminder to plan storage. It is the point where Ceph warns it is running out of the spare space it needs to heal itself.
One OSD failure at 85% can push surviving OSDs past backfillfull (0.90), at which point backfills refuse to start and recovery stalls. If another OSD fails in that window, you are left with degraded PGs that cannot be recovered, and the next stop is OSD_FULL at 95% where all client writes return ENOSPC.
What this means
Ceph has three capacity thresholds, all stored in the OSDMap after cluster creation:
| Threshold | Default | Effect |
|---|---|---|
nearfull_ratio | 0.85 | HEALTH_WARN, backfill may be throttled |
backfillfull_ratio | 0.90 | Target OSDs refuse backfill data, recovery blocks |
full_ratio | 0.95 | All writes stop, clients get ENOSPC |
Ceph enforces nearfull < backfillfull < full, and the OSD_OUT_OF_ORDER_FULL health check fires if you set them in the wrong order.
The non-obvious part: backfillfull does not produce a HEALTH_ERR. It produces backfill_toofull PG states and silently stalls recovery. A cluster sitting at 88% looks like it is functioning, but if an OSD fails, the PGs assigned to it cannot be redistributed because no surviving OSD will accept the backfill. The warning you ignored becomes the recovery that never starts.
flowchart TD
A["Cluster at 85%+ (nearfull)"] --> B["OSD fails"]
B --> C["PGs need to move to surviving OSDs"]
C --> D{"Surviving OSDs under 90%?"}
D -->|"Yes"| E["Backfill proceeds, cluster self-heals"]
D -->|"No"| F["backfill_toofull blocks recovery"]
F --> G["Degraded PGs accumulate"]
G --> H["Second failure risks data loss"]This cascade is why the headroom rule exists. To survive losing one failure domain (host, rack) worth of OSDs and still have recovery proceed, you need enough spare capacity that the redistributed data does not push surviving OSDs past backfillfull. The operator rule of thumb: stay at least 20% below backfillfull. With the default backfillfull at 0.90, that means keeping raw utilization below roughly 70-72%.
Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| Organic data growth | All OSDs filling evenly, nearfull rising slowly over weeks | ceph df trend, daily growth rate |
| Unbalanced CRUSH distribution | A few OSDs hit nearfull while cluster average is moderate | ceph osd df tree, max vs mean utilization |
| OSD loss reducing effective capacity | Nearfull appears after OSDs marked OUT | ceph osd tree, count of OUT OSDs |
| Snapshot accumulation | Pool grows but live data size does not | ceph df detail, snapshot counts per pool |
| RGW GC backlog | RGW pools growing after bulk deletes | radosgw-admin gc list --include-all |
| Reweight drift | One OSD oversized from past reweight imbalance | ceph osd df, CRUSH weights |
Quick checks
These are read-only and safe to run during production.
# Which OSDs and pools triggered nearfull
ceph health detail | grep -iE 'nearfull|near_full'
# Per-OSD utilization with failure domain hierarchy
ceph osd df tree
# Actual configured thresholds from the OSDMap (not ceph.conf)
ceph osd dump | grep -E 'full_ratio|nearfull_ratio|backfillfull_ratio'
# Pool-level usage and max_avail
ceph df detail
# PGs already blocked by capacity
ceph pg dump_stuck unclean | grep -iE 'toofull'
# Failure domains and any down/out OSDs reducing capacity
ceph osd tree
# Recovery flags that may be silently stopping healing
ceph osd dump | grep -E 'norecover|nobackfill|noout'
How to diagnose it
Confirm the real thresholds. The defaults are 0.85 / 0.90 / 0.95, but your cluster may have been tuned. Run
ceph osd dump | grep -E 'full_ratio|nearfull_ratio|backfillfull_ratio'. These values live in the OSDMap, notceph.conf, so editing the config file has no effect on a running cluster. Useceph osd set-nearfull-ratio,ceph osd set-backfillfull-ratio, andceph osd set-full-ratioto change them.Check whether recovery is already blocked. Look for
backfill_toofullorrecovery_toofullPG states. If you see them alongsideOSD_NEARFULL, the trap has already sprung: the cluster cannot heal because target OSDs are too full. This is more urgent than the nearfull warning itself.Find the fullest OSDs, not the cluster average.
ceph osd df treeshows per-OSD utilization. The OSD that triggers nearfull is the most-full one, not the average. A cluster at 70% average with one OSD at 86% is already in nearfull. CRUSH does not guarantee even distribution, and variance of 10-20% between OSDs is common.Estimate runway. Track daily growth rate from
ceph dfsamples over time:(total_bytes - used_raw_bytes) / daily_growth_rate. Use the worst-case growth, not the average. Account for replication: a 3x replicated pool uses 3x raw space per usable byte.Model losing your largest failure domain. If you lose the host with the most OSDs, can the remaining OSDs absorb that data without crossing backfillfull? This is the question the nearfull warning is actually asking. If the answer is no, you are already in the danger zone regardless of the current cluster-wide percentage.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
ceph_osd_nearfull_ratio / ceph_osd_full_ratio | Actual configured thresholds from OSDMap | Alerts must use these, not hardcoded 0.85 / 0.95 |
ceph_cluster_total_used_raw_bytes / ceph_cluster_total_bytes | Raw cluster utilization | Trending toward 0.70 with OSD failure risk |
| Per-OSD utilization (max, not mean) | First OSD to cross threshold triggers the warning | Max OSD above configured nearfull ratio |
ceph_pg_backfill_toofull / ceph_pg_recovery_toofull | Recovery already capacity-blocked | Any nonzero count |
ceph_pool_recovering_bytes_per_sec | Is recovery making progress | Zero with degraded PGs present |
ceph_health_detail{name="OSD_NEARFULL"} | The health check itself | Active |
ceph_health_detail{name="POOL_NEAR_FULL"} | Pool-level nearfull (quota or pool fullness) | Active |
ceph_osd_flag_norecover / ceph_osd_flag_nobackfill | Recovery intentionally stopped | Set with degraded PGs |
The most common monitoring mistake is alerting on a hardcoded 0.85. If an operator tuned mon_osd_nearfull_ratio to 0.80 for a small cluster, your 0.85 alert fires too late. Always alert against the actual configured ratio exposed as ceph_osd_nearfull_ratio.
Fixes
Reweight oversized OSDs (fast, temporary)
If a small number of OSDs are disproportionately full, reweight them down so CRUSH moves data elsewhere:
# Caution: triggers data movement. Do one OSD at a time and watch recovery impact.
ceph osd reweight <osd-id> 0.9
This only helps if other OSDs have room. If the whole cluster is tight, reweighting just moves the problem.
Add capacity (the real fix)
New OSDs are the only durable fix for genuine capacity exhaustion. Adding OSDs gives CRUSH more targets and lowers per-OSD utilization. Plan for the rebalance I/O impact during the addition, especially on clusters where client I/O and recovery share the same network or disks.
Delete data or snapshots
Check for snapshot accumulation, which consumes space invisibly:
ceph df detail
RBD and CephFS snapshots from weeks ago on heavily-written volumes can be enormous. Removing stale snapshots frees space, but the deletion itself generates I/O as Ceph flattens the deltas.
Force RGW garbage collection
If you run RGW and recently deleted large volumes of objects, the data may still be queued for GC rather than removed:
# Processes the GC queue once and exits
radosgw-admin gc process
Deleted objects and aborted multipart uploads are not removed immediately. A GC backlog can consume significant space that ceph df attributes to the pool without any obvious live-data cause.
Temporarily raise backfillfull_ratio (emergency only)
If recovery is already blocked by backfill_toofull and you need it to proceed while you add capacity, you can raise backfillfull_ratio slightly with ceph osd set-backfillfull-ratio. This is risky: it lets OSDs accept more data and pushes them closer to full_ratio, where writes stop entirely. Restore the default as soon as capacity is added. The same caution applies to raising full_ratio to unblock writes: it buys time but does not solve the underlying shortage.
Prevention
- Alert against the configured ratio, not 0.85. Use
ceph_osd_nearfull_ratioas the threshold in your alert, not a hardcoded constant. - Track per-OSD max utilization. The cluster average hides the OSD that crosses first. Alert when any OSD exceeds 80% of its configured nearfull ratio.
- Keep raw utilization below roughly 70%. This is the 20% headroom rule below backfillfull. It is the difference between surviving an OSD failure and deadlocking recovery.
- Model failure scenarios in capacity planning. Project what happens if you lose your largest failure domain. If the answer is crossing backfillfull, you need more capacity before the next failure, not after.
- Watch for small clusters. The default thresholds assume enough OSDs that losing one is a small percentage of capacity. On a 3-5 node cluster, losing one node is a large fraction of total space, and the defaults are too aggressive. Consider lowering nearfull for small clusters so the warning fires while there is still time to act.
- Track daily growth rate. Runway estimation only works if you know your growth rate. Sample
ceph dfregularly and trend it, then compute days-to-nearfull against the worst-case growth, not the average.
How Netdata helps
- Per-second per-OSD utilization shows the OSD that crosses nearfull first, not just the cluster average that hides it.
- Correlate nearfull with PG state. When
OSD_NEARFULLfires, Netdata showsceph_pg_backfill_toofullandceph_pg_recovery_toofullon the same timeline, so you immediately know whether recovery is already blocked. - Recovery rate trending.
ceph_pool_recovering_bytes_per_secnext to degraded PG counts tells you whether healing is progressing or stalled, which is the question that actually matters once capacity gets tight. - Configured-ratio awareness. Netdata surfaces
ceph_osd_nearfull_ratioandceph_osd_full_ratioas metrics, so alerts track the real threshold even if operators tune it away from the defaults. - Per-device-class breakdown.
ceph_cluster_by_class_total_bytesseparates HDD, SSD, and NVMe capacity, which matters when one device class fills faster than another.






