Gym Membership: Subscription, Freeze, Cancellation, and Collection in One Customer State
Back to blog
automation·September 6, 2026·5 min read·By Yehonatan Saadia

Gym Membership: Subscription, Freeze, Cancellation, and Collection in One Customer State

One state model for a gym membership: five states, what each transition does to the next charge, and a daily reconciliation between the door and the ledger.

Key takeaways

  • Five states cover nearly everything: active, frozen, pending-cancellation, cancelled and in-arrears. An "active yes or no" field cannot represent any of the middle three.
  • A transition is not a field update. It is a row with a start date, an end date, a requester and an approver.
  • The monthly charge is decided by the state on the charge date, not by the state at the moment the collection run happened to start.
  • Arrears is derived from the charge ledger rather than typed in by hand. Otherwise there are two sources of truth for one question.

A membership is not a boolean. It is one of five states, and every transition between them has a defined effect on the next charge and on entry at the door. When the app, the front desk and the billing system each hold their own version of that state, the member gets a different answer in every one of them. What follows is a technical description of a data model, not legal or financial advice.

Five states, and what each does to three systems

One state has to answer three questions at once: do we bill, does the door open, and what does the member see in the app.

StateNext chargeEntry at the clubWhat the member sees
ActiveCreated as normalOpensActive membership and renewal date
FrozenNot created during the freezeBlockedFreeze dates and a return date
Pending-cancellationCreated only up to the end dateOpens until the end dateThe end date, shown
CancelledNot createdBlockedMembership ended, history available
In-arrearsCreated, plus a retry attemptPer club policyAn open balance and a payment route

The third row is the one that collapses first in any system holding a boolean: "cancelled but still walking in" is not a contradiction, it is a perfectly legitimate state that lasts until the end date. The general model, beyond fitness, is taken apart in a state machine for recurring subscription billing.

The transitions, and what each does to the next charge

A well-defined state model is a list of permitted transitions, not a list of states. Each transition carries a trigger, an effect on billing, and an effect on the end date:

TransitionTriggerEffect on the next chargeEffect on the end date
Active to frozenMember request, club approvalCharges in the period are not createdPer the club's own agreement terms
Frozen to activeReturn date, or an early requestBilling resumes from the return dateBack on the normal schedule
Active to pending-cancellationA cancellation request with a dateCharges created up to that dateSet explicitly
Pending-cancellation to cancelledThe date arrivingCharges stop being createdEnded
Active to in-arrearsA failed chargeA retry on a scheduleUnchanged
In-arrears to activeA payment received and matchedBack on the normal scheduleUnchanged

What the table omits matters just as much: there is no direct move from frozen to cancelled without an explicit decision in between, and no move from cancelled back to active. A renewal is a new membership pointing at the old one, not the resurrection of a closed record.

Why does a frozen member still get charged?

Almost always for one of two reasons, and both are immediately identifiable.

The first: the collection run read the state at the moment it started, rather than the state in force on the charge date. If the freeze was recorded on the 28th and starts on the 1st, and the run went out on the 31st, "active" is what the run saw. The fix is not in the scheduling but in the query: the state you ask for is the state on the charge date.

The second: the collection file has already gone. A batch of direct-debit instructions is a document that leaves you and arrives somewhere, and once it has been sent, removing a line from it is no longer a change inside your system. That is why every charge deserves a field marking it as included in a dispatched batch, and locked. The difference between debit batches and card standing orders is discussed in Masav direct debits vs card payments.

Effective dating: a state is a range, not a value

The row holding the state should look like this:

  • membership_id - the membership, not the customer. One customer can hold two memberships over time.
  • state - one of the five values, from a closed list.
  • valid_from and valid_to - the validity range. An empty valid_to means this is the current state.
  • requested_by and approved_by - who asked and who authorised. Sometimes the same person, in which case both fields carry the same value.
  • reason - from a list, never free text.
  • document_ref - a pointer to the request as received, where one exists.

"What was the state on 1 October" becomes a range query rather than a guess. The other side of that coin is that an existing row is never updated: a change closes the previous range and opens a new one. Commercial billing models are built this way explicitly, and what it looks like in an external system is visible in Stripe Billing subscriptions.

Is in-arrears a state or a flag?

For management purposes it is a state; for door access it is a flag. Both can be true at once if you separate them properly.

Arrears is derived from the charge ledger: a charge exists whose due date has passed and which has not been matched to a payment. It is not written by hand and not typed in by a receptionist. The moment it is typed in, there are two sources for one fact, and they will diverge within weeks.

Door access is a separate decision resting on the state and the balance:

  1. Immediate block - rare, and usually excessive for a single day of lateness.
  2. Block after a day threshold - the threshold is a setting, not a rule in code.
  3. A front-desk alert with no block - entry opens and a note appears for the receptionist.

All three options derive from the same data. What changes is one setting, which is exactly what lets a club change policy without touching code. Building the surrounding operations is covered in automation for gyms and coaches.

A daily reconciliation between the door and the ledger

At the end of each day it is worth running a short check that looks only for contradictions:

  • Members in a frozen state with a recorded entry.
  • Members in a cancelled state for whom a charge was created.
  • Charges created for a date on which the state was not active.
  • Members past the arrears threshold whose entry opened anyway.
  • Active members with no valid collection instrument.

Those five lines are a short report on most days, and when it lengthens it is a sign that one specific transition is failing repeatedly. An empty report is not the goal. A report nobody reads is the problem.

What actually breaks

  • A freeze recorded as a note. "Frozen, we spoke" in a comments field is not a state and affects no calculation.
  • Two memberships for one person. An old membership never closed keeps generating charges alongside the new one.
  • A cancellation dated today. A member who asked to finish at month end is blocked at the door immediately.
  • A manual payment never matched. The money arrived, the charge stayed open, and the member stayed in arrears.
  • A run that executed twice. With no unique key per charge, the same month is collected twice.
  • An expired payment instrument. A card past its expiry creates arrears that look like non-payment and are not.

Sources

#state machine#memberships#billing#Masav#automation#אוטומציה לעסקים

Frequently asked questions

How many states does a small club really need?

Five cover nearly every case, and you can start with four if freezes do not exist at all. What does not work is two. The moment a membership can end on a future date, you need a state meaning "still entering, no longer renewing", and there is no shortcut around it.

Where should membership state live, in billing or in access control?

In one place that both read from. The access system may hold a local copy for fast lookups, provided that copy is overwritten from the source and never edited. Editing state from the front-desk screen is the shortest route to two different versions of the same truth.

What happens when a member asks to freeze mid-month after being charged?

Technically these are two separate actions: recording a freeze state from an effective date, and a business decision about the charge already issued. The second is a credit, a deferral or an extension of the term, and it belongs to the club. The system's job is to record which one was chosen.

Should entry be blocked automatically on arrears?

That is club policy. From a build standpoint, what matters is that the threshold is a parameter rather than code, and that every block is created with a reason and a timestamp. A block with no explanatory record looks like a fault to the receptionist, who will override it next time.

Keep reading

Related service

Business Automation

I build custom automations that remove repetitive work end to end.

Learn more →←

About the author

Yehonatan Saadia

Freelance automation, web & MVP developer

I'm Yehonatan Saadia, a senior developer who builds business automation, custom websites, and MVPs for small and mid-sized companies across the US, Europe, and Israel. These guides come from real client work, not theory.

Work with me

Have a project like this?

Tell me what you're trying to automate or build. I reply within 24 business hours with a few targeted questions, then we walk through it on a free 30-minute call, with no commitment. You come away with a scope, a timeline and a fixed price - or a straight answer that it isn't worth building.