I've been building infrastructure for B2B SaaS and kept running into the same problem:
A SaaS can look "finished" while some of the most important security boundaries haven't actually been tested.
So I put together a free production-readiness checklist focused on the things that are easy to miss:
The part I care most about is testing the failure cases.
For example:
Can User A access User B's data if they know the resource ID?
Can a revoked API key still make requests?
Can the same Stripe webhook safely be processed twice?
Can a member call an admin endpoint directly?
I put the checklist and a deeper tenant-isolation guide here:
https://github.com/wendelandrady/production-saas-readiness
I'm mainly looking for feedback from people who have actually shipped multi-tenant SaaS.
What did you discover too late?
What would you add to the checklist?
The revoked API-key test raises another failure case I’d add: does revocation still hold if the action has already moved beyond the component checking the key?
A system can correctly reject stale authority locally while a queued worker or downstream provider is still acting on an earlier grant.
I’d test three things separately: authority at the point of consequence, whether revocation actually reached that boundary, and what evidence proves the downstream action did or didn’t occur.
Otherwise “revoked” can become a control-state claim rather than evidence of what actually happened.
Good distinction — "the key check passed" and "the action didn't happen" aren't the same claim, and conflating them is exactly how revocation testing gives false confidence.
I'd add a fourth thing to test alongside your three: time-to-effect under load. A revoked key rejecting requests instantly in a quiet system can still have a real propagation delay once you've got queued workers or retried webhooks under load — so "revoked" needs a tested upper bound, not just a pass/fail.
This is actually one of the harder things to get right with async Stripe webhook handling too — a webhook retry landing after a key's already been revoked but before the revocation propagated to the worker's cache is a real failure mode, not a theoretical one.
(Side note — I turned a lot of this production-readiness thinking into an actual foundation and launched it on PH today, if you're curious: https://www.producthunt.com/products/b2b-saas-os?launch=b2b-saas-os)
That fourth test is important. A revocation timestamp by itself doesn’t prove when enforcement actually became effective.
I’d probably separate “revocation issued” from “revocation effective at the consequence boundary” for exactly the propagation/cache problem you describe.
Under load, that gap becomes measurable rather than theoretical. And if an action lands inside it, I wouldn’t want an audit trail retrospectively describing it as simply “revoked” or “blocked.”
The webhook example makes the problem even sharper because now you have authority state, propagation state and an already-moving asynchronous action potentially disagreeing at the same time.
I think the upper-bound idea is particularly useful: if a system claims revocation, it should be able to establish how long stale authority can remain executable — or explicitly admit that it cannot.
And congrats on the launch. This is exactly the kind of production boundary that tends to disappear behind a green check until something consequential happens.
That distinction — "issued" vs "effective at the consequence boundary" — is the right frame, and it's more actionable than mine. "Revoked" as a single audit-log state is genuinely misleading if you can't also say how long the stale-authority window was.
Practically, I think this pushes toward logging two timestamps instead of one: revocation_issued_at and something like last_enforcement_gap_observed, even if that second number starts as a system-wide upper bound rather than a per-action guarantee. Better to log "we cannot prove enforcement was instant" than to imply it was.
Honestly, this is a good example of the gap between "we have audit logs" and "our audit logs make claims we've actually verified." Worth being upfront about — I don't think what I've built proves an instant enforcement boundary either, just a reasonable one. That's a fair thing for anyone evaluating infra like this to push on.
Appreciate you pushing on this — this is the kind of thread that's more useful than most of what happens on launch day.
Exactly — and I think your last point is the important one.
I like recording the enforcement-gap measurement, but I’d be careful about letting a system-wide upper bound become evidence that a particular action was safe.
revocation_issued_at tells us when authority changed. An observed enforcement bound tells us something about system behaviour. But for a consequential action, I’d still want to know what authority was actually effective at that specific execution boundary.
Otherwise we risk replacing “revocation was instant” with a slightly more sophisticated assumption that “revocation should have propagated within X.”
And your distinction between having audit logs and having audit logs whose claims are actually verified is exactly it. The latter is a much higher standard.
This has been a useful discussion from my side too.
Right — a system-wide bound tells you what's typical, not what was true for this specific action, and treating those as the same thing is just a more sophisticated version of the original problem.
For anything consequential, the honest version is probably: check authority at the execution boundary itself, not before it, and don't infer backward from a general enforcement window. That's a stronger design constraint than what I started with a few replies ago.
Genuinely appreciate this — this is the kind of pushback that's more valuable than any comment count or upvote today.
Appreciate that, Wendel — and I think we've reached the useful boundary.
What you've just described is actually the reason I've been separating system behaviour from action-specific assurance in OpsWatch. A general propagation characteristic can describe the system, but it can't establish what authority governed one particular consequential action.
I'm going to resist giving you another architecture suggestion here, because I think the more interesting question now is whether this boundary actually matters in the environments you're building for.
Are any of your current users or deployments allowing AI/automation to take consequential actions where a customer would need to establish afterwards that the action was still authorised when it occurred?
If not, this has been a genuinely useful technical discussion and I'd leave it there.
If yes, though, that's probably more interesting for both of us than continuing to refine the model in comments.
Sorry for the slow reply — this got buried in launch-week chaos, but I've been thinking about your question since you asked it.
Not yet, no — most of what I'm building for right now is still human-initiated actions with the authorization boundary you'd expect. But it's a genuinely good question, and it's making me think the audit-log distinction we've been discussing becomes non-optional the moment AI agents start taking actions with real consequences, since there's no human in the loop to notice the gap in the moment.
Curious what you're seeing in OpsWatch — is that the exact problem you're already dealing with, or anticipating?
Yes — that’s very close to the problem I’m dealing with in OpsWatch now.
The distinction I’ve ended up making is between authorization, dispatch, execution, and downstream consequence. They sound like one event until something changes between them — authority is revoked, a request times out, a provider accepts work asynchronously, or a retry occurs.
That’s where an audit log saying “authorized” or “blocked” can become misleading. Authorization earlier doesn’t prove authority still existed when the consequential action executed, and an internal DENIED state doesn’t necessarily prove nothing happened downstream.
So OpsWatch deliberately preserves an unresolved state when the evidence can’t establish the consequence, rather than upgrading uncertainty into success or prevention.
I think you’re right about agents making this non-optional. Human-initiated systems can sometimes rely on a person noticing the ambiguity. Once the system is acting autonomously, the evidence itself has to carry that burden.
That four-way split is sharper than how I'd been thinking about it — I had it as roughly two states (issued vs. effective), but breaking out dispatch and execution separately makes the actual failure points clearer. Especially dispatch vs. execution, since "we sent it" quietly becoming "it happened" is exactly where this stuff goes wrong.
Good luck with OpsWatch — this is a sharp problem to be building for.
That’s exactly the boundary that caught my attention in what you’re building, Wendel.
If B2B SaaS OS is helping founders get production-ready infrastructure in place, I suspect there may be a more direct overlap here than just comparing notes.
The moment one of those systems starts dispatching consequential actions — billing, provisioning, account changes, queued jobs, webhooks, or agent-triggered operations — the infrastructure can prove what it accepted or sent, but that doesn’t necessarily prove what executed or what consequence occurred downstream.
That gap is basically where OpsWatch starts.
I’d be interested in testing one bounded workflow from B2B SaaS OS against that four-boundary model. Not as a generic demo — just to see whether there’s actually a clean seam between production readiness and independent execution evidence.
If there is, that could be quite an interesting fit.
That's a genuinely interesting proposal. I'd be glad to walk through one bounded workflow with you — the Stripe webhook handling is probably the cleanest one to test against your model, since it already has explicit dispatch/execution separation (webhook received vs. subscription state actually updated).
I don't think it currently proves independent execution evidence the way your model would require — it's built to be idempotent and consistent, not to generate proof of what happened downstream. So this might genuinely surface a real gap, which is exactly the kind of thing worth knowing.
Happy to share the relevant code/flow if you want to look at it directly, or walk through it here first if that's easier.
Yes — Stripe webhook handling sounds like an excellent bounded case.
I think email will be easier from here, especially if we’re going to freeze the workflow and look at the actual code/flow rather than keep it theoretical.
Send it through to jason@mcgillintelligence.com.au and I’ll take it from there.
I’ll keep the first pass strictly bounded to webhook receipt → subscription-state update. That should let us establish what the existing implementation can actually prove before either of us draws conclusions from it.
If there’s no meaningful gap, that’s useful to know. If there is, then I think we may have found a genuinely interesting seam between what you’re building and OpsWatch.