Rebuilding Battle.Tech when patching was no longer enough
Battle.Tech tied Counter-Strike results to accounts, prize money, and on-chain profiles. I rebuilt the product around a tournament core the company could actually own.
- Role
- Product and full-stack engineer
- Status
- Shipped product / concluded
- Scope
- Product / Next.js / NestJS / FACEIT / Solidity / Event indexing
I joined OWNED.gg after an agency-built first version had become too costly and brittle to keep. We rebuilt the tournament core, interface, backend jobs, and payout flow.
Taking over
Why the first version could not be patched
I joined OWNED.gg with a friend to take over Battle.Tech. An agency had built the first version, and even small changes were slow, expensive, and risky.
Worse, the tournament engine belonged to the agency. OWNED.gg could run tournaments, but it did not fully control the rules or outcomes of its own product.
We kept NestJS, then reorganised the backend into modules we understood. I rebuilt the Next.js interface while we replaced the agency’s tournament system with our own.
The product
One result changed the whole product
Battle.Tech ran Counter-Strike 2 tournaments, but a final score touched far more than the leaderboard. It could change prizes, progression, and a player’s on-chain profile.
FACEIT supplied tournament and anti-cheat data. An escrow contract held the prize pool. Our backend had to connect the result to the right players and pay them safely.
Each system had its own delays and failure modes. A match could be over on FACEIT while Battle.Tech was still verifying the result or waiting for a transaction.
The backend
Reliability meant waiting, checking, and retrying
FACEIT gave us an API, but not the webhooks or live events we needed. Even with partner access, rate limits meant the backend had to poll carefully.
Jobs watched registrations, detected starts and finishes, checked results, calculated winners, and triggered the escrow contract.
An indexer then waited for the transaction to become final. Only after confirmation could profiles, levels, prizes, and tournament history be updated.
The hard part was not one clever algorithm. It was making each step safe to run again when an API stalled, a job failed, or the chain took longer than expected.
After a match ended
The result still had a long way to travel
- 01FACEITMatch resultsRegistrations, games, results, and anti-cheat data arrived through a rate-limited API.
- 02BackendPolling and checksJobs watched for changes, verified results, and worked out who should be paid.
- 03ContractPrize distributionThe escrow contract distributed the tournament prize to the winners.
- 04IndexerChain confirmationAn event indexer waited for the transaction to become final.
- 05ProductProfiles and historyThe confirmed result appeared in progression, prizes, and tournament history.
A winner could exist before their account did.
The awkward edge case
A winner could arrive before their account
Anyone could enter through FACEIT, including players who had never joined Battle.Tech. That meant someone could win real prize money before we had an account for them.
We could not block the tournament or discard the reward. Instead, the prize became a claimable record with its own status.
The player could register later, connect FACEIT, prove their identity, and collect what they had already won. The tournament could finish without waiting for them.
The interface
The complexity had to disappear
I also rebuilt the interface. Most people on the project were not deeply familiar with Counter-Strike, so I often had to translate game rules into product decisions.
A new player could sign in with X, connect Steam and FACEIT, import stats, choose a name and avatar, and arrive at a profile that already felt useful.
We kept wallets and contracts out of the main journey. Joining a tournament, reading a result, and collecting a prize should not require a lesson in blockchain.
The same interface also carried quests, achievements, seasonal points, lotteries, leaderboards, and paid tournaments. Many moving parts had to feel like one product.
The ending
The product shipped. Growth did not.
The rebuilt Battle.Tech shipped, and the tournament system worked. What we could not solve was finding enough players at a sustainable cost.
We later pivoted to a memecoin battle product and shipped that too. The company ended after the founder left.
I do not want to turn the ending into a growth story. It was not one. I am proud that we took a product the company barely controlled and rebuilt it into something it owned.