Is Syncthing v2 with very large folders possible ?

That explains the size. We’re currently storing the relative path per file. For a usage scenario like yours this ends up with a lot of bloat in the files table.

The question is if it would speed things up or would end up being worse if we reduce the size by e.g pulling the path prefixes into a separate table.

Hopefully calmhs patch can help with the other big chuck of the database: blocks

But ultimately I think our scaling problem might be also cache related. We switched back to the default page cache size in v2.0.7. It was a good decision to get the memory usage of our read connections under control, but I fear that our writer connections suffer in cases like this.

My 2 cents on the last message,

My setup is ~30 folders, ~5 peers, ~1M files, ~400GB now.

I was trying setup with different a) MaxConnections, b) Cache (per connection, that’s why a), c) IdleTime to speedup DB close to prune cache earlier, when not needed.

My current findings are:

  1. safe min MaxConnections seems to be like around 6. That’s for my setup with scale given above. With 2, 3, 4, it deadlocks sometimes. With 6 never seen as of now. But not sure. Maybe 8 is a better shot here.

  2. cacheSize I can live with, given this setup, is 32MB per connection. It mostly trades memory for CPU/latency to go to OS page cache however. Can speed up things, but not a game changer. But if you see CPU all saturated, increasing may be helpful, but not my case.

  3. MaxIdleTime 10 seconds runs fine and you can have A LOT larger cache with this, but is causing this bug more often than without (like per default): Consider better reaction to SQLITE_BUSY · Issue #10529 · syncthing/syncthing · GitHub - just because auto-closing DBs is doing WAL commits automatically and thus more often. If this gets fixed by just retrying, this can save on better cache management.

(stats based on aproximatly 3 month of tests on all my live systems)

Posted in the Files are locally modified when logs says they are unchanged topic but it is probably relevant here too.

The number of Out of Sync and locally changed Items seems to go down slowly while the folder is in Preparing to Sync state.

Zabbix monitors the value of “needFiles” from Syncthing API which isn’t the same as these two apparently but is in the same ballpark, currently :

  • Out of Sync : 16 692 125,
  • Locally Changed : 16 522 253,
  • needFiles in JSON from API : 16 037 923.

Based on the last 24h it will probably take approximately 6 months for these values to reach 0.

More information in case it can be helpful to pinpoint a bottleneck. You’ll find the “needFiles“ value history over the last 7 days as reported by the API to our Zabbix server. Syncthing was restarted 6 days and 21 hours before the generated image (the gap in the graph is due to the API not being available for some time after the restart).

For each of the 7 decrease periods in the needFiles value on this graph I can find an initial sharp load increase that doesn’t last long (less than an hour which is the data’s history resolution). There are both sharp increases of IO wait and actual CPU work at these times but the history data isn’t precise enough to make sure that they overlap or don’t.

That said I don’t think they happen at the same time given how the system behaved when I looked at it though htop (and I look quite often…).

Another food for thought : the 2 other devices syncing this folder (the send-only and the other receive-only) both report that the v2.0.10 device is currently “Syncing (48%, 9.54TiB)”.

9.54TiB is the sum of the out of Sync Items of the two folders : 7.79TiB for this folder and 1.74TiB for the other one.

(The other one is currently “Waiting to Sync” as only one folder can do IO intensive work at a time.)

It seems most of the work done is resolving out of sync items that shouldn’t exist as the 3 devices report the same Global State for the folder (sometimes the v2.0.10 device lags a bit but always catch up). So the v2.0.10 device should already know that almost all of the files are already synced having finished a full scan of the folder. I’m not sure what needs to be processed.

There’s not much network activity either. Since the restart almost 7 days ago the total download is 2.15GiB and the total upload is 1.69GiB.

Can you decrease the scrape interval to something like a minute for a few weeks to collect more granular data? (Perhaps just the syncthing and cpu/disk usage data)

Actually there is more granular history data than I thought. It seems Zabbix chooses to switch to trends data when rendering the graphs if history data is too fine-grained for the period. If I zoom on shorter 2-days periods I get the history data points (for Zabbix related values every 5 minutes).

The IO wait spikes happens at the very start of the decreases of needFiles, sometimes even before the graph for needFiles shows a decrease it reaches 45% which is about 5 processes waiting for IO. The iowait decreases after about 30 minutes but remains around ~10% which means that although there is work done there’s the equivalent of about one process waiting for IO during the whole period during which needFiles decreases.

I changed the period to collect more fine-grained data about Syncthing (every 1mn instead of 5mn) but I don’t think it will help much now that I can see that the IO wait spikes last about 30 minutes.

One possibility of these “doing something” / “doing nothing” cycles is internal maintenance which is each 8 hours by default. It seems that timespans of “doing something” are almost exactly these 8 hours, and then after, they are interrupted by “doing nothing” - this is the time when maintenance is effective.

Maybe it is not this case and I am interpreting this wrong, but consider it - this was my case at least. Message on the solution is above - disable it or at lease make it less frequent.

UPD: 2.0.14 released where tuning it is available without hacks.

@gyver would you mind capturing logs with db debugging active?

Actions → Logs → Debugging Facilities → db

Not sure if this is tied to your problems, but a thing we should improve.

If you mean “db/sqlite” I just changed its log level to debug but for now the last message is the log level change :

2026-02-03 18:10:28 INF Changed package log level (package=db/sqlite level=DEBUG log.pkg=slogutil)

I’ll report when I see something.

I’m mostly interested in the time spent for the db maintenance.

You might be interested by this message too :

2026-02-03 17:23:28 INF GC was interrupted due to exceeding time limit (processed=6 runtime=5m19.649458056s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocklists rows=28498961 chunks=284 log.pkg=db/sqlite)

This is on the affected folder and happens regularly with groups of two messages separated by approximately 3 hours happening at roughly 1-day intervals :

2026-01-31 21:09:32 INF GC was interrupted due to exceeding time limit (processed=7 runtime=5m32.485188706s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocklists rows=28480312 chunks=284 log.pkg=db/sqlite)
2026-02-01 00:33:44 INF GC was interrupted due to exceeding time limit (processed=1 runtime=11m32.559689506s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocks rows=126605643 chunks=1266 log.pkg=db/sqlite)
2026-02-01 18:20:38 INF GC was interrupted due to exceeding time limit (processed=7 runtime=5m43.474690066s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocklists rows=28481232 chunks=284 log.pkg=db/sqlite)
2026-02-01 21:25:07 INF GC was interrupted due to exceeding time limit (processed=1 runtime=11m4.686691217s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocks rows=126605643 chunks=1266 log.pkg=db/sqlite)
2026-02-02 20:19:18 INF GC was interrupted due to exceeding time limit (processed=6 runtime=5m31.391500503s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocklists rows=28483607 chunks=284 log.pkg=db/sqlite)
2026-02-02 23:13:50 INF GC was interrupted due to exceeding time limit (processed=1 runtime=10m46.316504909s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocks rows=126605643 chunks=1266 log.pkg=db/sqlite)

As you’ve got some monitoring in place, could you keep an eye on the WAL sizes?

Would it be worth it to add support for postgresql and outsource the database trouble to a more qualified secondary process? Seems like that should be relatively straightforward if you wanted to go fish that path.

1 Like

Adding postgres support would solve a lot of headaches as it scales better at a certain point.

That said, I still think that the GC handling is a low hanging fruit that can be optimized. Will that magically solve the performance problems in this case? Maybe not, but we would push the boundaries of a working sqlite setup a bit further.

1 Like

Bumping the cache size of our writer connection is the other low hanging fruit IMHO. We could do that on the fly using PRAGMA cache_size. Raise the cache size after acquiring the connection and lower it back to default when we release it.

1 Like

Here are some logs from db/sqlite since last time :

2026-02-03 22:14:07 DBG GC query result (processed=0 runtime=11m21.33402176s result=rows=0 folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocks rows=126605643 chunks=1266 log.pkg=db/sqlite log.src.file=db_service.go log.src.line=276)
2026-02-03 22:14:07 INF GC was interrupted due to exceeding time limit (processed=1 runtime=11m21.351684512s folder=xxxxx-xxxxx fdb=folder.0002-qioaq2fp.db table=blocks rows=126605643 chunks=1266 log.pkg=db/sqlite log.src.file=db_service.go log.src.line=256)
2026-02-04 06:42:05 DBG Skipping unnecessary GC (folder=yyyyy-yyyyy fdb=folder.0003-rr3hhgw2.db log.pkg=db/sqlite log.src.file=db_service.go log.src.line=115)
2026-02-04 06:42:05 DBG Periodic done in (t1=16h47m26.963003274s t0t1=65.534µs log.pkg=db/sqlite log.src.file=db_service.go log.src.line=93)
2026-02-04 06:42:05 DBG Next periodic run due (after=8h0m0s log.pkg=db/sqlite log.src.file=db_service.go log.src.line=83)
2026-02-04 06:43:52 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13092 updatepoints=257570 res=1 modified=7522936 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:44:06 DBG Checkpoint result (db=folder.0003-rr3hhgw2.db checkpointscount=22 updatepoints=269277 res=1 modified=3911 moved=764 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:45:40 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13102 updatepoints=272395 res=1 modified=7531100 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:47:07 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13112 updatepoints=296486 res=1 modified=7539003 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:48:05 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13122 updatepoints=293989 res=1 modified=7546353 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:48:51 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13132 updatepoints=257587 res=1 modified=7552460 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:49:39 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13142 updatepoints=281856 res=1 modified=7559122 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:50:44 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13152 updatepoints=348136 res=1 modified=7565435 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:51:12 DBG Checkpoint result (db=folder.0003-rr3hhgw2.db checkpointscount=32 updatepoints=251704 res=1 modified=14813 moved=764 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:51:28 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13162 updatepoints=280124 res=1 modified=7570558 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:52:26 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13172 updatepoints=263054 res=1 modified=7578295 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:53:13 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13182 updatepoints=327653 res=1 modified=7586900 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:53:42 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13192 updatepoints=262591 res=1 modified=7593262 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:53:57 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13202 updatepoints=291607 res=1 modified=7598355 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:54:10 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13212 updatepoints=255106 res=1 modified=7603209 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 06:54:49 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13222 updatepoints=251806 res=1 modified=7608553 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:07:00 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13232 updatepoints=251905 res=1 modified=7615928 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:14:48 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13242 updatepoints=253780 res=1 modified=7623135 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:18:56 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13252 updatepoints=253526 res=1 modified=7632929 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:27:34 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13262 updatepoints=254791 res=1 modified=7640204 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:35:07 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13272 updatepoints=251450 res=1 modified=7646794 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:41:12 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13282 updatepoints=250026 res=1 modified=7654710 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 07:49:17 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13292 updatepoints=255859 res=1 modified=7661850 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:04:31 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13302 updatepoints=252032 res=1 modified=7669344 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:06:58 DBG Checkpoint result (db=folder.0003-rr3hhgw2.db checkpointscount=42 updatepoints=250009 res=0 modified=443 moved=443 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:14:15 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13312 updatepoints=255500 res=1 modified=7677665 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:25:35 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13322 updatepoints=254735 res=1 modified=7685731 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:36:02 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13332 updatepoints=253726 res=1 modified=7694299 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:41:32 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13342 updatepoints=254028 res=1 modified=7700637 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:46:41 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13352 updatepoints=251359 res=1 modified=7709423 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 08:59:31 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13362 updatepoints=253679 res=1 modified=7717143 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:18:32 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13372 updatepoints=255929 res=1 modified=7723602 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:28:32 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13382 updatepoints=252071 res=1 modified=7731207 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:35:28 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13392 updatepoints=255880 res=1 modified=7739660 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:38:20 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13402 updatepoints=251925 res=1 modified=7748583 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:41:51 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13412 updatepoints=253312 res=1 modified=7756304 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:44:56 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13422 updatepoints=251711 res=1 modified=7763804 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:47:38 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13432 updatepoints=253738 res=1 modified=7771027 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:52:12 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13442 updatepoints=251840 res=1 modified=7779491 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:55:50 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13452 updatepoints=253710 res=1 modified=7787232 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 09:59:24 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13462 updatepoints=254542 res=1 modified=7795804 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 10:01:47 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13472 updatepoints=254075 res=1 modified=7804335 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 10:04:34 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13482 updatepoints=250824 res=1 modified=7812282 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 10:07:39 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13492 updatepoints=250087 res=1 modified=7819712 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)
2026-02-04 10:16:10 DBG Checkpoint result (db=folder.0002-qioaq2fp.db checkpointscount=13502 updatepoints=252896 res=1 modified=7825886 moved=790 log.pkg=db/sqlite log.type=folderdb log.src.file=folderdb_update.go log.src.line=552)

1 Like

Possible but a bit convoluted : the user zabbix doesn’t have read access to the individual files currently (I’d have to make a specific configuration to get the file size using sudo).

That said the .config/syncthing has its own dedicated filesystem and not much changes currently except the WAL size corresponding to the folder in the “Preparing to Sync” state. So I can have an estimation of the evolution of the WAL size by looking at the filesystem used space which was easy to add today.

Wait…wasn’t that database somewhere around 50GB?