GymPaid
A renewals tracker for Pakistani gyms that replaces the paper register and answers one question: who owes me money today?
A gym in Punjab kept memberships in a paper register. A member who joined on the 17th pays on the 17th, every month, and with a few hundred members on a few hundred different days the owner could not tell who was due.
GymPaid gives the front desk a due list, WhatsApp reminders and revenue figures that stay correct without anyone maintaining them.
Decisions
01
Renewals anchored to the join dayDecision D-3
- Chose
- Each member keeps a pay day separate from their next due date.
- Instead of
- Computing each due date from the previous one.
- Why
- A member anchored on the 31st is due on 28 February; computing March from the 28th would move them to the 28th for good. Keeping the anchor restores the 31st.
02
Status is computed, never storedDecision D-14
- Chose
- Active, due soon, overdue or lapsed is worked out on every request from the due date and the gym’s grace period.
- Instead of
- A status column.
- Why
- A status column goes stale at midnight because nothing runs to flip it, and every screen, and later the door, would believe it.
03
No cron, no queue: reminders are a queryDecision D-11
- Chose
- The due list is a query, and a reminder opens WhatsApp with the message already typed.
- Instead of
- A background worker, a queue of reminder records and the WhatsApp Business API.
- Why
- A query is always correct and has nothing to retry. It shipped on day one with no verification process and no per-message cost.
04
Wrong payments are voided, not deletedDecision D-24
- Chose
- An owner can void the latest payment, which restores the previous due date and keeps the receipt.
- Instead of
- Deleting the payment, or fixing it in SQL.
- Why
- Staff will tap Paid on the wrong row. Deleting would free a receipt number a member already holds and erase the record that it happened.
05
A door that holds no fingerprintsDecision D-46
- Chose
- Each minute the door terminal is sent only the difference between who it lets in and who should get in now; fingerprint templates never leave the device.
- Instead of
- A command queue with retries, and a copy of members’ biometrics.
- Why
- A member who lapses at midnight is shut out on the next poll with nothing scheduled, and “we hold no fingerprints” is a promise the design keeps.
GymPaid, in use: GymPaid’s due list: who owes money today, with WhatsApp and Paid buttons. The members list: plan, status and next due date for each member. Membership plans: monthly, three months and annual. GymPaid: who owes you money today?
























- gympaid.ezvenda.com/queueThe one question it answers: who owes money today, with a reminder a tap away.
- gympaid.ezvenda.com/membersEvery member’s plan and when they are next due.
- gympaid.ezvenda.com/plansPlans with the price per month worked out.
- gympaid.ezvenda.comThe question it answers, on its card.
What shipped
- Milestone 1 built against a two-day hand-over deadline.
- 154 automated tests green, 48 of them on the renewal rule alone.
- A pre-deploy security review that found and closed a way around the sign-in rate limit.
- Door polling at about 12 ms per poll, with no fingerprints stored.
Built with
TypeScript, Fastify, Drizzle, Postgres, React, TanStack, ZKTeco ADMS






