Engineering 21 min read

Your Note Was 40 Bytes. Your Disk Wrote 55 Kilobytes.

MMNMNOTE
write amplificationjournaldfilesystemlinuxstoragelocal-firstengineering

A 4-byte message — the word "test" — produces a 752-byte journal record and triggers at least 55 KB of physical disk writes on a standard Linux ext4 system. That is a write amplification factor of roughly 13,750×. This post traces every multiplier in the chain: block granularity, filesystem journaling, structured-record overhead, and copy-on-write amplification.1 2 3

The measurement is not vendor marketing, not an SSD endurance claim, and not a theoretical worst case. In August 2026, a GitHub contributor named ValdikSS posted a methodical instrumented run against systemd's journald — kernel block-stat counters before and after a single logged message, a controlled plain-file comparison as the baseline, and a second run on btrfs for comparison.2 The thread drew 236 points and 179 comments on Hacker News as of 2026-08-14.4 This post reads those numbers carefully, then explains what produces each one.

The finding matters whether you are a systems programmer auditing SSD wear, a note-taking enthusiast wondering where writes go, or anyone who has asked: does saving a small file really cost what I think it costs?


The receipt: what the measurement actually shows

A structured logging daemon — measured with kernel block-stat counters — writes between 55 KB and 386 KB to disk for a message a few bytes long, even when you send only one message. The plain-file control for identical content costs roughly one 4 KB block.

The primary source is systemd/systemd GitHub issue #40262, posted 2026-08-03.2 The methodology: create a loop device, mount it with Compress=no, run one or fourteen logger -p info test commands, then read the block-stat deltas. The deltas report in 512-byte sectors — the Linux kernel defines a "sector" as a standard UNIX 512-byte sector, independent of any device or filesystem block size.5

The measured figures:

That last figure is the load-bearing comparison. The same content, durably flushed, cost roughly one filesystem block. The structured logger cost between 55 KB and 386 KB.


The multiplier chain, layer by layer

Each layer in the storage stack adds its own write overhead. They do not add — they multiply.

Layer 1 — The block floor

Disks do not write bytes; they write blocks. The default block size on Linux ext4 is 4 KB. When you write 4 bytes of user data, the filesystem must read the existing block at that location, modify it in memory, and write the entire 4 KB block back. Even a single-byte write costs one full block of physical I/O.

This is the floor beneath every write on every filesystem. You cannot write less than 4 KB to ext4 through the kernel's block layer. The measurement confirms it: the plain-file control — three sequential appends with explicit fdatasync+fsync — wrote roughly one block per operation plus a small journal commit.

Layer 2 — The filesystem journal

Most Linux filesystems run in journaled mode by default. Before writing a data block, the filesystem writes the intended change to a separate journal area, so that a crash mid-write can be recovered cleanly — the mechanism that prevents corruption.9 On ext4's default data=ordered mode, metadata changes go through the journal. The journal itself is a second region of the disk being written.

A single small write can therefore trigger: one write to the journal area (recording what will change), one write of the actual data block, and a journal commit record. That is at minimum three block-layer operations for one logical write.

Layer 3 — The structured record

journald does not store raw text. The on-disk format is a binary structure: each message is wrapped with metadata fields — priority, PID, UID, GID, hostname, transport, timestamp, monotonic clock, cursor fields, machine ID, and a data hash — laid out for indexed random-access queries and cryptographic sealing.10

ValdikSS measured the overhead directly. One logger -p info test message — four bytes of user text — produces a journal record of "about 752 bytes" when read back with journalctl -o json -a | wc -c.2 The record is 188× the user payload before any block rounding, before any filesystem journal overhead, before any metadata write.

# Send one four-byte message to the journal
logger -p info test

# Read it back as structured JSON and measure the byte count
journalctl -o json -a -n 1 | wc -c
# → "about 752 bytes" (ValdikSS, 2026-08-03)

Layer 4 — Copy-on-write

On filesystems with copy-on-write semantics — btrfs by default; APFS on macOS — a write never overwrites data in place. Instead, the filesystem writes the new version to a free location, then atomically updates the metadata pointer. The old block remains until the next garbage-collection pass.

For a small write, CoW means: write the new block at a fresh location, write updated b-tree metadata, write changed extent records. The btrfs run in the measurement shows the effect: block-stat deltas of +73,728 bytes (the journal file) and +208,896 bytes (the btrfs b-tree and metadata writes) for a single message — more than three times the ext4 cost for identical content.7

Layer 5 — Access-time stamps

Reading a file on Linux traditionally updates its atime (last-access timestamp). Reading triggers a write. One commenter in the thread captured the practical consequence: "I've long switched to noatime, probably two decades ago when I found out that even running find results in a massive amount of writes."11 Opening a note to read it can write to your disk.

The standard mitigation is the relatime mount option (the kernel default since Linux 2.6.30) or the more aggressive noatime. Under relatime, atime is only updated if it is older than mtime or ctime, which eliminates most read-induced writes without breaking programs that depend on atime ordering.12


What the format buys

The journald format is expensive to write. That expense is not accidental — it is the price of specific features the format was designed to provide.

XANi, the engineer who opened the issue, states it directly: "the ondisk format is just extremely wasteful and verbose, the journal format was designed with lots of indexing structure in mind but this makes it expensive to write and expensive to read."13

The indexing structure XANi refers to includes: binary search across billions of log entries by time, by PID, by unit, by priority; structured field queries (find all entries from a specific service in the last hour) without a full scan; and cryptographic sealing — journalctl --verify can detect whether a log has been tampered with, because each journal file can be sealed with a key.

These are real capabilities. A plain append log provides none of them. If you need to audit "what did unit X log between 14:00 and 15:00 yesterday," a structured indexed format answers in milliseconds. A grep over a plain text file answers in the time it takes to read the whole file.

The thread makes clear where the tension lives — not in whether those features exist, but in whether the default cost structure is proportionate for the overwhelming majority of workloads. XANi's original report notes "VM doing ~50 IOPS when writing 2 lines of log per second" — a logging rate that should be idle.1 The write amplification is applied uniformly, even to sessions where no one will ever query by PID or verify cryptographic integrity.


Two diagnoses for one measurement

The thread did not converge on a single verdict about cause. Linux kernel contributor Andy Lutomirski (amluto) offered one reading: "But the fundamental conclusion is: the design was wrong. I should not have used mmapped writes. pwrite would have been far better."14 He was reflecting on his own earlier append-log database work, not issuing a verdict on systemd's architecture — but the technical observation is precise. Memory-mapped writes interact with the kernel's page-dirtying and writeback machinery in ways that inflate physical I/O beyond what sequential pwrite calls would produce.

XANi disagreed on the root cause: "mmap'ed files aren't even the problem, most of it is caused by massively bloated format for some goals that vast majority of users don't care about, while not hitting any goals users do care about (quick lookup/search, reasonable write performance)."15

Both parties agree on the measurements. The dispute is which layer bears the most responsibility. That is what a productive post-mortem looks like: stable numbers, multiple defensible framings.

A third finding is more immediately actionable than either diagnosis. ValdikSS discovered that the SyncIntervalSec setting does not do what its name implies: "Oh my, journald writes every line to disk, SyncIntervalSec is only a fdatasync+fsync delay, not a data write delay."16 A longer sync interval does not reduce how much journald writes — it only delays when the OS confirms the write is durable. The write happens at message-arrival time. This is a widespread misreading of the configuration.


The plain-file baseline

The most important figure in the thread is not the journald number — it is the control. ValdikSS ran the same content through a plain file with O_APPEND and explicit fdatasync+fsync flags, ensuring durability equivalent to journald's guarantees. The result: roughly one ext4 block per write, 21 KB total across three appends.8

# Plain-file control: write the same content with durable flush, no structured store
# conv=notrunc,fdatasync,fsync ensures the write is durable — equivalent to journald's guarantee
echo -n "test" | dd of=./control.log conv=notrunc,fdatasync,fsync oflag=append
# → "it's most of the time a single ext4 block for write + 1024 bytes of something"
# → "21 KB written overall" across three appends (ValdikSS, 2026-08-03)

This is not a fair-feature comparison. journald provides indexing, structured queries, and sealing; a plain append file provides none of those. The comparison is not an argument that journald should not exist. It is a measurement of what the structured format's overhead costs at the block layer — and what the alternative baseline looks like.

For note-taking applications, the comparison is directly relevant. A note stored as a plain Markdown file inherits the plain-append cost: one block per write, plus filesystem journal overhead. The architecture of a local-first plain-file store aligns with the control baseline, not with the structured-record overhead. You pay for exactly what you wrote — no indexing tax, no sealing overhead, no copy-on-write amplification unless you chose a CoW filesystem.

The durability properties of a plain file — what happens to a write if power fails mid-operation — are a separate question, covered in the crash-safety piece in this series: The Append-Only Log File That Never Rewrites History.9 The question this piece addresses is purely about write volume: how much does a durable save cost?

Whether a write can be lost entirely — at the application or database layer — is covered in the companion piece: Your Notes Live in a Database That Can Lose a Write.12 The three pieces form a sequence: safety, durability, and cost.


Three settings you can actually change

None of these reduce journald's write amplification. They apply to your own files.

1. Mount options. If your filesystem uses atime (the traditional default on some distributions), every file read updates a timestamp and triggers a metadata write. Switch to relatime (the current kernel default on most Linux systems) or noatime in /etc/fstab. The change eliminates most read-induced writes.

# /etc/fstab — add relatime (or noatime) to your filesystem's options
# Example: ext4 volume with relatime (eliminates most read-induced writes)
UUID=xxxx-xxxx  /  ext4  defaults,relatime  0  1

# Verify the current mount options without rebooting
findmnt -o TARGET,OPTIONS /

2. Filesystem choice. Copy-on-write filesystems (btrfs by default; ZFS) amplify small writes more than non-CoW filesystems (ext4, XFS). The btrfs run in the measurement showed more than three times the ext4 write volume for the same content.7 The chattr +C flag disables CoW per-file on btrfs — the measurement tested this explicitly and still showed the journald format's overhead, confirming that CoW and format size are independent multipliers.

3. Autosave interval — what it does and does not do. Reducing your editor's autosave frequency from 1 second to 10 seconds means your data is at risk for longer; it does not mean you write less. The block write happens when the data reaches the page cache. The fdatasync is when the OS confirms the write survived a power failure. If you are trying to reduce write volume, autosave interval is not the lever. If you are trying to reduce the frequency of durability guarantees, it is — but that is a different tradeoff.


Scale and corroboration

The instrumented figures are one measurement, not a systematic study. ValdikSS is one engineer with a loop device and block-stat counters — not a peer-reviewed paper. A T1 academic citation for this specific workload does not exist in the literature we verified.

Two things lend the numbers weight. First, they were derived from kernel primitives — block-stat counters and cgroup block I/O accounting — with the exact command sequence published in the thread, making them reproducible by anyone with a Linux system. Second, independent observers in the same thread reported consistent scale: one user noted "in just 15 minutes journald had almost 7GB" and "22 minutes … almost 11GB" measured with iotop — user reports rather than instrumented measurements, but consistent with the direction and the order of magnitude.10

The thread drew 179 comments on Hacker News from engineers familiar with block-stat and cgroup counters. No comment disputed the measurement methodology — the disagreements were about root cause and remedy, not about whether the numbers were real.


Frequently Asked Questions

Why does journald use so much disk space? The journald on-disk format is a binary indexed structure designed for structured queries and cryptographic sealing. Each log entry carries metadata fields — PID, UID, timestamps, cursor fields, a data hash — making a 4-byte message encode to roughly 752 bytes before block rounding. Instrumented measurements show at least 55 KB of physical writes per single message on ext4, and over 110 KB on btrfs.2 3 7

How much does saving a file actually write to disk? For a plain file with fdatasync (a durable write), the measured cost is roughly one 4 KB filesystem block plus a small journal entry — around 21 KB across three sequential appends in the instrumented control.8 For a structured logging format like journald, the same content costs at least 55 KB per message on ext4 and over 110 KB on btrfs. The ratio is not a matter of coding quality — it reflects what the two formats are designed to do.

What is write amplification in Linux? Write amplification is the ratio of physical bytes written to disk versus logical bytes written by the application. The causes compose: block rounding (minimum 4 KB per write), filesystem journaling (metadata written before data), structured-record overhead (format metadata multiplied into each entry), and copy-on-write (each write spawns a new block location plus metadata updates). In the systemd thread, the ratio for journald versus a plain append ranges from roughly 55× to over 386× at small message sizes.3 6

Does noatime reduce SSD wear? Yes, for read-heavy workloads. On default atime mounts, reading a file updates a timestamp and causes a metadata write to disk. The noatime mount option eliminates those reads-turned-writes entirely. The relatime option (the current Linux kernel default) achieves most of the benefit: it only updates atime when it is older than mtime or ctime. Practitioners have used noatime for decades specifically because of write-induced wear from directory traversal tools like find.11

What does SyncIntervalSec actually do in journald? SyncIntervalSec controls how frequently journald calls fdatasync to confirm data is durably on disk. It does not control when the data is written to the page cache. The write happens immediately when the message arrives; SyncIntervalSec governs only when journald asks the OS to guarantee the write survived a power failure.16 Increasing this value makes journald less crash-safe, not less write-intensive.

Is the 55 KB figure peer-reviewed? No. It is an instrumented measurement from a named GitHub contributor using kernel block-stat counters, published in an open thread with the exact commands — reproducible by anyone with a Linux system and a loop device. It has not appeared in a peer-reviewed publication. Independent reports in the same thread corroborate the scale at higher log rates.10 This post treats it as a credible engineer measurement, not as an academic finding.

Does this affect my note-taking app? It depends on how your app stores notes. Apps that store notes as plain files pay the plain-file cost: one block per write, plus filesystem journaling. Apps that store notes in a structured database pay that format's overhead, which varies by design. The measurement in this post applies specifically to journald as a worked example of a feature-rich structured format and the write cost it imposes.


A write is never the size of what you typed. The disk sees the block floor, the journal metadata, the structured record, and the copy-on-write tree — each layer multiplying the last. The right architecture for your workload depends on which of those layers you need to pay for.


Plain Markdown files, stored locally on your own device, inherit the plain-append baseline — not the structured-record overhead. mnmnote.com keeps your notes as open files, readable without the app.

Footnotes

  1. XANi (GitHub user), systemd/systemd issue #40262, opened 2026-01-03. https://github.com/systemd/systemd/issues/40262 2

  2. ValdikSS (GitHub user), comment in systemd/systemd issue #40262, posted 2026-08-03. Measurement: one logger -p info test message produces a journal record of "about 752 bytes" (measured with journalctl -o json -a | wc -c). https://github.com/systemd/systemd/issues/40262#issuecomment-5169482357 2 3 4 5

  3. ValdikSS, ibid. "either a single log message or 10 of similar log messages result in at least 55 KB of written data" (ext4 loop device, Compress=no). 2 3 4

  4. Hacker News, item 49290215, submitted 2026-08-13T18:41:01Z. 236 points / 179 comments as of 2026-08-14. https://hn.algolia.com/api/v1/items/49290215

  5. Linux kernel documentation, block/stat.html: "sectors" are "standard UNIX 512-byte sectors, not any device- or filesystem-specific block size." https://docs.kernel.org/block/stat.html

  6. ValdikSS, ibid. "14 log messages resulted in 386 KB physical writes (according to block stat) and 319 KB writes from journald (according to cgroup block stat)." 2

  7. ValdikSS, second comment in systemd/systemd issue #40262, posted 2026-08-03. btrfs chattr +C run: block-stat deltas "+73728" and "+208896" bytes per single message; cgroup counter "+110592 bytes since start." https://github.com/systemd/systemd/issues/40262#issuecomment-5170402308 2 3 4

  8. ValdikSS, ibid. Plain-file control: O_APPEND + conv=notrunc,fdatasync,fsync — "it's most of the time a single ext4 block for write + 1024 bytes of something, much smaller than journald" — "21 KB written overall" across three appends. 2 3

  9. Cross-link: crash-safety and append-only durability — https://blog.mnmnote.com/posts/the-append-only-log-file-that-never-rewrites-history 2

  10. a_glitch_in_the_matrix (GitHub user), comment in systemd/systemd issue #40262, posted 2026-04-07. User report (not instrumented measurement): "in just 15 minutes journald had almost 7GB" / "22 minutes … almost 11GB" (measured with iotop in accumulation mode). https://github.com/systemd/systemd/issues/40262#issuecomment-4202650639 2 3

  11. birdie-github, comment in systemd/systemd issue #40262, posted 2026-08-04: "I've long switched to noatime, probably two decades ago when I found out that even running find results in a massive amount of writes." https://github.com/systemd/systemd/issues/40262#issuecomment-5175162272 2

  12. Cross-link: write durability and the risk of data loss — https://blog.mnmnote.com/posts/your-notes-live-in-a-database-that-can-lose-a-write 2

  13. XANi, comment in systemd/systemd issue #40262, posted 2026-08-03: "the ondisk format is just extremely wasteful and verbose, the journal format was designed with lots of indexing structure in mind but this makes it expensive to write and expensive to read." https://github.com/systemd/systemd/issues/40262#issuecomment-5170643382

  14. Andy Lutomirski (amluto), Linux kernel contributor, comment in systemd/systemd issue #40262, posted 2026-08-13: "But the fundamental conclusion is: the design was wrong. I should not have used mmapped writes. pwrite would have been far better." https://github.com/systemd/systemd/issues/40262#issuecomment-5285702021

  15. XANi, comment in systemd/systemd issue #40262, posted 2026-08-14: "mmap'ed files aren't even the problem, most of it is caused by massively bloated format for some goals that vast majority of users don't care about, while not hitting any goals users do care about (quick lookup/search, reasonable write performance)." https://github.com/systemd/systemd/issues/40262#issuecomment-5288569922

  16. ValdikSS, comment in systemd/systemd issue #40262, posted 2026-08-03: "Oh my, journald writes every line to disk, SyncIntervalSec is only a fdatasync+fsync delay, not a data write delay." https://github.com/systemd/systemd/issues/40262#issuecomment-5170864970 2