Entitlements that do not leak
The client knows what it believes it is owed. Only the server knows what is true.
One record, two readers
Access rights resolve to a single authoritative row, read by both the client and the server. Not two stores kept in sync — one row. Anything else eventually produces a state where the interface believes a feature is available and the server disagrees, and the user is left looking at a button that does nothing.
The client may cache it for responsiveness. It may not be the authority. Every paid operation re-checks server-side before it does the expensive thing, because the copy nearest the user is the copy easiest to edit.
The problem nobody tests: ordering
Billing providers deliver events by webhook. Webhooks are not ordered, and they are retried on failure. Both of those are documented, and both are routinely ignored, because in development events arrive one at a time in the order you caused them.
In production a retried expiration from four minutes ago can land after a fresh renewal from ten seconds ago. Processed naively, the system revokes access the user has just paid for. It self-heals on the next event, which may be a month away, and the support ticket says only that the subscription stopped working.
So entitlement writes carry the originating event timestamp and refuse anything older. The important part is where that refusal lives: in the SQL predicate of the update itself, not in application code. Read-then-write in the application is a race — two concurrent deliveries can both read the old row, both conclude they are newer, and both write. Pushing the comparison into the update's own condition makes the database resolve it, which is what a database is for.
Compare shared secrets in constant time. Webhook signature verification with an ordinary string comparison leaks the secret one byte at a time to anyone able to measure response timing across many attempts. It is a small change and there is no reason not to make it.
Keep the provider behind one file
Payment provider integration sits behind a single module. Nothing else in the codebase knows which provider is in use.
This is not architectural fashion. Billing providers get acquired, change pricing, or stop serving a market. Keeping the integration to one file makes that a bounded piece of work rather than a migration touching every screen that checks whether a user is subscribed.
The leak we shipped
We had a cached entitlement that signing out did not clear.
The path is unremarkable and that is the point. Sign-out cleared the session, because that is obviously what sign-out means. The entitlement cache was written by a different subsystem, at a different time, for good reasons, and nothing connected the two. Sign in as someone else on the same device and the premium state from the previous account was still sitting there.
Two fixes. Sign-out now clears the entitlement before it touches the session. And account deletion clears local state only after the server-side deletion has actually succeeded — previously it cleared first, so a failed deletion left someone with a wiped device and an account that still existed.
Both were one-line ordering problems. Neither was visible in any test, because the tests covered sign-out and entitlement separately, and the bug lived in the space between them.
The next generation of software will be intelligent.
ScentID Solutions is building toward that future — one platform, one integration, and one intelligent solution at a time.
Work With Us