PsTally.
Session tracking, shift reconciliation and console monitoring for gaming lounges. Built inside one, then rebuilt for the rest.
Gaming has always been one of my hobbies. At some point I decided to turn that into a business and opened a game lounge. It was my first business, and I went into it with very little experience on the operational side.
What started as something I enjoyed quickly turned chaotic. Constant disagreements with staff over shifts. Cash discrepancies at the end of every day. Customers underpaying for time they had actually played. Small problems that kept piling up until managing the lounge ate all the time that should have gone into running it.
I was spending most of my time resolving disputes instead of building a business. Something had to change.
As a developer, my first instinct was to look for something that already existed. I searched for a POS system, a management tool, anything that could bring order to the business. I found nothing that truly addressed the problem — not even partially.
What I found instead was that most gaming lounges were running on notebooks. Handwritten tallies. End-of-night mental arithmetic. Many owners had simply accepted the chaos as part of the job.
They had not accepted it because there was a better way. They had accepted it because there was no other way.
That realisation changed the question. It was no longer about finding a tool. It was about whether I was the right person to build one.
The first thing I got right was refusing to design for myself. An owner looks at this software for ten minutes a day. An attendant looks at it for eleven hours, standing, with a customer waiting and three bays running.
So the staff surface has no navigation, no reports, and no settings. Six cards, and the two things you do to a card: add a game, or end the session. A new attendant is productive within a shift because there is almost nothing to learn.
Pricing follows the same rule. Most sessions here are sold per game, not per minute, because that is how customers ask for them — two games, not twenty minutes. Some games are timed, some have a free-every-five rule the lounge already ran informally. The software models the transaction that was already happening at the counter rather than importing one.
The cashout screen has four buttons because Kenyan lounges take money four ways: cash, M-Pesa, a split of both, or nothing yet because the customer is known and will pay tomorrow. Removing the fourth option would have made the reconciliation cleaner and the software useless.
Reconciliation settled the arguments about money that had been recorded. It did nothing about money that was never recorded at all.
A console gets switched on for a friend. A customer plays twenty minutes while the attendant is outside. A session runs and nobody opens it in the system. Every owner I spoke to believed this was happening. Not one could tell me how much.
The system only knew what staff told it — which is exactly the wrong thing to trust when the question is whether staff are telling you everything.
The only honest way to answer it was to stop asking people and start watching the hardware.
PsTally Monitor is a background agent that runs on a PC in the lounge and reports which consoles are actually on. Nothing is installed on the consoles, the owner configures nothing, and it works over the WiFi that is already there. A lounge that can put one PC on its network is a lounge that can run it.
It runs on a machine I do not own, on a network I cannot configure, through daily power cuts, with nobody present who could restart it.
Every property below is an answer to one of those four facts.
The first version was a desktop app. It needed someone logged in, it could be closed by accident, and every fix meant a trip to a lounge and an evening of not knowing whether the install had taken. It is now a Windows service: no login, no window, starts on boot, restarts itself on failure.
Consoles were first tracked by IP. A router hands out a new lease overnight and one bay’s activity silently becomes another’s. That corrupted a lounge’s records for weeks before anyone could name what was wrong.
Consoles are now matched on a hardware identity that survives whatever the router decides overnight. The address is free to move. The console is not.
The original logic called a console off after sixty seconds of not hearing from it — on lounge WiFi, where things go missing for reasons that have nothing to do with consoles. It reported 144 false power-offs a day. It once showed a bay as off while a customer was playing on it.
Now a run of consecutive misses is not enough on its own: the agent has to go and check, and be told nothing, before it will report anything. In between it holds a “lost” state rather than guessing. False reports fell to three a day.
Events queue to disk when the server is unreachable and replay in order when it returns, bounded so the queue can never eat the machine. Updates arrive over the wire: the agent checks the payload’s hash before replacing anything, keeps the previous version, and rolls back on its own after repeated failed starts.
A lounge left dark by a bad update is worse than a lounge left on an old version.
Once the hardware data existed, the obvious move was to subtract billed time from powered-on time and hand the owner a number. That number would have been wrong, and wrong in the direction that destroys trust.
A console idling on the home screen between customers is not stolen revenue. Neither is one left on during setup, or for ten minutes after someone leaves. Treating every unbilled minute as theft inflates the figure several times over.
An owner who checks one case, finds the console was merely idling, and decides the number is invented will never believe it again. This gets one chance at being believed.
So it reports three things instead of one. Time that was billed. Time the console was on close to a real session — setup, wrap-up, the gap between customers, which costs electricity and not revenue. And time it was on with no session anywhere near it. Only the third is described as unbilled.
Every figure is a floor. Only time between two confirmed observations is counted; if the agent goes quiet for an hour, that hour is not claimed, because nobody knows what happened in it. And the page says plainly how much of the week it actually saw — “monitoring saw only 79% of console time this week; the real figure is higher than shown.”
That line costs the product its headline. It is the reason the headline can be repeated to a member of staff.
“At least six hours went unbilled” survives that conversation. “Nine hours” does not, if three of them were the monitor being offline.
A monitoring product has one failure worse than being wrong. It can be silent. A lounge that believes it is being watched and is not has stopped watching for itself, and nothing on the screen says so.
It happened. An agent stopped reporting and it took over an hour to notice, by accident, while looking at something else entirely.
The answer was a beacon that notices a quiet lounge and says so within twenty-five minutes. The hard part was never detection. It was not crying wolf: every lounge goes silent at closing time, and an alert that fires every night is one you filter within a week — and then you filter the one that matters too.
So silence only counts during the hours that lounge normally reports, learned from its own history rather than typed into a settings page. No opening hours to maintain, no timezone to get wrong, and it follows a lounge that changes its habits.
In its first ten minutes running it found a lounge that had been dark for five days. Nobody knew.
Closing a shift is three screens, and the order is the whole design.
The attendant sees the shift before they see the money: sessions run, revenue split between cash and M-Pesa, debts still outstanding, and anything the system thought was unusual. Five flagged sessions is not an accusation — it is a chance to say “that one was a regular, he paid yesterday” while it is still remembered.
Only then does the counting start, and the figure is stated before a note is touched: opening float plus cash collected. M-Pesa sits underneath, greyed out, labelled “not in till” — it is revenue, it is real, and it was never in the drawer. A reconciliation that mixes the two manufactures a discrepancy every single night and teaches everyone to ignore the number.
Notes and coins are entered separately, because that is how a person counts a till.
And the drawer never goes to zero. Whatever is left becomes the next shift’s opening float, recorded as a handover rather than assumed.
That last screen exists because of where the arguments actually came from. Not from a single shift going wrong — from the seam between two people who were never in the room at the same time. If nobody records what was passed across, both shifts inherit a number neither of them agreed to.
The tolerance is a few tens of shillings across an eleven-hour day. Past that, it is traceable to a session, a moment, a decision.
A summary reaches the owner on WhatsApp as the shift closes. Owners are not sitting at dashboards — they are somewhere else, and that is the only surface they will reliably see.
The lounge needed clarity, not surveillance. That is still what PsTally delivers.
Ninety days of a real lounge, reconciled: Ksh 167,815 across 1,207 sessions, averaging Ksh 139 each. Cash and M-Pesa split almost evenly, 54 to 46 — which is why both had to be first-class from the start rather than one bolted on later.
One game accounts for nearly all of it. Demand peaks between noon and 4pm, not in the evening, which is the opposite of what the owner assumed and changed how the lounge was staffed.
None of this was available to the owner before. Not because it was hard to compute, but because nobody was writing anything down.
Three choices that shaped how the system thinks.
Every request resolves its lounge from the authenticated session inside tRPC middleware, never from anything the client sends. A session belongs to the shift that opened it at the database level, so a close can only ever draw on sessions that attendant personally owned.
This came from a real incident: two staff signed in at once, sessions bleeding across shifts, a discrepancy neither of them had caused. The fix was not a filter in the interface. It was putting ownership somewhere it cannot be argued with.
Per-game pricing, free-every-five, split payments, and customers who owe — none of these were product ideas. They were things the lounge already did, badly, on paper. The software’s job was to make them exact, not to replace them with a cleaner model that nobody at the counter recognises.
Shifts close on an exact three-part figure. Unbilled time is a floor with a coverage percentage printed beside it. Consoles the agent cannot currently see are labelled as unseen rather than assumed off.
A product that rounds to zero looks more finished and hides the only information worth having. The number is not an accusation. It is the beginning of a conversation somebody can actually have.
If this way of building resonates —
No brief required · Tell me what you’re trying to make
What came next
The platform that ended the arguments was rebuilt from the ground up — with the GTM layer engineered in.
PsTally Rebuilt →