architecture – Should caller of service wrap the service with transaction or service provider should define transaction and commit within

The reason this is done the way it is, and not the way you expect it to be, is to give you control about the related transaction.

Right now, you’re not interested in this update being part of a larger transaction outside of the service, so having to create the transaction seems like something the service could automate for you. But the service has been written to specifically account for you wanting to pass in your own transaction.

If tomorrow you need to update this thing and perform another data mutation in a single transaction (= both pass or none pass), you are able to do so because you are the one who provides the transaction under which the service works. This means that your colleague doesn’t have to revisit their code just because you are adding something to the transaction you manage.

This is a matter of inversion of control and making sure the codebase is change-friendly without incurring more work.


If an analogy helps, your question/idea boils down to:

My local coffeeshop has me bring in my own cup for them to put the coffee in. They should just use plastic/cardboard cups.

While your idea is certainly a viable one, it is not the most consumer-friendly one. Plenty of people want to choose which cup their coffee is made in, because they don’t like/want the default cup that is provided.

You are correct, however, that it is nice if the coffeeshop at least still provides a default cup if you don’t bring your own. However, that decision is up to the coffeeshop.
For example, they may want you to bring your own cup as a point of principle to avoid needless resource usage. If you really like cardboard cups, you can still just go out and get your own cup and bring that to the coffeeshop.

The same is true of your transaction. You’re perfectly able to just create your own transaction and pass it in, and you’re not explicitly required to do more with this transaction than a single call to the service.
If it bothers you that much, just write a wrapper service which automatically opens a transaction, calls the service, and commits the transaction.