Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

devonblzx's avatar

Database Transaction Middleware

So I've been working across a few different languages and frameworks recently and I've found that outside of Laravel, it's actually quite common to have a single database transaction (at least for writes) per request.

When using Doctrine, you'd persist things to the EntityManager but it's rare to see implementations that flush until the full request is completed. So all changes are committed in the same transaction.

In a Go framework I've been working with, they actually have a database transaction middleware that starts a transaction per request, then commits at the end of the request. This seems like an easy way to prevent an inconsistent state in the application, especially with unexpected exceptions.

Has anyone implemented this in Laravel? Any thoughts on this approach?

Implementation seems like it'd be pretty easy especially if the app only has one database. And you could always manually flush (commit and open a new transaction) if the need arises inside your app.

0 likes
3 replies
bobbybouwmann's avatar

Laravel does not come with this by default, but you can easily set it up yourself!

You can find three implementations here: https://gist.github.com/rodrigopedra/a4a91948bd41617a9b1a

Let me know if you need any more examples or explanation ;)

Note: I think the last reply is the best option, because it will fail on all exceptions in the application! However you might want to have a bit more control and then the original gist might be the best option!

devonblzx's avatar

@bobbybouwmann Yeah, I figured implementation would be fairly straightforward, but thanks for the links to the gists on some inspiration. I like the last option too. I'd probably want to implement a service that handles the transaction for me though, especially if I need to manually flush. I see manually flushing as something that may be important when dealing with external transactions, like a Stripe payment. (You wouldn't want to delay the commit after an external payment was already processed).

I'm, however, more interested in how this worked out for anyone that tried it. I'm not sure what effect this has on concurrency and load when wrapping every request in a transaction. Looking for insight into performance and usability concerns and anyone that wants to play devil's advocate to provide arguments against doing this.

bobbybouwmann's avatar

@devonblzx So I might be that devil. Laravel uses active record which is a complete different implementation than Doctrine. Because it's active record, models that are changed but not saved are lost in space. The instance of a model in active record pattern is highly coupled with the single database record. In Doctrine it keeps up a list of changed models and then you can flush it to persist everything to the database. However active record doesn't work like that. Doctrine doesn't know where it's saving the data. It's basically a data mapper that is keeping up with the current changes but doesn't know anything about the database implementations. Two complete opposite solutions.

In general you can use doctrine in Laravel to create this functionality. However I do believe that using this pattern on active record is not the correct way to go. I would either advice you to not use the active record pattern provided by Laravel and use a data mapper pattern like doctrine or use the default behaviour of Laravel!

Let me know if I can help you in any other way.

1 like

Please or to participate in this conversation.