As part of building my own backend tech for my Bubble apps, I recently upgraded a client’s booking app’s booking infrastructure. The purpose was to ensure transactional updates to an event’s availability. Transactional updates ensure that the system handles write requests in order. This maintains fairness to my users. First come, first serve.
The original booking system relied only on Bubble’s workflows. It has done a decent job the last 13 months. It did come with some flaws:
- Bubble doesn’t have a true transactional backend or any native transactional features so I had to bootstrap a complex system consisting of a booking lists, reservation lists, custom events and some client-side tricks to ensure that my users are properly notified if their booking went through or otherwise.
- Because this complex web of workflows relied on Bubble’s backend, the WU cost is very high, reaching hundreds of thousands for a single event.
- Speed was never an issue because I kept my workflows as synchronous as I could, the biggest issue was accuracy. There were a lot of bookings that got stuck on the reservation list, either because a record wasn’t deleted when it should have. This resulted in discrepancies which affected my client’s events a little bit.
The solution was to look for a native transactional database that I could quickly add into my Bubble app without making many changes to the booking app itself. I eventually settled on Cloudflare’s Durable Objects (DO). Reasons being:
- Native transactional writes. I don’t have to write one from scratch, Cloudflare handles all of that.
- I can write the code in one Cloudflare worker and that worker will serve as an endpoint (for API calls), and when bound to a DO, serve as a state (instead of traditional database) that will keep the booking details.
- Cloudflare Workers always run on the edge (It means your code runs close to the user, not far away in a single data center — which makes it way faster and more responsive) so I can be assured that my users are always served fast and reliably.
- Barely any warmup time between gaps of API calls.
Fortunately setting things up in Cloudflare and making the API calls from Bubble is easy, the bulk of the work is writing and troubleshooting the code for the Worker. With AI I got things up and running in a couple of hours. Here’s a brief look at the booking system:
- UI, user and event and booking records are on Bubble
- Availability information (including booking UIDs) is stored in the DO.
- The DO does the availability validation before updating it’s state.
- When the user books an event, I use the API connector to call the DO, it gets validated (or not) and then receives a success or failure response.
- The Bubble frontend responds appropriately and sends an email (through Postmark) for successful booking.
The client currently has an event up for booking and here are the benefits that I have noticed:
- Lower WU costs: I cut down the amount of workflows for each booking made. Bubble handles tracking the event, booking and calling Postmark to email the confirmation of a booking.
- Accurate updates of availability: They are still cached since I decided not to keep them fresh. What was important is that availability validation is accurate when a user decides to make a booking.
- Much cheaper $ costs: WU $ costs are more than run time $ costs of a Cloudflare Worker & DO.
- Logging and error tracking: I can add my own logging on top of Cloudflare’s analytics.
This is not a diss on Bubble because as mentioned it has served my clients and I well the last many months. Neither do I intend to shift away from Bubble. Bubble enables me to function as a solo dev in my current projects and also in the larger scale projects in my pipeline. Building my own backend tech to support my Bubble apps is just a means to keep costs low while staying ambitious to pursue larger projects, and at the same time learning more about programming.
My primary intention in sharing is correcting the idea that just because you have to attach external services to your Bubble app, then it means that Bubble is not good for production at scale.
In a perfect world I can rely only on Bubble features and functions for my entire tech stack but that has never made sense when it comes to web development at scale. Even more so when you need to keep costs lean. Developers use different services in their tech stack all the time.