Hmm... when synchronous_transfer is set to data_flush, IMO the intuitive behaviors are
(1) synchronous_commit = on A data flush should wait for the corresponding WAL to be flushed in the standby
(2) synchronous_commit = remote_write A data flush should wait for the corresponding WAL to be written to OS in the standby.
(3) synchronous_commit = local (4) synchronous_commit = off A data flush should wait for the corresponding WAL to be written locally in the master.
I thought synchronous_commit and synchronous_transfer are kind of orthogonal to each other. synchronous_commit only controls whether and how to wait for the standby only when a transaction commits. synchronous_transfer OTOH tells how to interpret the standby listed in synchronous_standbys parameter. If set to "commit" then they are synchronous standbys (like today). If set to "data_flush", they are asynchronous failback safe standby and if set to "all" then they are synchronous failback safe standbys. Well, its confusing :-(
So IMHO in the current state of things, the synchronous_transfer GUC can not be changed at a session/transaction level since all backends, including background workers must honor the settings to guarantee failback safety. synchronous_commit still works the same way, but is ignored if synchronous_transfer is set to "data_flush" because that effectively tells us that the standbys listed under synchronous_standbys are really *async* standbys with failback safety.