Mobile Chess App Development
Building a chess app and facing move desync, timer disputes, or AI integration? We solve these on iOS, Android, and Flutter. The main technical challenge is real-time synchronization of game state between two clients with minimal latency and correct timer handling. Without a solid architecture, players will experience desync, stuck moves, and unfair timing. WebSocket is the only suitable protocol for exchanging moves; HTTP polling introduces delays and extra traffic. On iOS we use URLSessionWebSocketTask, on Android — OkHttp WebSocket, on Flutter — web_socket_channel. The client sends a move in UCI notation (e2e4), the server validates the position and broadcasts the update to both players. All legality checks happen on the server.
How to Synchronize Moves in Real Time?
WebSocket is the only suitable protocol. HTTP polling introduces delays and extra traffic. On iOS we use URLSessionWebSocketTask (native), on Android — OkHttp WebSocket, on Flutter — web_socket_channel. Exchange protocol: the client sends a move in UCI notation (e2e4), the server validates the position and broadcasts the update to both players. The client does not trust itself regarding move legality — all validation is done server-side. Otherwise, a modified app could make illegal moves.
// Android — sending a move webSocket.send(Json.encodeToString(MoveMessage( gameId = currentGameId, move = "e2e4", remainingTimeMs = timerViewModel.whiteTimeMs ))) On connection loss, the client falls back to HTTP polling every 2 seconds and attempts reconnection with exponential backoff. The game continues — a player with poor connection does not automatically lose time.
Why Must the Timer Be on the Server?
The timer is a source of disputes in online chess. If kept only on the client, a dishonest player could slow down their timer. The correct approach: the server stores white_remaining_ms and black_remaining_ms, updates them on each move, and sends the current values to clients. The client displays the timer (animation of decrease) but is not the source of truth. On reconnection, the client requests the current state and synchronizes the display.
Board Rendering Technologies
For native apps we use Canvas API (Android) or CAShapeLayer + CALayer (iOS). Move animation — moving ImageView/UIImageView via ValueAnimator / UIView.animate. In Flutter — a custom CustomPainter with Canvas.drawImage for pieces. Pieces in SVG format are converted to raster images for different resolutions — this allows recoloring for different themes.
Chess Engine for Playing Against AI
Stockfish is the industry standard, open-source, and strongest. It compiles as a C++ library for iOS, via JNI for Android, or via the stockfish package for Flutter. Search depth is controlled via UCI commands: setoption name Skill Level value 10 (0–20), go movetime 1000. Position analysis runs in a separate thread to avoid blocking the UI. Engine settings allow adapting difficulty: at level 0 it makes gross mistakes, at 20 it plays at grandmaster level.
Elo Rating and Matchmaking
Elo formula: newRating = oldRating + K * (score - expectedScore). K = 32 for new players, 16 for experienced. Matchmaking looks for an opponent within ±100 Elo with a timeout expansion every 10 seconds. The queue is stored in a Redis Sorted Set, score = timestamp of entry. When searching, the closest in rating participant is selected. The algorithm ensures waiting time rarely exceeds 30 seconds with 500 concurrent players.
Platform Comparison: Performance and Latency
| Component | iOS (Swift) | Android (Kotlin) | Flutter (Dart) |
|---|---|---|---|
| WebSocket | URLSessionWebSocketTask | OkHttp WebSocket | web_socket_channel |
| Timer | Server-sync | Server-sync | Server-sync |
| Engine | Stockfish (C++) | Stockfish (JNI) | Stockfish (native plugin) |
| Rendering | CAShapeLayer | Canvas | CustomPainter |
| Latency (p95) | < 50 ms | < 60 ms | < 80 ms (on older devices) |
Native apps in Swift/Kotlin provide 20% less latency compared to Flutter on devices that are 5 years old. For modern flagships, the difference is negligible. This is confirmed by our tests on iPhone 8 and Samsung Galaxy S9.
How to Scale the App for Thousands of Players?
The architecture is based on microservices: matchmaking, synchronization, and rating are separate services. Database on PostgreSQL with sharding by games.id. Redis is used for queues and caching. WebSocket server on Node.js with clustering — for horizontal scaling. This allows handling thousands of concurrent games without performance loss.
Architecture Details
We use Kubernetes for service orchestration. Each service has its own load balancer. The WebSocket server runs on multiple pods with a shared Redis pub/sub for move broadcasting. This ensures fault tolerance and linear scaling.What Is Included in the Work
- Architectural documentation (flow diagrams, database schemas).
- Source code with Unit tests.
- Integration with App Store Connect / Google Play Console.
- Deployment and monitoring instructions.
- Training for the client's team (1-2 days).
- Technical support for 3 months after release.
Estimated Timelines
| Feature | Timeline |
|---|---|
| Play against AI (Stockfish) | 4–5 weeks |
| Online play + timer | 6–8 weeks |
| Matchmaking + rating | 2–3 weeks |
| Full app | 8–12 weeks |
Why Order from Us
Our team has over 8 years of experience in mobile development and more than 15 completed projects in online games. We use only proven technologies: WebSocket, Stockfish, native APIs. Cost optimization — up to 30% savings compared to developing your own engine. We offer turnkey development: from prototype to publication in stores. App Store Review Guidelines (Section 4.2, 5.1) — our engineers know them by heart.
Contact us to discuss your project. Get a consultation on architecture and cost estimate. We guarantee transparency at every stage. Order a demonstration of our approach on a real project.







