Zachary Lili

What fsync actually promises

February 2026·Storage·8 min read

The man page says fsync() transfers all modified in-core data to the storage device. It does not say the data is on stable media, and that gap has undone more than one careful design.

Three layers, three promises

Data written by an application travels through the page cache, into the device's own cache, and finally onto the medium. write() reaches the first. fsync() reaches the second. Only the third survives a power loss, and it is the one the filesystem cannot see on its own.

A device with a volatile write cache will acknowledge the flush before the data is durable. The filesystem trusts that acknowledgement, because it has no way to verify it.

The barrier that is not there

Filesystems rely on a cache flush command to enforce ordering. If a device lies about having executed it, the ordering guarantees the filesystem assumes are simply not in effect, and a crash can leave a structure that was never valid on disk. This is why some drives are known to lose data on power failure despite a filesystem that is careful.

What to do about it

  • Know whether your storage has a volatile cache, and whether it honours flush. On enterprise drives this is documented; on consumer drives it often is not.
  • Batch your syncs. The cost of fsync() is dominated by the flush round-trip; one sync for a group of writes is far cheaper than one each.
  • Do not use fsync() as a substitute for a write barrier between two files. It orders one file's data, not the relationship between two.
  • Test the failure that matters. Pull power, do not just kill the process, and see what you actually get back.
The question is never whether fsync was called. It is whether the thing underneath it told the truth.