A Syncthing and SQLite Gotcha
So, I have this little app, Epoch, that I use to keep a journal. It’s a<br>tiny Rust web app that runs as a systemd service and uses SQLite as<br>the database. I use a desktop and a laptop regularly, and use<br>Syncthing to synchronize them, including Epoch’s database. That way I can<br>use the app on both devices without needing a server to synchronize them, the<br>tradeoff being that I have to make sure the sync is finished before performing<br>any mutations.
But I had this bug. Say I edit today’s entry on the laptop, come home, wait for<br>Syncthing to finish, then I’d open today’s entry on the desktop, and the text<br>would be missing. It’s not that the server is holding a lock on the file and<br>preventing the sync: opening the database with the sqlite3 command line tool<br>shows the new text is there. If I restart the server, Epoch can read the new<br>text.
My mental model was:
The rusqlite Connection object points to the database file. Syncthing<br>swaps the file’s contents from under it. Subsequent queries go to the new<br>file.
Turns out there’s a very important part of POSIX filesystem semantics I was<br>ignorant of. The standard way to replace a file safely (i.e. atomically) is the<br>rename system call:
int rename(const char *old, const char *new);
Which Syncthing uses. This I know. What I didn’t know is: what happens if other<br>processes had open file descriptors pointing to new? Do they see the new<br>contents? No: those processes can keep reading and writing to the old file<br>object, but the file is orphaned in that no path points to it. And once all<br>file descriptors are released, the file becomes inaccessible.
I’m used to thinking of filesystem operations in terms of “this syscall takes a<br>path and gives you a pointer to the file, which you mutate directly”. Whereas<br>rename works at the level of directory entries: it atomically mutates the<br>mapping from pathnames to files but doesn’t touch files at all.
Published<br>23 August, 2026
Previous
Our Servants Will Do That For Us
Next
None
Feel free to email me! I would<br>love to hear from you.
© 2014–2026 Fernando Borretti