Pairity
From a player’s frustration to builder
For a few years now, I’ve been a member in various badminton clubs in Ireland. Each club has their own way of doing matchmaking, whether that is using traditional peg boards where players manually track the queue and pairings, or use software like BadBoard which promised automation. The process is tedious and repetitive and either method does not do it reliably nor efficiently. It led to the same people sitting out, or unfair skill levels, or repeated matches, with no insight into how it’s picked or match history.
I tried running the sessions too - most clubs that opted to use a tool, went with BadBoard and while it improves on the traditional pegboard, the negatives are quite the deal breaker. It’s a local-only Widnows app so if it crashes, all data is lost. It is quite an old app so very understandable.
I wanted to use modern approaches and tools to improve how we approach this difficult problem of solving fairness in the badminton court, and also utilize what I’ve learned in Tines from good UXUI design to building a great product. I also wanted to scratch an itch of becoming a founder and building another 0-1 product, and doing stuff beyond just engineering like talking to the customer, building relationships with different clubs, etc.
My product philosophy
Before I talk about building this, let me lay the ground on what I wanted to build and to avoid.
- Prioritize trust and reliability before engagement features
- Simple to use
- Matchmaking speed is core
- Beautiful UI
- Focus on solving the problem (i.e. player check-in is a nice to have feature)
- Simple infrastructure to focus on building the product
I initially wanted to let each club design their divisions but then opted for Glicko-2 rating system so that every player, globally, can refer to the one system.
V0
I tried various ideas after chatting to many users of BadBoard, my experience from running the club nights, and also just observing in general.
Building V1 - the pairing wizard
So, after a few prototypes, I wanted something very simple (it is so hard not to scope creep between exciting features and features that will entice users to use the app). My V1 had:
- division-based skill tracking
- session management
- player profiles
- analytics
- saved matchmaking preferences for various club nights
For the pairing algorithm, it was a very simple math where the average division of one pairing cannot be greater than 1 division of the opposing team’s average division.
While this works, I felt like I was not solving the problem entirely by trying to make the matchmaking as simple as possible. In other words, while my approach of using simple math was effective, this brings about another set of problems that cancels out what I just fixed. These problems are:
- a player can still end up playing (or sitting out) back to back games
- no ability to pair preferences together like team mates
- it’s on-demand generation
I also decided to leave the onus of deciding a player’s division to the club owners but then I received feedback that it’d be great if players’ rating adjusts to their match outcomes.
The pivot to V2 - the algorithm
Through real-world testing, I realized the algorithm was the actual differentiator, not the UI polish. The matching quality-how balanced, fair, and enjoyable the games felt-determined whether organizers would trust and adopt the system.
The original strategy’s “co-pilot” approach was right in theory, but the underlying algorithm needed to be truly intelligent. I needed:
- Constraint programming (CP-SAT solver) for high-quality initial solutions
- Glicko-2 rating system that tracks skill with uncertainty, not just simple ELO
- Multi-objective optimization balancing skill, variety, fairness, and preferences
- Self-learning via Optuna to continuously improve weights without manual tuning
So I rebuilt. V2 is Python-focused, algorithm-first. I wrote comprehensive tests, benchmarked performance, and optimized from 30+ seconds to under 2 seconds. I added a FastAPI backend for integration and kept a lightweight React frontend for visualization.
The algorithm became the product.
Version 2: The Algorithm Engine (Current)
A specialized Python-based optimization system focusing on the core differentiator:
The Smart Matchmaker
- CP-SAT constraint programming for high-quality initial solutions
- Glicko-2 rating system tracking skill with uncertainty measures
- Multi-objective cost function balancing:
- Skill balance between teams
- Variety (avoid repeated pairings)
- Sandbagging prevention (large skill gaps within teams)
- Player preferences (preferred partners, blacklists)
- Self-learning optimization using Optuna to tune weights automatically
- Randomized local search to escape local optima
The Integration Layer
- FastAPI backend with full REST API
- CSV-based player data import
- React/TypeScript frontend for visualization
- Real-time cost function explanation (transparent “glass box”)
- Comprehensive pytest test suite
Performance
- Generates optimal schedules in 1-5 seconds for 100 players across 6 courts
- Supports custom constraints (max rounds, gender preferences, social dynamics)
- Self-learning continuously improves match quality
My key learnings
On Product Development
Empathy requires experiencing both sides
Being both player and organizer fundamentally changed how I understood the problem. Single perspective would have led to a worse solution.
The co-pilot pattern is powerful
“Augment, don’t replace” proved superior to full automation. Humans have context algorithms don’t (social dynamics, player energy, club culture). The best tool amplifies human judgment.
In other words, human in the loop tool.
Real-world testing is non-negotiable
This was true in Tines, true here, and true as always.
The true differentiator emerged through building
Started thinking UI and reliability mattered most. Learned through V1 that algorithm quality was the actual competitive moat.
On Technical Execution
Constraint programming is underused
CP-SAT solver provides provably high-quality solutions orders of magnitude faster than naive approaches.
Multi-objective optimization is hard
Balancing competing goals (fairness vs variety vs preferences) requires careful weight tuning. Self-learning via Optuna automated this but required good baseline heuristics.