Enterprise Architecture for the PlayStation 2: Inside jpd002/PlayServices

How a solo developer used clever AWS hacks and a C++ to C# pipeline to build a modern cloud-save engine for a two-decade-old console.

6 min read · jpd002/PlayServices

A modern server rack with a transparent PlayStation 2 memory card slotted into a drive bay, illustrating the blend of retro gaming and modern cloud infrastructure.
PlayServices bridges the gap between local emulation and cloud-native infrastructure.
Key Takeaways

Cheating the Alphabet in AWS S3

Amazon S3 is excellent at storing files. S3 is remarkably bad at functioning like a time-series database. When a user boots up a game, the emulator needs to instantly fetch their most recent cloud save. S3 has no native query to get the latest file without fetching the entire bucket contents and sorting them locally.

The solution in GameDataService.cs is a masterclass in exploiting platform quirks. The developer forces S3 to do the sorting by naming files using a reverse index. By subtracting the save version number from the maximum possible integer, the newest file mathematically becomes the first file alphabetically.

string s3Key = $"{userId}/{gameId}/{uint.MaxValue - saveVersion}.ps2";
// Version 10: 4294967285.ps2
// Version 11: 4294967284.ps2 (Appears first in alphabetical sort)

This allows the service to perform a simple list request with a limit of one. The most recent save is always returned instantly. Beyond sorting, the server issues pre-signed URLs to the client. The emulator uploads its 8MB memory card files directly to S3. The C# backend never touches the binary data, reducing server bandwidth costs to absolute zero.

MetricTraditional FlowPlayServices Flow
Bandwidth CostHigh (Server proxies all files)$0.00 (Client talks to S3)
Server LoadHeavy I/O processingLightweight token generation
Client FlowClient -> Server -> DatabaseClient -> Server (auth) -> S3 (data)
Bottleneck RiskServer network interfaceNone (Distributed via AWS)

The S3 Reverse Index Hack in action.

A Triple-Play Architecture

Building a cloud ecosystem for an emulator requires bridging radically different computing domains. The PlayServices repository manages this by splitting the workload across three distinct languages and environments.

The native client uses high-performance C++ to interface with local SQLite databases, tracking game serials like SLUS-20002. The backend is a scalable C# ASP.NET Core application orchestrating the cloud logic. Finally, a TypeScript and React web frontend gives users a modern dashboard to manage their synchronized data.

A pocket watch mechanism laid open with three interlocking gear types spinning in synchronization.
Three distinct environments (C++, C#, TypeScript) working in unison.

The Serverless Build Tracker

The infrastructure also functions as a deployment pipeline. The BuildsController.cs file bridges the GitHub repository with the end-user. When thousands of emulator clients check for updates simultaneously, hitting the GitHub API directly would result in immediate rate-limiting.

To solve this, the developer implemented a 60-second TTL cache in DynamoDB. The server only queries GitHub if the cached commit metadata is older than a minute. This shields the upstream API while providing near real-time update notifications to users globally.

Patreon as an Identity Provider

Authentication is strictly required to keep cloud saves private. Instead of defaulting to Google or GitHub OAuth, the developer made a highly practical business decision. PlayServices uses Patreon's API as its primary Identity Provider.

The backend maps Patreon OAuth tokens to internal GUIDs. This effectively gates premium cloud infrastructure to active project supporters. It ensures the solo developer can afford the AWS hosting costs while maintaining strict data isolation between users.

A bank vault door where a mechanical ticket dispenser hands a stamped entry pass to a robotic hand.
Using Patreon tokens as temporary entry passes for AWS resources.