Okay, just to make things a little more complicated:  both autocommit and commit_on_success will only call commit() or rollback() if the transaction is dirty.  This might mean that a transaction that is open and is mostly doing writes will never be committed until something is written.  (Even the transaction middleware tests if the transaction is dirty before calling commit or rollback.)  I don't know if the is_dirty() method will return true if there were reads on the transaction. I'm guessing that it does, since there are warnings in the doc for manual transactions that they need to be committed or rolled back, even if only read.

If all that is true, then the issue with the number and placement of context_managers should wrap the places where transactions get dirty.  If you have wrapped them all at the lower level, then there's no need to do so at a higher level.  Only question is whether there are "holes" in between your lower levels that requires a higher-level wrapper, just in case.