A Surgical Approach to Selective Sync: Per-File Toggle with Placeholder Stub

Hi Syncthing Team,

First off, I love the project, I use it every day and couldn’t live without it.

I’m not the first to request selective sync - and to my dismay I’ve seen several previous proposals fizzle out (e.g. #193, #7985, #3940 (there’s a two hyperlink limit LOL).

Those were great suggestions but all kind of worked against SyncThing’s existing functions and would have required substantial work.

I’d like to propose a refined approach to selective sync that builds on previous discussions while addressing some of the architectural and UX concerns that have stalled progress in the past.

Rather than introducing a virtual file system or reworking the sync engine, I’m suggesting surgical per-file “optional” toggle that determines whether a file should be downloaded to a given device.

Here’s what I’m thinking, and I’d love to get this group’s input on feasibility:

If the toggle is enabled, the file syncs as usual.

If disabled, the device

  • Skips the actual file transfer.

  • Writes a placeholder stub (either empty or metadata-only).

  • Marks the file as “synced” locally to avoid repeated attempts.

This preserves folder structure and sync state while giving users control over what gets downloaded.

Past proposals often assumed:

  • A need for full metadata indexing across devices.

  • A virtual file system layer (e.g. SAF on Android or FUSE on Linux).

  • Complex hydration/dehydration logic across platforms.

This proposal avoids those pitfalls by keeping the opt-out decision local to the device, by using a placeholder file to represent skipped content and respecting BEP protocol expectations without disrupting sync logic.

Devices that opt out of syncing a file do not advertise that decision. Other devices continue syncing normally. No metadata leakage occurs, and the opting-out device is treated as “up to date.”

First-Time Setup Flow (Selective Sync Mode)

When a new user installs Syncthing and adds a shared folder, they’re prompted with a simple question:

“Would you like to download all files now, or choose files selectively?”

If they choose selective sync, Syncthing proceeds to sync the full folder structure and metadata—filenames, sizes, timestamps, etc.—but does not download the actual file contents. Instead, each file is internally marked as “declined,” meaning it’s known to the system but not yet hydrated.

This gives the user immediate visibility into the folder without consuming disk space or bandwidth. It also sets the stage for on-demand downloading via the Web UI.

New Web UI Experience (File-Level Control) component required:

• Adding a file browser panel to the Web UI, capable of listing remote files before they’re synced.

• Surfacing per-file metadata (name, size, timestamp) from the sync engine.

• Tracking and displaying the download status of each file.

• Allowing user interaction to trigger hydration (i.e., download on demand).

In the Web UI, the user sees the full folder tree as usual. But files that haven’t been downloaded yet are visually distinct—perhaps grayed out, tagged with a “placeholder” icon, or listed with a status like “Not downloaded.”

Clicking on a file gives the user the option to:

  • Download now (hydrating the file)
  • Keep as placeholder

This interaction updates the internal toggle for that file. If the user chooses to download, Syncthing begins syncing the file normally. If they leave it declined, the placeholder remains.

No .stignore rules are touched. The existing system handles everything through internal flags and sync logic as is.

Handling Opted-Out Files (Placeholder Strategy)

Files marked as declined are represented locally by placeholder stubs. These could be:

  • Empty files with the same name
  • Metadata-only files (e.g. JSON or .syncthing-placeholder extensions)
  • Read-only or hidden files to prevent accidental modification

These placeholders serve two purposes:

  1. They preserve the folder structure and give users visibility into what’s available.
  2. They prevent Syncthing from repeatedly attempting to sync the file, since the system treats them as “intentionally declined.”

Importantly, these placeholders are local-only. Other devices don’t know or care that this device has declined the file. From the network’s perspective, the device is “up to date.”

This approach keeps the UX clean, avoids OS-specific dependencies, and respects Syncthing’s sync model. It also opens the door to future features like “sync on access” or “sync when connected to power/Wi-Fi.”

At least that’s the idea. Copilot helped me with this. Whatever appearance there might be of programming skills is purley machine generated. The fan and appreciation part is real.

1 Like

You might like GitHub - burkemw3/syncthingfuse

Honestly, the .stignore file approach is not bad–not sure what you have against it. As a user I prefer it over creating empty or JSON filled placeholder files.

I’m thinking of making a GUI for Syncthing selective sync using filestash–but there are one or two technical limitations which lead to unusual situations to users who treat Syncthing like a non-mesh system. One thing that would help with this would be finer-grained control along the lines of ignoreDelete (for other types of file operations like modify and create). But I’ve read that the main Syncthing devs regret adding ignoreDelete.

Synctrain implements selective sync through careful editing of .stignore. The implementation is described here: sushitrain/README.md at main · pixelspark/sushitrain · GitHub

From my experience: this will only ever work in practice with a good UI.

As for placeholder files: I chose not to do that as it may give the user the impression of a file being there while it is not. It should however be possible to do this with the ignore-based approach (just make sure placeholder files are always ignored, and periodically walk the global file tree to create any missing placeholders)

2 Likes

This requires a very platform specific implementation.

How does it work in a Linux shell environment?

What if you delete all the zero byte files? Do the deletes propagate?

A few useful platform specific solutions exist already and if that covers your use case then go for it.

Something inside the Webgui is really the only way to make the solution platform independent. (Requiring some kind of directory tree browser that browses the global state and the local file system.). (maybe something can be built off the versioning restore code?)