Skip to content

Flash wear

This page answers what is writing to the router’s flash, and whether the flash is wearing. Nothing needed provoking: the RB5009 writes to NAND on its own, and the agent’s yaffs source shows it. The MTD figures are from 2026-09-14.

Measured on RB5009UG+S+ · 4 × 1.4 GHz Cortex-A72 · RouterOS 7.24.2 · Linux 5.6.3 · · agent at 10 Hz in an ephemeral privileged container

Over one 30-second window at idle, the Main partition took 2 page writes and 14 page reads; over another, zero.

The cause is findable:

/system/logging/print where action="disk"
# TOPICS ACTION
30 dns disk

The dns topic logs to disk, which is also why this device’s log holds tens of thousands of rows. If the pw (page writes) or er (erasures) deltas climb, ask what started writing.

Field Meaning Read it as
er erasures the counter that maps to flash lifetime
pw / pr page writes / reads the workload
gcc GC copies write amplification: gccpw means the filesystem is working hard for each byte you store
gc garbage collections how often the filesystem collected at all
bad bad blocks a level, and it must stay 0
free free chunks headroom

On /metrics the counters are mikroscope_flash_operations_total{device,kind} with kind one of page_writes, page_reads, erasures, gc_copies and gcs; the levels are mikroscope_flash_bad_blocks and mikroscope_flash_free_chunks.

At the default per-source floors the counters are read every tick and stored only when a counter moved or the free-chunk level changed, which on the reference device is about 0.04 times a second (a few times a minute). A missing flash row in a sample means neither happened, not that the source is absent.

Both YAFFS devices are reported. The split is instructive: after two weeks, the Main partition showed 83 812 page writes and 1 579 erasures, while the Boot partition showed 6 page writes and 16 erasures for the device’s whole life — Boot is written only by a firmware upgrade.

The ECC counters: the warning before the loss

Section titled “The ECC counters: the warning before the loss”

Under privileged=yes the MTD ECC counters are readable too, from /sys/class/mtd: corrected_bits, ecc_failures and bad_blocks. All are zero on a healthy device. corrected_bits climbing is aging NAND; ecc_failures is data loss.

The YAFFS bad-block count is the post-mortem — a block is retired only after the ECC has failed on it. The corrected-bit count is the leading indicator, because it climbs as the cells weaken. The kernel publishes the ceiling as well: bitflip_threshold is the corrected bits per ECC step at which it moves the data off a block, and ecc_strength is the most bits per step the code can correct at all.

On the reference RB5009 on 2026-09-14 there were three partitions — RouterBoard NAND 1 Boot (8 MiB), RouterBoard NAND 1 Main (1 GiB) and RouterBoot (1 MiB SPI) — with corrected_bits, ecc_failures, bad_blocks and bbt_blocks all 0, and bitflip_threshold 12 and ecc_strength 16 on the NAND.

In a sample they are mtd rows (corr, fail, bad, bbt, bitflip_threshold, ecc_strength); on /metrics, mikroscope_mtd_ecc_corrected_bits_total{device,partition}, mikroscope_mtd_ecc_failures_total, mikroscope_mtd_blocks{kind="bad"|"bbt"}, mikroscope_mtd_bitflip_threshold and mikroscope_mtd_ecc_strength. They are cumulative since boot and shipped as read, never differenced, because they move on the scale of a device’s lifetime. The agent reads them every 10 s — an arbitrary, generous cadence, not a measured floor.

This is the source that justifies --ephemeral: a deployment with its root and image on tmpfs adds nothing to these counters at all.

Needed no provoking ·

  • pw and er deltas at idle that you did not cause: something is configured to write. Look at /system/logging actions set to disk first.
  • gcc far above pw: the filesystem is paying write amplification.
  • corrected_bits rising, or any ecc_failures or new bad blocks: the flash itself, not the workload.