I Made Billing Invisible. Now My Developers Ship Paid Features Without Writing a Single Line of Payment Code.

I have a confession.
I hate payment integrations.
Every SaaS developer knows the drill. You build a feature. It works. Users love it. Then someone says, "Great, now make it paid." Suddenly you are drowning in Stripe webhooks, idempotency keys, race conditions between UI state and payment confirmation, and the existential dread of accidentally charging someone twice.
What if the feature developer never had to think about payments at all?
That is exactly what I built for vibe.oakoliver.com. A middleware called billingGuard sits between the client and every paid API endpoint. When a user triggers a paid action, the middleware intercepts the request, pushes an approval event via Server-Sent Events, and the client auto-renders a payment confirmation modal. The user approves. Credits are deducted. The original API call proceeds.
The developer building the feature never writes a line of payment code.
I – Payment Code Is a Cancer
I do not mean that hyperbolically. Payment logic metastasizes throughout your codebase.
Consider what happens in a typical SaaS when you want to charge for an API call.
The frontend needs to check if the user has enough credits before enabling the button. The button handler needs to open a confirmation modal. The modal needs to show the cost, current balance, and maybe a top-up link. On confirmation, the frontend deducts credits optimistically. The API call includes a payment intent or credit deduction. The backend validates the balance, deducts credits, and processes the action. If the action fails, credits need to be refunded. The frontend needs to sync the new balance.
That is eight touchpoints across frontend and backend for a single paid action. Now multiply by every paid feature in your app. Every developer on your team needs to understand the payment flow. Every code review needs to check for billing edge cases.
The billingGuard pattern reduces this to zero touchpoints per feature. The middleware handles everything.
II – How Invisible Billing Actually Works
The system has three moving parts.
First: a persistent SSE connection. Every authenticated user has an EventSource connected to a billing events endpoint. This connection stays open for the user's entire session and handles all billing events across the entire application.
Second: the billingGuard middleware. It wraps any API route that requires credit deduction. When a request hits a guarded route, the middleware checks the user's balance, creates a pending approval record, pushes an approval event through the SSE channel, and then — this is the critical part — suspends the original HTTP request.
The request is not rejected. It is not redirected. It is held open with an await on a Promise that will only resolve when the user approves or rejects.
Third: the approval cycle. The SSE event reaches the browser. A global billing provider component — wrapping the entire React app — receives the event and auto-renders a payment confirmation modal. The user sees the cost, their current balance, their balance after deduction, and a countdown timer. They click approve. The browser POSTs to an approval endpoint. That endpoint resolves the Promise that the middleware has been awaiting. Credits are deducted. The original API call proceeds.
From the user's perspective, they clicked "Generate Report," saw a quick confirmation, tapped approve, and the report appeared. They never navigated to a payment page. They never entered card details. The billing was invisible.
III – The Suspended Request: JavaScript's Event Loop as a Payment Queue
The most architecturally interesting part of this system is what happens to the original API request while it waits for approval.
When the middleware intercepts a paid route, it creates a new Promise and stores the resolve and reject functions in an in-memory Map, keyed by a unique approval ID. It pushes the approval event via SSE. And then it awaits the Promise.
The HTTP request is literally suspended. The Elysia route handler has not executed yet. The response has not been sent. The connection is open, waiting.
Meanwhile, on a completely different HTTP request — the POST to the approval endpoint — the server looks up the pending approval by ID, verifies the requesting user matches the original user, and calls resolve on the stored Promise.
The original request unblocks. Credits are deducted atomically. The settlement event is pushed via SSE. The route handler finally executes. The response flows back to the client.
This is concurrency coordination through Promises. No external queue. No Redis pub/sub. No polling. Just JavaScript's event loop mediating between two HTTP requests through a shared in-memory Map.
If the user does not approve within sixty seconds, the timeout fires, the Promise rejects, and the original request returns a 408 Request Timeout. No credits deducted. No harm done.
IV – Why Credits, Not Direct Stripe Charges
You might wonder why the system uses a credit model instead of charging the user's card directly for each action.
Latency. Stripe payment intents take one to three seconds to confirm. For a quick API action — generate a report, run an analysis — that is an eternity. Credit deduction is a database update. Sub-millisecond.
Predictability. Users know exactly how many credits they have. There are no surprises on their credit card statement. They top up when they want, and every action shows the credit cost upfront in the approval modal.
Failed payment isolation. If Stripe is down or a card declines, it only affects the top-up flow. It never blocks an in-app action. The user pre-purchased credits, so the value exchange already happened.
Simpler refunds. Refunding credits is a database update. Refunding a Stripe charge involves webhooks, disputes, and potential chargeback fees.
The credit deduction uses optimistic locking to prevent double-deduction. The database update includes a WHERE clause that checks the balance is greater than or equal to the cost. If two concurrent requests try to deduct from the same user, only one succeeds — the other's update matches zero rows because the balance dropped below the required amount. No explicit database locks needed.
V – The Auto-Rendering Modal That Feature Developers Never Import
Here is the part that makes the pattern truly invisible.
A BillingProvider component wraps the entire React application. It manages the SSE connection and listens for billing events on a single channel. When an approval_required event arrives, the provider automatically renders a PaymentApprovalModal.
No feature developer needs to import this modal. They do not wire it up. They do not pass it props. It appears whenever the SSE channel delivers an approval event, completely decoupled from feature code.
The modal shows the action description, the credit cost, the current balance, the balance after deduction, and a countdown timer matching the server-side timeout. Approve and reject buttons POST to the respective endpoints.
When the approval_settled event arrives, the modal closes, the balance updates, and the original action's response arrives — all within milliseconds of each other.
From the user's experience, it is seamless. From the developer's experience, it does not exist.
VI – What a Feature Developer Actually Writes
This is the beautiful part.
A developer building a new paid feature adds a middleware configuration to their route. Three parameters: cost in credits, a human-readable description for the modal, and an optional flag for automatic refund on failure.
That is it. Three lines of configuration.
No modal code. No balance checking. No credit deduction logic. No error handling for insufficient funds. No refund logic if the report generation fails — the refund flag handles that automatically.
The developer focuses entirely on the feature. The middleware handles the money.
VII – Automatic Refunds When Actions Fail
When the refund-on-failure flag is set and the route handler throws an error after credits have been deducted, the billingGuard automatically refunds the credits.
The credits are restored. A balance_updated event is pushed via SSE with a reason explaining the refund. The user sees: "Something went wrong generating your report. Your credits have been refunded."
They did not lose money. And the developer did not write a single line of refund logic.
This is important because it changes the risk calculus for developers. They do not need to worry about "what if my feature fails after the user paid?" The middleware guarantees the user's money is safe. This means developers are more willing to build and ship paid features, because the financial risk is handled at the platform level.
VIII – Every Edge Case I Thought Of (And Some I Did Not)
What if the user closes the tab before approving? The approval times out after sixty seconds. The original request returns a timeout response. No credits deducted.
What if the user has two tabs open? Both tabs receive the approval_required SSE event. Both show the modal. The first tab to POST the approval wins. The second tab's modal closes when the settlement event arrives. The pending approvals Map ensures the approval resolves only once.
What if the server restarts with pending approvals? The in-memory Map is lost. The suspended HTTP requests fail with a connection reset. The client retries the original action, triggering a new approval flow. No credits were deducted — deduction happens after approval — so nothing is lost.
What if the balance changes between the approval request and actual deduction? The optimistic locking catches this. If the balance dropped below the required amount between the approval event and the deduction query, the update matches zero rows, the deduction fails, and the user gets an insufficient balance response.
What about concurrent paid actions? Each action gets its own approval ID and its own Promise. The client queues multiple approval modals, though in practice only one is shown at a time. Each deduction is independently locked at the database level.
If you are building a SaaS with per-action billing, or if payment integration is slowing down your team's ability to ship features, I have been refining this pattern across production systems. Book a session at mentoring.oakoliver.com and we will design a billing architecture that gets out of your developers' way. Or see the pattern in action at vibe.oakoliver.com.
IX – Why SSE Is the Right Tool (Again)
The approval needs to appear within milliseconds of the API call. Polling would work but wastes bandwidth and adds latency. WebSockets would add complexity for no benefit — we only need server-to-client push.
SSE is the perfect fit. Persistent connection. Instant delivery. Automatic reconnection. Works through Traefik without configuration changes.
The billing event channel stays open for the user's entire session and handles all billing events across the entire app. One connection, all billing events, all paid features.
X – Middleware as a Business Model
The billingGuard is not just an engineering convenience. It is a strategic architecture decision.
Velocity. New paid features ship in hours, not days. No billing integration work means faster time to market.
Consistency. Every paid action looks and feels the same to the user. Same modal. Same approval flow. Same balance update animation. This builds trust.
Auditability. Every credit deduction goes through the same code path. One place to add logging, fraud detection, rate limiting, or compliance checks.
Experimentation. Want to A/B test pricing? Change the cost parameter. Want to offer a free trial of a paid feature? Conditionally skip the guard. Want to add bulk discounts? Modify the middleware. Feature code stays untouched.
The billingGuard transformed billing from a per-feature burden into a platform capability. Feature developers build features. The platform handles money.
The best payment code is the code your developers never have to write.
XI – The Pattern in Five Pieces
If you are building a SaaS with per-action billing, here is what you need.
A credit system with atomic deduction using optimistic locking. A persistent SSE channel per authenticated user. A middleware that intercepts paid routes, suspends requests, and pushes approval events. A global UI provider that listens to the SSE channel and auto-renders approval modals. And approval endpoints that resolve the suspended Promises.
The entire system is about 400 lines. It eliminates thousands of lines of payment code that would otherwise be scattered across your codebase.
What billing patterns have you found effective in your SaaS — and how much of your developers' time is spent on payment logic instead of features?
– Antonio