Research

Digital Surface Labs

"Multiplayer Game Feasibility Analysis for OpenArcade"

Multiplayer Game Feasibility Analysis for OpenArcade

Executive Summary

OpenArcade currently runs 7 single-player browser arcade games on a Jetson Orin Nano, with a data pipeline that captures gameplay frames and keyboard events for ML training. This analysis evaluates whether and how multiplayer games can be added to the platform -- covering AI-assisted game generation, networking architectures, hardware constraints, scaling strategy, and data collection value.

Bottom line: Multiplayer is feasible but requires careful scoping. Turn-based and casual multiplayer games are achievable on the Jetson with modest engineering. Real-time action multiplayer is possible for small player counts (2-8 concurrent matches) but will hit hardware limits quickly. The data collection value of multiplayer far exceeds single-player, making this worth pursuing in phases.


1. Can Claude Code (or Similar AI) Generate Complex Multiplayer Games?

What AI Code Generation Does Well

The current OpenArcade games prove the model: each game is a single self-contained HTML file (236-878 lines) with inline CSS and JavaScript. Claude Code and similar tools excel at generating this type of code:

  • Game logic and rules: Collision detection, scoring, level progression, physics simulations. These are well-understood algorithms with abundant training data.
  • Canvas rendering: 2D drawing, sprite animation, particle effects. The existing games demonstrate clean canvas rendering that AI generates reliably.
  • UI and polish: Overlays, score displays, game-over screens, responsive layouts. All 7 current games have consistent, polished UI generated in this pattern.
  • Single-player AI opponents: The Pong game already has a CPU opponent. AI can generate competent bot logic for most classic game types.

What Is Hard for AI to Generate

Multiplayer introduces categories of complexity that AI code generation handles poorly:

  • Netcode and state synchronization: Correctly synchronizing game state between two or more clients over unreliable networks is notoriously subtle. Issues like client-side prediction, server reconciliation, input delay compensation, and rollback are hard to get right even for experienced developers. AI-generated netcode will have bugs that only manifest under real network conditions (latency, jitter, packet loss).
  • Anti-cheat: Any game where clients exchange state has trust problems. AI can generate naive implementations but will miss exploitation vectors.
  • Matchmaking and lobby systems: Session management, player pairing, handling disconnections gracefully, reconnection logic -- these are stateful server-side concerns that do not fit the "single HTML file" pattern.
  • Concurrency and race conditions: Multiple players interacting with shared state creates timing bugs that are hard to reproduce and hard for AI to reason about preemptively.

The right split is:

Generate with AI Build as shared infrastructure
Game rendering and visuals WebSocket server (Node.js or Python)
Game rules and physics Room/lobby management
Client-side input handling State synchronization protocol
Bot/AI opponents Matchmaking service
UI, menus, animations Disconnect/reconnect handling
Sound effects integration Authentication (if needed)

The pattern: Build a thin multiplayer server framework once. For each new game, AI generates the game-specific logic (rendering, rules, scoring) and plugs into the framework via a standard interface (e.g., onTick, onPlayerInput, onStateUpdate). The game itself remains a single HTML file; the server-side room logic is a small module per game.

Realistic Output Estimate

With a well-built server framework, AI could realistically generate:

  • 10-15 turn-based games (card games, board games, trivia) with high reliability
  • 5-8 casual real-time games (cooperative or low-stakes competitive) with moderate reliability
  • 2-4 action multiplayer games (fighting, racing, competitive shooters) with significant manual debugging required

Each game would take 1-3 hours of AI generation plus 1-4 hours of manual testing and netcode debugging, depending on complexity tier.


2. Networking Architecture Options

How it works: Clients maintain persistent WebSocket connections to the server. The server acts as authoritative state manager, broadcasting game state updates at a fixed tick rate (typically 20-60 Hz for action games, 1-10 Hz for casual games).

Best for: Most multiplayer arcade games -- Pong, Asteroids, Space Invaders co-op, Breakout vs, Tetris battle.

Pros: - Simple to implement on both client and server - Works through Cloudflare tunnel and proxies - Server-authoritative model prevents most cheating - Node.js ws library is lightweight and battle-tested - Integrates naturally with the existing nginx reverse proxy

Cons: - Latency floor of ~50-150ms through Cloudflare tunnel (acceptable for casual, marginal for competitive) - Each connection holds server memory (~2-5 KB per socket) - Server CPU scales linearly with number of active games

Implementation sketch:

Client (browser) <--WebSocket--> Nginx (:8099) <--proxy--> Game Server (:8095)
                                                              |
                                                         Room Manager
                                                         /    |    \
                                                      Room1  Room2  Room3
                                                     (pong) (tetris) (asteroids)

Tick rate recommendations by game type: - Pong, Asteroids, Breakout: 30 Hz server tick, client interpolation - Tetris battle, Snake: 10 Hz server tick (discrete movement) - Card/board games: Event-driven, no tick loop

Option B: WebRTC Peer-to-Peer

How it works: After initial signaling through the server, players establish direct peer-to-peer connections using WebRTC DataChannels. Game state is exchanged directly between browsers.

Best for: Two-player games where latency is critical (fighting games, racing) and players are on the same network or nearby.

Pros: - Lowest possible latency (direct connection, potentially sub-10ms on LAN) - Offloads bandwidth and CPU from the server - Server only handles signaling, not game traffic

Cons: - NAT traversal fails ~15-20% of the time (needs TURN fallback, which requires a relay server) - No server authority -- both clients can cheat - Harder to collect training data (data stays between peers unless explicitly relayed) - More complex client-side code that AI generates less reliably - Cloudflare tunnel does not help with direct peer connections

Verdict: Not recommended as primary architecture. The data collection requirement (central to OpenArcade's purpose) conflicts with peer-to-peer. Consider only for a "local multiplayer" LAN mode where both players are on the same network as the Jetson.

Option C: Turn-Based HTTP Polling

How it works: Clients poll the server via standard HTTP requests for game state updates. Players submit moves via POST requests. Server maintains game state in memory or database.

Best for: Chess, checkers, card games, trivia, word games, turn-based strategy.

Pros: - Simplest to implement -- works with existing nginx and API patterns - Extremely lightweight on server resources - No persistent connections; scales effortlessly - Works perfectly through Cloudflare tunnel - AI generates this pattern very reliably - Tolerates high latency (even seconds of delay is fine)

Cons: - Not suitable for real-time action games - Polling interval creates inherent delay (typically 1-3 seconds) - Slightly higher bandwidth than WebSocket due to HTTP overhead per request

Implementation: Could literally use the existing ingest API pattern. A /api/games/{gameId}/state GET endpoint and /api/games/{gameId}/move POST endpoint is sufficient.

Use different architectures for different game categories:

Game Category Architecture Examples
Turn-based HTTP polling Chess, Cards, Trivia, Battleship
Casual real-time WebSocket, 10-20 Hz Tetris battle, Snake arena, Co-op Breakout
Action real-time WebSocket, 30 Hz Pong PvP, Asteroids deathmatch
Ultra-low-latency WebRTC (LAN only) Fighting game (future)

Build the WebSocket server first (it covers the most games), add HTTP polling for turn-based (trivial), and defer WebRTC to a later phase.


3. Can the Jetson Orin Nano Handle This?

Current Resource Usage Assessment

The Jetson Orin Nano has: - CPU: 6-core ARM Cortex-A78AE (moderate single-threaded performance, ~60% of a modern x86 core) - RAM: 8 GB shared between CPU and GPU (this is the primary constraint) - GPU: 1024-core Ampere (powerful for inference, but shared RAM limits model size) - Storage: 916 GB NVMe (ample) - Network: Gigabit Ethernet (sufficient)

Current services already consuming resources:

Service Estimated RAM CPU (idle/active)
ChromaDB (:8000) 300-500 MB Low / Moderate
MCP Server (:8082) 100-200 MB Low
Buddy (:8001) 200-400 MB Low / Moderate
Ollama (:11434) 500 MB - 4 GB (model-dependent) Low / High during inference
Nginx 20-50 MB Low
OS and system 500-800 MB --
Total baseline ~1.6-6 GB --

Available headroom: With Ollama idle (no model loaded), roughly 4-5 GB free. With a model loaded, potentially only 1-2 GB free.

WebSocket Server Capacity

A Node.js WebSocket server is lightweight: - Per connection: ~2-5 KB RAM for the socket + ~1-2 KB for game state = ~5-7 KB per player - Per game room: ~20-50 KB (room state, player states, tick loop overhead) - Server process baseline: ~30-60 MB for Node.js runtime

Estimated capacity: - Concurrent connections: 500-1000 players could connect simultaneously (RAM is not the bottleneck for connections alone) - Active game rooms: The CPU bottleneck kicks in first. At 30 Hz tick rate, each room's game loop costs ~0.5-2ms per tick depending on game complexity. On a single core, that allows ~15-30 simultaneous action game rooms before CPU saturation. - Practical limit with headroom: 20-50 concurrent matches across all game types, assuming a mix of action (30 Hz) and casual (10 Hz) games.

Data Ingestion at Scale

This is where multiplayer significantly increases load. Current single-player pipeline: - 2 fps JPEG capture per player, ~15-30 KB per frame - ~30-60 KB/sec per active player - Upload every 60 seconds in segments

Multiplayer amplifies this: - 2-player game: 2x frame data + server state snapshots - 4-player game: 4x frame data - Plus: Server-side game state logs (authoritative state, much more valuable than client captures)

Estimated data rates per active match: - 2-player: ~120 KB/sec (frames) + ~5 KB/sec (events/state) = ~125 KB/sec - 4-player: ~240 KB/sec + ~10 KB/sec = ~250 KB/sec

With 20 concurrent matches (average 2.5 players each): - Ingest bandwidth: ~3 MB/sec sustained - NVMe write load: ~180 MB/min = ~10.8 GB/hour - Daily storage (8 hours active): ~86 GB/day

The 916 GB NVMe would fill in roughly 10 days at sustained peak load. Realistically, with intermittent usage, storage lasts weeks to months, but a data rotation/archival strategy is needed.

GPU Utilization Conflict

The 1024-core Ampere GPU is primarily valuable for ML inference (Ollama, future game AI). Running the game server itself does not use the GPU. However:

  • If Ollama is actively running inference (e.g., processing gameplay data, running bot AI), GPU memory contention with other services increases
  • The GPU should be reserved for ML workloads, not game serving
  • Game logic runs entirely on CPU, which is the right separation

Realistic Player Count Limits

Scenario Concurrent Matches Players Feasibility
Small community 5-10 10-20 Comfortable. Jetson handles easily.
Active evening 15-25 30-60 Achievable. Some latency under load.
Popular launch 30-50 60-100 Pushing limits. Need to throttle Ollama.
Viral moment 50+ 100+ Jetson cannot handle. Need cloud overflow.

Hard limits: RAM becomes critical above ~80 concurrent players if Ollama has a model loaded. CPU becomes the bottleneck above ~30 simultaneous action-game rooms.


4. Scaling Strategy

Phase 1: Jetson-Only (0-50 concurrent players)

Keep everything on the Jetson. This is the cheapest and simplest option.

What to build: - Node.js WebSocket game server on port 8095 - Nginx proxy rule to route /ws/ to the game server - 3-5 initial multiplayer games (Pong PvP, Tetris battle, a turn-based card game) - Server-side state logging integrated with existing ingest pipeline

Cost: $0 additional (hardware already owned).

Timeline: 2-4 weeks for infrastructure, then ~1 week per game.

Phase 2: Cloudflare Workers for Matchmaking (50-200 players)

Offload stateless work to the edge. Keep game simulation on the Jetson.

What to move to cloud: - Matchmaking and lobby management (Cloudflare Workers or Durable Objects) - Player authentication (if added) - Leaderboards and stats API - Static asset serving (already via Cloudflare)

What stays on Jetson: - WebSocket game server (actual gameplay) - Data ingest pipeline - ML inference

Cost: Cloudflare Workers free tier covers 100K requests/day. Durable Objects start at ~$0.15/million requests. Estimated: $0-5/month.

Phase 3: Cloud Game Servers (200+ players)

When the Jetson cannot handle the game simulation load, add cloud game servers.

Options and cost estimates:

Provider Instance Monthly Cost Capacity
Fly.io shared-cpu-1x, 256MB $2/month ~20 concurrent matches
Fly.io shared-cpu-2x, 512MB $5/month ~50 concurrent matches
Railway Starter $5/month ~30 concurrent matches
AWS Lightsail $3.50 instance $3.50/month ~25 concurrent matches
Hetzner VPS CX22 ~$4/month ~40 concurrent matches

Architecture: Game server runs identically on Jetson and cloud. A routing layer sends players to the least-loaded server. Game state and recordings are still shipped back to the Jetson for ML processing (async, not latency-sensitive).

Cost at scale: ~$5-20/month covers 100-500 concurrent players. This is extremely cheap compared to traditional game hosting because these are 2D canvas games with minimal state.

Phase 4: Edge Computing (Future, 500+ players)

For genuine low-latency multiplayer at scale: - Cloudflare Durable Objects can run lightweight game logic at the edge (~50ms latency worldwide) - Game state stays in Durable Object memory; recordings stream to R2 storage - Jetson becomes purely the ML training and inference backend

Cost: Durable Objects pricing is ~$0.15/million requests + $0.50/GB-month for storage. For 500 concurrent players generating ~10M requests/month: ~$5-15/month.

What Can Stay on the Jetson Forever

  • ML model training and inference (its primary value)
  • Data pipeline processing (ingesting, labeling, augmenting gameplay data)
  • ChromaDB vector store
  • Development and testing environment
  • Low-volume game serving (always keep the Jetson as a game server for local/LAN play)

5. Data Collection Value

Why Multiplayer Data Is More Valuable Than Single-Player

Single-player gameplay data captures one human's interaction with a deterministic environment. Multiplayer data captures something fundamentally richer:

  1. Adversarial strategy: How humans adapt to unpredictable opponents. This is the core of decision-making under uncertainty -- the exact capability needed for office automation (responding to emails, handling unexpected requests, negotiating).

  2. Coordination patterns: In cooperative games, players develop implicit communication and task-splitting strategies. This maps directly to multi-agent AI coordination.

  3. Reaction to human behavior: Single-player games have predictable patterns. Multiplayer forces adaptation to novel situations, producing more diverse training data per hour of play.

  4. Natural difficulty scaling: Instead of artificial difficulty curves, the opponent provides organic challenge calibration. This produces data across a wider skill distribution.

  5. Social dynamics: Chat messages, emote usage, rage-quitting patterns, sportsmanship -- all valuable signals for building AI that interacts with humans naturally.

Types of ML Models This Data Enables

Model Type Single-Player Data Multiplayer Data
Imitation learning (behavioral cloning) Basic action prediction Strategic, adaptive action prediction
Reinforcement learning (reward signals) Score-based reward only Win/loss + opponent modeling
Multi-agent systems Not possible Direct training signal
Human behavior prediction Limited (one player) Rich (interaction dynamics)
Decision-making under uncertainty Deterministic environment Stochastic opponent behavior
Vision-language models (with chat) No language data Natural language in context

Estimated Data Volumes

Metric Single-Player (current) Multiplayer (projected)
Data per player-hour ~100 MB (frames + events) ~150 MB (frames + events + state)
Unique behavioral patterns Low (games are deterministic) High (opponent-dependent)
Sessions before data saturates ~100-200 per game ~1000+ per game (combinatorial)
Value per MB of data Moderate 3-5x higher

Storage projections (first 6 months): - Conservative (5 daily active players): ~3 GB/day = ~90 GB/month = ~540 GB total - Moderate (20 daily active players): ~12 GB/day = ~360 GB/month (need external storage by month 3) - Aggressive (100 daily active players): ~60 GB/day = far exceeds Jetson storage

At moderate usage, the 916 GB NVMe is sufficient for 2-3 months with rotation. After that, archival to cloud storage (Cloudflare R2 at $0.015/GB/month, or ~$5/month for 300 GB) makes sense.

  • Frame data: Canvas frames contain only game visuals, not webcam or personal information. Low privacy risk.
  • Browser fingerprinting: The collector_id in recorder.js uses a random UUID stored in localStorage. Not linked to real identity. Acceptable.
  • Multiplayer chat (if added): Chat messages could contain personal information. Must be disclosed in terms of service, with option to opt out of chat logging.
  • IP addresses: Standard web server logs. Covered by standard privacy policy.
  • GDPR/CCPA: If users outside the US play, a cookie consent banner and data deletion mechanism may be needed. For an indie/research project, a simple privacy policy page and email-based deletion requests are sufficient.

Recommended approach: Add a brief disclosure on the landing page: "Gameplay data is collected to train AI models. No personal information is captured." Link to a privacy policy page.


6. Recommendations

Go/No-Go by Game Complexity

Category Verdict Confidence Notes
Turn-based 2-player (chess, cards, trivia) GO High Simplest to build, AI generates reliably, minimal server load
Casual real-time 2-player (Tetris battle, cooperative Breakout) GO High WebSocket at 10-20 Hz is well within Jetson capacity
Action real-time 2-player (Pong PvP, Asteroids deathmatch) GO Medium Needs careful netcode; latency through Cloudflare tunnel is the risk factor
Real-time 4-player (Snake arena, party games) CONDITIONAL GO Medium Works for casual games; action games at 4-player need testing
Real-time 8+ player (battle royale, MMO-lite) NO-GO for now High Exceeds Jetson capacity quickly; defer to Phase 3 with cloud servers
Persistent world / MMO NO-GO High Wrong architecture entirely for this platform

Suggested Architecture

                    Cloudflare Tunnel
                          |
                        Nginx (:8099)
                       /      \
              Static files    /api/* proxy
              (game HTML)        |
                          +------+------+
                          |             |
                    Ingest Hub     Game Server
                    (:8090)        (:8095, new)
                          |             |
                     NVMe /ssd     Room Manager
                                   /    |    \
                                Rooms  Lobby  Matchmaker

Game Server stack: Node.js with ws library. Single process, event-driven. Each game type registers a room handler. The server framework handles connection management, room lifecycle, and state broadcasting. Individual game logic is a ~100-200 line module per game.

Client integration: Each multiplayer game HTML file imports a shared multiplayer.js client library (similar to how recorder.js is shared today). This library handles WebSocket connection, lobby UI, and state sync. The game-specific code implements onStateUpdate(state) to render and sendInput(input) to act.

Priority Order for Implementation

  1. Week 1-2: Build the WebSocket game server framework and multiplayer.js client library
  2. Week 2-3: Pong PvP (simplest real-time multiplayer -- two paddles, one ball, already has CPU opponent logic to reference)
  3. Week 3-4: Tetris Battle (side-by-side competitive with garbage lines -- independent game states with async events)
  4. Week 4-5: Turn-based card game (demonstrates the HTTP polling path and broadens the game catalog)
  5. Week 5-6: Snake Arena (4-player, tests scaling beyond 2-player)
  6. Week 6+: Additional games generated by AI, one per week, using the established framework

Risk Factors and Mitigations

Risk Likelihood Impact Mitigation
Cloudflare tunnel latency too high for action games Medium High Measure actual latency first; fall back to casual-only if >150ms consistently. Consider Cloudflare Spectrum for WebSocket optimization.
Jetson RAM pressure from concurrent services Medium Medium Add a resource monitor that pauses Ollama model loading when game server is under load. Set memory limits with cgroups.
AI-generated netcode has subtle sync bugs High Medium Build comprehensive server-side state validation. Log desync events. Use deterministic lockstep for simple games.
Low player count makes matchmaking frustrating High High Implement bot backfill -- if no human opponent is found in 10 seconds, spawn an AI opponent. This also generates useful human-vs-bot training data.
Data storage fills NVMe at scale Medium Medium Implement daily archival to Cloudflare R2. Keep only last 7 days on local NVMe. Estimated cost: $5-10/month.
Security vulnerabilities in game server Medium Low Games have no real stakes (no money, no accounts). Basic input validation and rate limiting are sufficient. WebSocket origin checking prevents cross-site attacks.

Final Assessment

Multiplayer for OpenArcade is not only feasible but strategically valuable. The combination of low-complexity 2D games, an already-functional data pipeline, and the Jetson's adequate-for-small-scale compute makes this a natural next step. The key insight is that the multiplayer infrastructure (server framework, matchmaking, state sync) only needs to be built once, and then AI can generate game after game on top of it -- the same pattern that made the current 7 single-player games possible.

Start with Pong PvP. It is the simplest possible real-time multiplayer game, it already exists as a single-player game in the catalog, and it will immediately validate whether the Cloudflare tunnel latency is acceptable. Everything else follows from that answer.