I’ve got some interesting/surprising data out of this. Syncthing is currently using a total of 2.5GiB of RSS memory with this connection configuration.
I overestimated the files rows space usage. If I read the output of my manual select correctly the blocklist_hash is 256 bit not 512 bit and SQLite uses a varint for the integers. So the whole files table fitting in less than 2.5GiB with our configuration isn’t odd.
With a common pool (shared between maintenance and the rest of the code) the whole cache_size was used very quickly during the “scanning” state. This most probably means that there are queries doing full table scans outside the maintenance code and it is common (common enough to rapidly fill the cache of all the connections in the pool).
Note : as I write this our huge folder just reached the “Syncing” state. 
The memory usage jumped to around 4GiB now that it is syncing (this is how I spotted the syncing state, I was monitoring the RAM usage).
Another thing : the checkpoints in our branch are working in the syncing state. I just saw the WAL being reduced from 2GiB to 8MiB. As I was writing this it grew to 24MiB before being reduced again to 8MiB.
It’s possible to integrate the maintenance dedicated 1-connection pool in our db_maintenance_performance branch : it is an easy modification and it really uses the cache efficiently (<2.5GiB covering all needs for a 60GiB database isn’t bad).
That said, the main benefit of the various cache_size changes was to help understand the access patterns. I don’t see a large performance boost from it (but our OS disk cache is mostly unused and available for Syncthing to use, it might bring a noticeable boost on systems where Syncthing isn’t the process making most of the disk accesses).
From what I see further gains might come from optimizing how Syncthing accesses the database in the Preparing to Sync and Scanning state.
Based on cache usage, the Scanning state seems to make queries which need full table scans (which may reduce the scan performance) and Preparing to Sync blocks the checkpoints.
Preparing to Sync blocking checkpoints might not have much of an impact in the real world. We were in a very bad state with more than 2 months of lag trying to sync a 30 million files folder. With our current code, the maintenance should not be able to slow the scanning/preparing to sync states enough that it becomes a problem again for us.
Now there’s time to cleanup the code while the syncing progresses. There’s a smaller (~9 million files) folder waiting to sync where we can see the whole process play out again hopefully with code almost ready for a pull.