Skip to content
Behind the Games

Building Games That Work on a Five-Year-Old Phone

Vanilla JavaScript, small bundles, code-splitting, and a steady 60fps. How we build games that run on old phones, and why that is really about reach.

By The 666 Game Team ·

Somewhere in a drawer, or in a kid’s hand, or being used as a backup device, there is a phone that came out five years ago. It has a slower processor than this year’s models, a fraction of the memory, and a battery that has seen better days. For a huge number of people around the world, that phone is not the backup — it is the phone. If a website only works well on a brand-new flagship, it does not work for them.

We build our games to run on that five-year-old phone. Not “technically load,” but actually play smoothly. This post is about the choices that make that possible, why they are not the choices most modern web games make, and why we think it matters more than a longer feature list ever could.

Vanilla JavaScript, no game engine

The biggest decision is one we made before writing a single game: we do not use a game engine or a heavy framework. Our games are written in plain JavaScript — often called vanilla JavaScript — talking directly to the browser’s built-in canvas and DOM.

Game engines are wonderful tools. They give you physics, asset pipelines, scene graphs, and a hundred conveniences. But they also arrive as a large bundle of code that the phone has to download, parse, and keep in memory before your game even starts. For a big, complex 3D game, that trade is worth it. For a Snake board or a sliding puzzle, you are shipping a moving van to deliver an envelope. All that engine code costs download time, startup time, and memory — three things a five-year-old phone has the least of.

Writing the games ourselves in plain JavaScript means the only code on the page is the code that specific game actually needs. A puzzle that could be described in a few hundred lines ships as a few hundred lines, not as a few hundred lines riding on top of a framework many times its size.

Small bundles, because bytes are time

On a fast laptop with fiber internet, the size of a web page barely registers. On an older phone with a spotty mobile connection, every kilobyte is time. Time to download over the network, and then — the part people forget — time for the phone’s processor to parse and execute that JavaScript once it arrives. A slower chip parses code more slowly, so a big bundle hurts twice: once on the network and once on the CPU.

So we keep our bundles small on purpose. We avoid pulling in large libraries for things we can write compactly ourselves. We lean on features the browser already provides for free rather than shipping our own version of them. The goal is that when you tap a game, it is playable almost immediately, even if your connection is slow and your phone is old. A small bundle is the single most reliable way to get there.

Code-splitting: only load the game you opened

Here is a trap that is easy to fall into. You have a dozen games, so you bundle all of them together and send the whole collection to every visitor. Now someone who just wants to play Snake is downloading the code for Minesweeper, the memory match, the word guesser, and everything else — code they may never touch.

We avoid that with code-splitting. Each game is its own separate chunk of code, and the browser only downloads the chunk for the game you actually open. Land on the Snake page and you get Snake’s code, and only Snake’s code. The rest stays on the server until and unless you ask for it. This keeps the amount each visitor downloads proportional to what they are actually doing, which is exactly the behavior you want on a limited connection and a limited device.

Aiming for a steady 60 frames per second

Smoothness is not decoration. When a game runs at a steady 60 frames per second, it feels responsive and fair — the snake turns exactly when you swipe, the falling block lands where you expect. When the frame rate stutters and drops, controls feel laggy and mushy, and on an action game that is the difference between a fair loss and a cheap one. Old phones are precisely where frame rates tend to fall apart, so this is where the care pays off most.

Hitting 60 frames per second means each frame has to be drawn in about 16 milliseconds. That is not a lot of time, so we protect it. A few of the habits that keep us inside that budget:

  • We let the browser set the pace. We schedule drawing through the browser’s own animation timing rather than firing updates on arbitrary timers, so the game draws in sync with the screen and never does work for a frame nobody sees.
  • We only redraw what changed. Repainting an entire board every frame when a single tile moved is wasted work. Keeping each frame’s work small is how a slower processor keeps up.
  • We do not fight the garbage collector. Creating piles of temporary objects every frame forces the browser to pause and clean up memory, and those pauses show up as stutters. Reusing objects and keeping the per-frame footprint low keeps the motion smooth.

None of these are exotic. They are just discipline applied in the hot loop where it counts.

Why this is really about accessibility and reach

It would be easy to file all of this under “engineers being tidy.” It is not. It is about who gets to play.

The newest, fastest phones belong to a relatively small and relatively wealthy slice of the world. Most devices in most hands are a few years old, mid-range, or hand-me-downs, and a great many of them are in places where mobile data is metered and expensive. If our games demanded a recent flagship and a fast connection, we would be quietly telling most of the planet that these games are not for them. Building light is how we say the opposite.

There is a straightforward accessibility angle too. A game that runs cool and smooth is easier on someone whose phone overheats, kinder to a nearly dead battery, and less likely to freeze up someone who is relying on an assistive setup layered on top of an already-strained device. Performance is not separate from accessibility — for a lot of people, performance is the access.

And here is the quiet bonus: everything we do to make a game run on an old phone also makes it feel instant on a new one. Small bundles, fast starts, and steady frame rates are not a compromised experience for high-end users. They are just a good experience for everyone. Building for the weakest device in the room turns out to be the most reliable way to build well for the whole room.

Try it on whatever you’ve got

The real test is the one in your pocket. Open a game on your oldest device and see how fast it starts and how smoothly it plays. Snake is a good stress test for smoothness, and Minesweeper for fast starts. If you want to see the same care applied to gameplay rather than performance, our write-up on Minesweeper’s first-click guarantee is a good next read.

Frequently asked questions

Why not use a game engine?
Engines ship a large bundle the phone must download, parse, and keep in memory before the game starts. For small puzzle games, plain JavaScript ships only the code the game actually needs.
Why do small bundles matter on old phones?
Every kilobyte is time twice over: time to download on a slow connection, and time for a slower processor to parse and run the code. Smaller bundles start playing sooner.
What is code-splitting and why use it?
Each game is a separate chunk, so opening Snake downloads only Snake's code. You never download games you did not open, which suits limited connections and devices.
Why aim for 60 frames per second?
A steady 60fps keeps controls responsive and fair. Stutters make inputs feel laggy, which matters most on older phones where frame rates tend to drop.
How do you keep the frame rate steady?
We draw in sync with the browser's animation timing, only redraw what changed, and avoid creating piles of temporary objects that trigger memory-cleanup pauses.
Why does old-phone performance matter so much?
Most phones in most hands are a few years old or mid-range, often on metered data. Building light keeps the games playable and accessible for far more people.

← All posts Play a game