Lapsed members are still getting through the door
In short
A turnstile that admits a cancelled member is rarely reading a wrong membership record — it is reading its own cached copy of one. Access controllers hold a local allow-list so the door keeps working when the network drops, which makes revocation something you have to push, and puts the fault in the timing and direction of that push rather than in the membership system.
Key takeaways
- The door decides locally. Membership status only reaches it when something pushes a change to the controller.
- A sync that adds and updates but never deletes will never revoke anybody, however often it runs.
- Diff the controller's credential list against live membership at one instant — that single check names the cause.
- Most of the exposure is usually billing latency, not door latency: dunning can hold a lapsed member active for days.
- If you accept a cache window, write the number down and pair it with a daily lapsed-entry report at the desk.
The controller on the wall by the turnstile holds its own list of credentials that may open the door. It has to: the door is expected to keep working when the internet drops, the card reader does not have time to ask a cloud service on every swipe, and a barrier that fails shut during a school swimming lesson is its own incident. So the membership record is not what admits anyone. A cached copy of it is.
That reframes the problem entirely. You are not looking for a member record that says the wrong thing — you are looking for a revocation that never left, left late, or arrived and was ignored. Attendance capture is a separate job with separate constraints, handled in check-in that assumes there is no network; this page is only about who the barrier lets through.
The check: diff the door against live membership at one instant
Everything below is guessing until you have this diff. It takes an afternoon and it identifies the cause on its own, because each cause leaves a different shape in the output.
- Export the controller's credential list. Every access system can produce this, even the ones with no integration surface — a management client export or a printed report is enough. Note the export time to the minute.
- Snapshot live membership at the same minute. Member id, credential id, status, status-effective date, and the timestamp of the last status change.
- Join on credential id, not name. Names collide, are re-keyed and get married. If the 2 systems share no credential identifier, that is your finding and the diff stops here.
- List credentials present on the door with a membership that is not entitled to enter. For each one, compute hours between the status change and the export.
- List the reverse — entitled members with no credential on the door. These generate desk queues and are the same defect in the other direction.
- Pull the entry log for the past 30 days and mark every entry that happened after its member's status change. Count them, and count the distinct members. That number is what makes the case for changing anything.
Seven causes, and what separates them
| Cause | Shape in the diff | Confirming evidence | Owner of the fix |
|---|---|---|---|
| Scheduled push only | Stale credentials, none older than 1 sync interval | Integration log writes only at the sync time | The access integration |
| Sync never deletes | Credentials revoked months ago still present | The door list is longer than the entitled list | The access integration |
| Reader trusts the card format | Cards that were never enrolled open the barrier | Present an unenrolled card of the right format | The access system installer |
| Freeze maps to no door rule | Frozen members entering, status correct everywhere | No freeze row in the status-to-access mapping | Whoever owns the status vocabulary |
| Status has not flipped yet | Diff is clean; the member is genuinely still active | Dunning retries still running against the card | Billing policy, named person |
| Credential shared or cloned | Entries with no plausible member behind them | Two entries at 2 sites minutes apart | Front desk policy |
| Controller fails open offline | Diff is clean and entries happen anyway | Entry times cluster in known network outages | The access system installer |
Where the exposure actually accumulates
Clubs assume the door is slow. Usually the door is the smallest term. Take a member whose card declines on a Tuesday, on a dunning schedule that retries on day 3, day 7 and day 14 before the membership is marked lapsed, with an access sync that pushes a full list at 03:00.
| Stage | Clock starts | Delay | Owner |
|---|---|---|---|
| Payment fails | First declined charge | Same day | Payment provider |
| Dunning completes | First decline | 14 days by policy | Whoever set the retry schedule |
| Membership status flips | Final retry fails | Immediate, or the next batch job | The membership platform |
| Access list updated | Status change | Up to 24 hours on a nightly push | The access integration |
| Controller applies it | Push received | Seconds — or never, if the sync merges | The controller configuration |
Fourteen days of that fifteen belong to billing policy. Shortening the door's window from 24 hours to 30 seconds removes 1 day of a 15-day exposure and feels like fixing all of it, which is exactly why the diff has to come before the engineering. The same misattribution shows up across the whole silo — full class, empty floor is the same timing defect wearing member-behaviour clothes.
Making revocation a first-class event
Most membership platforms emit an event when somebody joins and treat the end of a membership as a state that quietly becomes true. That asymmetry is the root of every cause in the table above, and it is fixable in the model rather than the integration.
- Emit a revocation event, not an absence. It carries member id, credential id, the reason, the effective instant and an idempotency key, so replaying it twice is a no-op.
- Map every membership state to a door decision explicitly. Active, in arrears, frozen, expired, cancelled, banned, guest, trial. A state with no row in that table will be handled by whatever the default is, and the default is usually admit.
- Make freeze a door state of its own. A frozen member should be admitted or refused deliberately, and clubs genuinely differ — what breaks is having the policy in a handbook and not in the mapping table.
- Acknowledge from the controller, not from the queue. A push accepted by the head-end and never delivered to the panel is the failure that survives every log you look at.
- Reconcile daily regardless. Re-read the controller list, diff it, and alert on any credential the door holds and the membership system does not — the same degrade-and-reconcile discipline that keeps operations systems useful when connectivity drops.
- Extend the same mapping to entitlements off the premises. A member who can no longer enter should not still be watching the members' stream, which is the identical cached-entitlement decision examined in a public video platform or your own club app.
Systems tell each other who exists. Almost none of them tell each other who has stopped existing, and that silence is where every stale allow-list comes from.
Multiple sites multiply the window, they do not share it
A club with 3 venues typically has 3 controllers, and often 3 different generations of hardware bought at 3 different times. Each has its own sync, its own interval and its own failure mode, so the exposure is the worst of the 3 rather than the average. Members and coaches move between sites the same evening — the movement modelled in one term timetable across three venues — so a credential revoked correctly at the main site can still open the barrier at the annexe.
Keep 1 canonical entitlement service and treat each controller as a downstream replica with its own health check. A per-site dashboard showing last successful sync, credential count on the door and credential count expected takes an hour to build and turns an invisible failure into a visible one.
Decision tree, with an owner on every branch
- Credentials removed months ago are still on the door. The sync merges. Move to a replace-or-explicit-delete write before you change anything else, because no scheduling improvement helps while deletions never arrive.
- Stale by hours, none older than one interval. This is an honest cache window. Choose deliberately between event-driven revocation and an accepted window, and if you accept it, write the number down.
- An unenrolled card opens the barrier. The reader is validating the card format rather than the credential. Nothing in your software can fix this; it is a controller configuration change and it is the most serious line on the list.
- The membership record still says active. Nothing is wrong at the door. This is a dunning and status-vocabulary question, and the fix belongs to whoever set the retry schedule.
- Frozen members are entering. Add the freeze row to the mapping table and decide the policy explicitly, once, for every site.
- Entries with no member behind them. Credentials are shared or cloned. That needs a desk policy and a second factor at the barrier, not an integration change.
- Everything reconciles and it still happens. The controller is failing open when the link drops. Ask the installer what the offline behaviour is configured to be, in writing, and decide whether you accept it.
Building the entitlement service, the revocation events and the nightly reconciliation is bounded AI agents and automation work in the sense that matters here — plumbing with alarms on it, not intelligence. The rest of this silo sits under scheduling, attendance and the facility, inside our sports, fitness and athletics practice.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
Why does gym access control let in cancelled members?
Because the controller decides locally from a cached allow-list rather than asking the membership system on each swipe. A cancellation only reaches the door when something pushes it, so the usual causes are a sync that runs on a schedule, a sync that adds and updates but never deletes, or a membership status that has not flipped yet because dunning is still retrying the payment. Diff the controller's credential list against live membership status at one instant and the shape of the difference tells you which.
Should the door check membership in real time instead of caching?
No — cache, and push revocations promptly. A door that asks a remote service on every swipe stops working when the connection does, which is unacceptable at a barrier with a queue behind it. The right design keeps the local allow-list for the decision and treats revocation as an event pushed within seconds, with a full reconciliation sweep daily to catch anything the event stream lost.
How quickly should a cancelled membership stop opening the door?
Within minutes if revocation is event-driven, and inside a stated window otherwise. The number matters less than it being written down and monitored: an undocumented window has no upper bound, because nobody notices when it grows. Whatever you choose, pair it with a daily report of entries by members who were not entitled, so the exposure stays visible.
Should a frozen membership still open the turnstile?
That is a policy choice, and the failure is leaving it unmade. Some clubs admit frozen members for paid casual entry; others refuse entry entirely so the freeze means something. Either is defensible, but the decision has to exist as a row in the mapping from membership state to door decision — a state with no row falls through to the system default, which almost always admits.
- access control
- membership status
- integration
- revocation
The work behind this page
Builds from our portfolio that this page draws on.
DockQueue
A dock scheduling and yard management platform that lets carriers self-book dock appointments, assigns the right door on arrival, and tracks every trailer's dwell and detention live.
LogisticsFieldRoute
An AI field-service platform that auto-dispatches the best-matched technician, optimizes routes, and tracks first-time-fix against every SLA.
OperationsRead next
- Full class, empty floor: where waitlist promotion silently failsThe spot is released, offered and accepted on a clock that runs out before anyone could reach the building. Instrument four timestamps for one week and the cause names itself.diagnostic
- Court utilisation is a fraction, and the denominator is the argumentBooked, attended and revenue-bearing over available: three honest utilisation numbers for one week, and the denominator argument that decides all three.definition
- Three systems, three member lists, all wrong in different placesDisagreeing member counts are a diagnosable defect, not a reason to buy something new. The mismatch classes tell you whether you have a sync problem, a definition problem or an identity problem.diagnostic
- A session series is not eighteen sessions: the recurrence record explainedA series is a rule plus an exception list, not a pile of rows. Every confusing this-event-or-all-events prompt comes from that one storage decision.definition
- What an attendance mark has to mean before you can count anythingAn attendance mark is a value from a small vocabulary plus an author, a timestamp and an amendment history. A tick box cannot answer a single question a club actually asks of a register.definition
- A guardian is not a member: the account type most club software lacksMost club systems model a parent as a member who happens to have children attached. That works until a household disagrees about who may do what, which happens constantly.definition
Working on something in this space?
Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.
Start the conversation