Skip to content
All work
Case study 01Closed testing on Google Play

KPSS Düello

Realtime quiz duels with server-verified scoring.

Role
Product, backend and mobile engineering
Year
2026
  • KPSS Düello home screen with the duel call to action and subjects
  • A live duel: a matching question with both players' progress
  • Duel result with the question-by-question comparison

Overview

  • Flutter
  • Dart
  • Firebase Realtime DB
  • Firestore
  • Cloud Functions
  • Node.js
  • Pub/Sub
  • GitHub Actions

A mobile app where candidates for KPSS, Türkiye's civil service exam, challenge a friend or a random opponent to a 10-question duel. I designed and built all of it: the Flutter app, the realtime game protocol, the Cloud Functions backend, payments and the release pipeline.

Studying for KPSS is long and lonely. The idea was to make practice social: the same questions, a real opponent, and the one who knows more wins. That only works if nobody can fake a score, and if a duel survives flaky mobile connections.

How a duel is played

  1. 1Flutter appjoins the queue or opens a friend room through a callable function
  2. 2Cloud Functionsmatch players in a transaction, pick the questions and create the room
  3. 3Realtime Databaseplayers write only their pick and a server timestamp per question
  4. 4Scoring functionchecks answers against the published question bank and times the answers
  5. 5Firestoreresult, profile stats, duel history and league points are written by the server

Making scores impossible to fake

The first version let each device compute its own score, which meant a modified client could send any number. I moved to a second room protocol: the server creates every room and chooses the questions, and a player can write only two things per question, the chosen answer and a server-generated timestamp.

When both players finish, or one leaves, a function reads the published question bank, checks each answer and computes speed points from the server times. Security rules make every other field read-only for clients, and old app versions keep working in a restricted legacy mode during the migration.

Realtime that survives real phones

  • Disconnect handlers mark a player who drops as having left; a stalled opponent ends the duel after 45 seconds instead of hanging it.
  • When one player finishes, the other's clock runs twice as fast, so nobody waits forever.
  • If no opponent turns up, a bot is offered after 10 seconds and joins on its own at 20; it plays on the server, its answers are validated like a human's and it never touches league points.

Everything around the game

  • Weekly leagues of 30 players with promotion and relegation, a daily challenge, streaks with freezes, a gold economy and cosmetics, all written only by the server.
  • Mock exams with KPSS subject weights and an estimated score; a mistakes notebook with spaced repetition.
  • Map questions drawn from Natural Earth data, and a separate map-duel queue.
  • Question bank and subject catalog edited in a web portal and published to Firestore; the app syncs only the topics that changed.
  • Subscriptions and one-time purchases verified with the Google Play Developer API; renewals, cancellations and refunds arrive through Pub/Sub.

Testing and release

  • About 3,000 Flutter tests, including every question type rendered at two screen sizes to catch overflow.
  • Node tests for answer checking and scoring, plus security-rules and integration tests that run against the Firebase emulators in CI.
  • Pushing a version tag builds the app bundle in GitHub Actions and uploads it to the Play testing track.
  • App Check with Play Integrity is rolled out in monitor mode before enforcement.

What I took away

  • Put the trust boundary on the server from day one; migrating a live protocol is much harder than designing it right.
  • Emulator-backed rules tests are cheap insurance for a Firebase backend.

0