In a recent pitch to a gym owner in Accra, she asked the question every gym owner should ask: “What happens to my gym data? Where does it actually live, and who can see it?”
It was the right question, and most software vendors give the wrong answer to it. They say “we take security seriously” or hand over a glossy PDF full of acronyms, and the gym owner walks away no clearer than before. So this post is the answer we’d rather give: a plain-language walkthrough of how FitSynQ actually protects the data you put into it.
Your data is isolated at the database, not just the screen
The boring but important fact comes first. When two gyms share a software platform, the dangerous version of “multi-tenancy” is the kind where everyone’s data sits in one big table and the application code is the only thing keeping them apart. One bug in the wrong place and a query reaches across gyms.
We don’t trust application code with that job. Every table that holds your gym’s data has Row Level Security policies enforced by the database engine itself. Before any query runs, the database checks who’s asking and whether they’re allowed to see this row. If the answer is no, the row never leaves the server. The application doesn’t have the option to mess this up. The database refuses.
That’s the floor we built on. Everything else is layered on top of it.
Who can see what, by role
Inside your gym, not everyone needs to see everything. A receptionist at your Tema branch shouldn’t be able to look up members from your Osu branch. An instructor shouldn’t see your revenue. A branch manager shouldn’t be able to delete the organization.
FitSynQ’s permission system is built around scope. Every role lives at one of three levels: organization-wide, branch-specific, or system-level. When someone signs in, the system loads their role and their scope, and every action they try gets checked against both. A branch manager at Tema asking for the member list gets back the Tema list. The same person querying an Osu member gets a “not allowed” response, even if they typed the URL by hand.
This isn’t decorative. It’s enforced at the API layer, again at the database layer through RLS, and cached for speed with automatic invalidation the moment a role changes. Three independent checks, every request.
Sign-in, sessions, and why we don’t store your password
We don’t run our own password system. Authentication runs on Supabase, which sits on a stack that hashes passwords, handles email confirmation, manages sessions, and patches itself when the next vulnerability lands somewhere on the internet. We get the benefit of a team whose entire job is keeping that layer healthy.
When a member or staff signs in, Supabase issues a signed token that proves who they are. Our server validates the signature on every single request. If someone tampers with the token, the signature breaks and the request is rejected before it touches a database.
QR check-ins that can’t be photographed off someone else’s phone
The QR code in a member’s app is a token we sign on our server. Inside it, alongside the user’s ID, is a fingerprint of their profile data and an expiration that’s never more than 24 hours away. The member’s app refreshes the token quietly in the background before that expiration lands; nothing for the member to do.
That expiry is the practical limit on a leaked QR. A screenshot of someone else’s code is useful for at most a day, after which every kiosk in the network rejects it as expired — including kiosks that were offline at the moment the original phone got stolen. The lifetime of a leaked QR is bounded by the clock, not by how fast the news of the theft travels through your branches.
The QR can’t be forged either: without our server’s private signing key, no one can mint a token the kiosk will accept. And if a member loses their phone, we revoke their current token on our end so it can’t be re-fetched. The rolling 24-hour window then guarantees the stolen copy goes dead within a day even on a kiosk that’s been offline the whole time.
Kiosks that only work at the branch they belong to
The check-in kiosk has its own authentication on top of the staff login. When a kiosk is first set up, the device’s browser fingerprint is registered against a specific branch. From that point on, every check-in request includes both the staff token and the device’s fingerprint. The server confirms three things in one go: the staff member is real, the kiosk is registered, and the kiosk is allowed to operate at the branch the staff member is signed into.
If someone tries to use a kiosk’s credentials from a different device, it fails. If a real kiosk is moved to another branch without re-registering, it fails. Neither case is a normal user experience — both look like break-in attempts and get logged as such.
A trail of who did what
Every action that changes data — a member created, a payment recorded, a role assigned, a session checked in — writes a row to the audit log. Each row has the user, the resource, the action, the timestamp, the IP address, and the user agent. We use it to investigate problems. You can use it to investigate your own staff. If a member’s record was edited and you want to know who did it, the answer is in the log within seconds.
The unglamorous list
There’s a long tail of smaller measures that don’t make for an exciting paragraph but matter just as much. All traffic between your devices and our servers runs over HTTPS. Only approved origins are allowed to talk to the API. Every database query goes through a parameterized layer that closes the door on SQL injection. Inputs are validated against typed schemas, and unknown fields get stripped before they reach your data. Rate limiting blocks brute-force attempts at sign-in. Internal IDs are generated as time-ordered UUIDs that can’t be guessed by counting up from 1.
What we don’t pretend
No system is bulletproof. The honest version of a security promise is that we’ve built defense in depth — multiple independent layers, each catching what the others miss — and that we maintain the boring habits that actually keep systems safe: dependency updates, audit logs we read, narrow permissions for our own team, and a willingness to publish a post like this one because the answer to “where does my data live and who can see it” should never be a mystery.
If you have a specific concern we haven’t addressed here, write to us. We’d rather answer the question than have you wonder.
Ready to modernize your gym?
See FitSynQ in action — no commitment required.