fsync
Flushes a stream's buffered data and metadata to physical storage.
fsync(resource $stream): bool- Added in PHP 8.1.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$stream | resource | An open file pointer from fopen() or fsockopen(), not yet closed by fclose(). |
Return value
boolReturns true on success or false on failure.
Errors
Returns false on failure; a value that is not a valid open stream raises a TypeError.
Changelog
- PHP 8.1.0Function introduced.
fsync() is the strongest durability guarantee PHP offers for a single file. It flushes PHP's own write buffer, then instructs the operating system to write its page cache for that file — data and metadata such as size and timestamps — down to the storage device, and it does not return until the device says the write landed.
When to reach for it
- Financial records, audit trails, or anything where "we told the user it saved" must survive a power cut.
- The commit point of a write-then-rename sequence: sync the temp file, then rename it over the target.
- Before signalling another process that a file it will read is complete.
What trips people up
It is slow, and deliberately so — a real fsync() costs milliseconds because it waits on hardware. Calling it after every line in a loop can cut throughput by orders of magnitude. Batch your writes and sync at meaningful checkpoints instead.
Do not confuse it with fflush(). fflush() only moves bytes from PHP into the kernel; the data still lives in volatile memory and is lost on a power failure. fsync() already performs that flush, so calling both is pointless.
The big blind spot is directories: PHP cannot fsync() a directory. Syncing a newly created file guarantees its contents, but the directory entry that gives it a name may still be unwritten, so after a crash the file can be missing entirely. Writing to a pre-existing file and renaming into place narrows that window.
Example
When to use it
- Sync a payment ledger entry to disk before returning a success response to the client.
- Complete a write-temp-then-rename deploy so a reader never sees a partially written config file.
- Checkpoint a long-running import every few thousand rows so a crash loses at most one batch.
Frequently asked questions
What is the difference between fflush and fsync?
fflush() moves data from PHP's buffer into the operating system, where it is still only in volatile memory. fsync() goes further and makes the OS write it to the physical device, so it survives a power failure.
Does fsync slow down my script?
Yes, significantly — each call waits on the storage device and typically costs milliseconds. Sync at meaningful checkpoints rather than after every write.
Why can my file still disappear after fsync?
fsync() guarantees the file's contents, but not the parent directory's entry naming it, and PHP cannot sync a directory. Write into an existing file and rename() it over the target to reduce that risk.
More examples
Sync then rename for an atomic publish
Readers see either version 1 or version 2, never a half-written file. Syncing before the rename ensures the new contents are on disk before the name starts pointing at them.
<?php
file_put_contents('config.json', '{"version":1}');
$tmp = 'config.json.tmp';
$fh = fopen($tmp, 'w');
fwrite($fh, '{"version":2}');
fsync($fh); // contents are durable
fclose($fh);
rename($tmp, 'config.json'); // atomic swap
echo file_get_contents('config.json'), "\n";
unlink('config.json');Checkpoint instead of syncing every row
Two syncs cover ten rows, so a crash loses at most one batch of five instead of forcing a device round trip per row.
<?php
$fh = fopen('import.log', 'w');
for ($i = 1; $i <= 10; $i++) {
fwrite($fh, "row $i\n");
if ($i % 5 === 0) {
fsync($fh);
echo "checkpoint at row $i\n";
}
}
fclose($fh);
echo 'total rows: ', count(file('import.log')), "\n";
unlink('import.log');fflush is not durability
After fflush() another process can already read the bytes, which is why the content prints. Only fsync() guarantees they survive a power loss.
<?php
$fh = fopen('demo.txt', 'w');
fwrite($fh, "in the kernel page cache\n");
var_dump(fflush($fh)); // visible to other readers...
echo file_get_contents('demo.txt');
var_dump(fsync($fh)); // ...but only now on the device
fclose($fh);
unlink('demo.txt');
Discussion