· 3 min read

Backend work on a live online game

by · Project: Age of Pirates Online

#age-of-pirates-online #backend #performance #security

In June 2026 I worked as a backend engineer on Age of Pirates Online, an online game that is already running with real players. The work covered three areas: adding a payment API, making the backend and website faster, and hardening the communication between the game server and the website.

Since this is a production system, this post stays at the level of what was done and why, not how the internals are built.

Working on a system that is already live

The main constraint on a live game is that players are online while you change things. A change that breaks sessions in progress, or needs a long maintenance window, is felt by players immediately. That applies to all three pieces of work below.

Payments

The first task was integrating Xsolla payments into the website, starting from nothing. Payments are the part of a game's backend where mistakes cost the most, both for players and for the operator. A player who pays should receive what they paid for exactly once, even if a request is retried or a callback arrives twice. A request that does not come from the payment provider should never be able to grant anything.

Performance: about 30% on both sides

The second task was speed, measured on two separate things:

  • Server-side processing got about 30% faster.
  • Website load time dropped by about 30%.

These are different problems. Server-side time is about how much work each request does before it can answer. Load time is what the player actually waits for in the browser, which also depends on how much is sent and in what order. A faster server does not automatically mean a faster page, so the two are worth tracking as separate numbers.

On the website, the main problem was that it tried to load everything at once. The fixes were:

  • Paginated JSON, so a page asks only for the data it shows.
  • Preloading, so the next thing the player needs is already on its way.
  • A transfer budget of about 2 MB per load, as a hard limit rather than a goal.
  • Untangling deeply nested code, which made the flow easier to follow and change.

On the server, the stack is C and PHP. The gains came from two changes:

  • Moving work off the main thread onto helper threads, so one slow task no longer holds up everything behind it.
  • Running low-value job types less often, since some job types were rarely needed but still ran often.

Protecting the link between the game server and the website

The game server and the website exchange data through a set of API gateways. Those gateways were exposed to the same traffic any public service gets, and some of it was hostile:

  • UDP floods, which try to overwhelm a service with volume.
  • Bots that ignore rate limits, hammering endpoints far faster than a real player would.
  • Other automated attacks aimed at the gateways.

I hardened the communication on the gateways that needed it, so that this traffic is blocked before it reaches the parts that serve real players. That meant banning IPs that keep abusing the service, filtering UDP floods, and putting a CDN protection layer in front. The goal was not to make the system unreachable to attackers in theory, but to make sure legitimate traffic keeps working while this kind of traffic is going on.

Around that, I set up a baseline for the server itself: tighter access control, automated backups, resource monitoring with crash alerts, scheduled restarts, and a review of file permissions.

Seeing what is happening

Blocking traffic is only half of it; the owner also needs to know what is going on. Instead of a one-off stress test, I set up an hourly report to the owner's Discord. It covers traffic, how requests are distributed across IPs, access attempts, and attacks on each endpoint. That turns "the server felt slow last night" into something you can look up.

Takeaways

  • On a live system, measure server time and page load separately, so improvements are numbers rather than impressions.
  • Treat payment handling as the part that must never double-grant or accept a forged request.
  • Protect the internal connections between services, not only the public website.
  • Report on traffic and attacks regularly, so problems show up in numbers before players complain.