DEV Community

dev game
dev game

Posted on

Why Balatro Bet on LÖVE and Lua: The Niche Stack Behind a 5-Million-Copy Poker Roguelike

Balatro should not have worked. A solo developer, a poker roguelike with no combat, and a 2D framework most Unity developers have never opened — yet it sold more than 5 million copies by January 2025, won Game of the Year at the 25th Game Developers Choice Awards, and was nominated for top honors at The Game Awards 2024, the D.I.C.E. Awards, and the BAFTAs.

The short answer for developers is this: Balatro was built by LocalThunk in LÖVE (love2d.org), a free, open-source 2D framework written in C++ that uses Lua as its scripting language. That niche choice shaped everything from its deterministic randomness to its hypnotic background to its explosive mod scene.

This article explains what LÖVE actually is, why Lua fit a solo card game, and what I think the rest of us are missing about constraints, randomness, and moddability.

Who this is for

You are an indie or hobbyist game developer choosing a stack, or a technically curious Balatro player wondering why the game feels so responsive and moddable. You do not need to know Lua. You do need to care about shipping scope: one person, 2.5 years, ten platforms.

Scope as verified in October 2026: Balatro released for Windows, Switch, PlayStation 4/5, Xbox One and Series X/S on February 20, 2024, for macOS on March 1, 2024, and for Android and iOS on September 26, 2024. Engine is listed as Löve across reference sources. The developer is solo developer LocalThunk, publisher is Playstack.

What LÖVE actually is — and how niche it is

LÖVE is an awesome framework you can use to make 2D games in Lua. It is free, open-source under the liberal zlib/libpng license, with no commercial restrictions, and it runs on Windows, macOS, Linux, Android and iOS.

Under the hood it is not a toy. The framework itself is written in C++ and exposes video and sound through SDL and OpenGL (and OpenGL ES 2/3 since 0.10), with fonts via FreeType. Current stable is 11.5 from December 3, 2023; version 12.0 was in development at last review. Its feature list is deliberately 2D-focused: OpenGL pixel shaders in GLSL, touchscreen and joystick support, PNG/JPEG/GIF/TGA/BMP images, WAV/OGG/MP3 audio, OGV video, optional Box2D physics, and TCP/UDP networking via LuaSocket plus Enet over UDP.

How niche? In July 2018 it was the 10th most popular tool among indie developers on Itch.io with a 1.97% share, far behind Unity, Unreal and Godot. Reference coverage explicitly calls out that Balatro, built with LÖVE, became a commercial hit without a mainstream engine such as Unity, Unreal Engine, or Godot. The official LÖVE homepage now lists Balatro first among example commercial games.

That is the niche-plus-popular contrast: a ~2% framework powering a 5-million-copy cultural hit.

Why Lua fit a one-person poker game

Lua is a powerful, efficient, lightweight, embeddable scripting language maintained at PUC-Rio in Brazil. It is dynamically typed, runs bytecode on a register-based VM, and uses incremental garbage collection.

Its design pitch maps almost 1:1 to Balatro's needs:

  1. Small and fast to iterate. The Lua 5.5.1 tarball is 390K compressed, ~32,000 lines of C; the interpreter plus standard library is under 800K on 64-bit Linux. For a solo dev treating the game initially as a side project for a résumé, that means instant restart, no 10-GB editor, no build pipeline fight.

  2. Embeddable and extensible. Lua has a simple C API for calling both directions. LÖVE exploits this: C++ does SDL/OpenGL heavy lifting, Lua does game logic. You can see the pattern in the official starter snippet — function love.draw() love.graphics.print("Hello World!", 400, 300) end — the whole game loop is three callbacks: load, update, draw.

  3. Proven in games. Lua is described as currently the leading scripting language in games, used in World of Warcraft, Angry Birds, Photoshop Lightroom scripting and embedded TV middleware. Balatro inherits that lineage: data-driven jokers, decks and vouchers are natural Lua tables, not class hierarchies.

Balatro's core loop — antes of three blinds, limited hands and discards, Chips x Mult scoring, 150 jokers at launch with Foil/Holographic/Polychrome/Negative variants — is essentially table manipulation plus seeded randomness. Lua tables make that joyful. A Unity ScriptableObject graph would also work, but would add editor overhead a solo dev did not need.

Deterministic randomness: the hidden systems design

Here is where verified facts end and careful analysis begins. I label it clearly.

Verified: Balatro is a single-player roguelike deck-builder where each run uses antes, blinds, shops, booster packs and jokers. Its rules and scoring (Chips multiplied by Mult) are documented in reference coverage. LÖVE provides seeded random generators that make deterministic runs practical.

My analysis: The most interesting technical decision is not that Balatro is random, but that it is deterministically random with isolated streams. LÖVE's random-generator API makes it cheap to implement what Balatro appears to do: one master seed per run, plus derived generators per system so rerolling the shop does not corrupt your next card draw.

Why does that matter? Most roguelikes use one global RNG. If they do, every random call shifts every future outcome, which makes debugging hell and makes seeded runs irreproducible after a patch adds one extra roll. Separate streams isolate luck. You can balance the shop economy without accidentally buffing flush draws.

My provocation: Balatro's addictiveness is not luck, it is legible luck. Because outcomes are deterministic given a seed, skilled players learn to manipulate probability mass — discard to thin suits, stack economy jokers to afford rerolls — rather than pray. Randomness becomes a resource you farm. If you are designing a roguelike, ask: does your RNG have one tap or many faucets? One tap feels unfair. Many faucets feels strategic, even if the total variance is identical.

Open questions I cannot resolve from public sources alone: exact seed derivation formula, whether ante scaling reseeds streams, and how mobile ports preserve determinism across ARM vs x86 floating point. Those would require source access. I leave them open deliberately — they are good modding research prompts.

Juice without a 3D engine: shaders and game feel

Verified capability: LÖVE supports OpenGL pixel shaders in GLSL and mesh/effect improvements since 11.0, including the effect method for shaders.

Observation + inference: Balatro's signature is not photorealism. It is a wobbling, liquid background, CRT curvature, card tilt, screen shake, and pitch-bending chip ticks. All of that is achievable with a single fullscreen GLSL shader plus sprite transforms — exactly what LÖVE is good at.

A mainstream engine would give you a shader graph, post-processing stack, and overhead you do not need for cards. LÖVE lets you write a short GLSL shader directly. For a poker game, constraint wins: you spend juice budget on feedback (Mult popups, dollar sounds) instead of lighting.

My divergent take: Balatro proves that game feel is resolution-independent. Players remember the background swirl more vividly than many AAA ray-traced reflections because the swirl never stops moving. Motion is branding. If your game has one screen players stare at for 100 hours, animate that screen with a shader, not a loading-screen logo. What would your game look like if you were forbidden from adding polygons and only allowed to warp pixels?

Moddability as architecture, not accident

Lua is text. LÖVE games ship as fused archives containing Lua source. That makes modding almost inevitable.

The community response is Steamodded (SMODS), with full install guides for Windows, Linux and Mac and a Your-First-Mod tutorial. Notably, Steamodded explicitly does not support Google Play / App Store versions — you must own the Steam version to mod on mobile. The official Balatro Discord also restricts non-desktop modding discussion, pushing mobile modders to the Steamodded Discord.

This is not a footnote. It is a growth loop: Lua modders add new jokers, decks and crossovers in days, streamers showcase them, base-game sales rise, more modders arrive. Unity games can be modded too, but IL2CPP and AssetBundles raise the bar. Balatro lowered it to edit a Lua table.

My question for you: did LocalThunk choose LÖVE because it was moddable, or did moddability emerge and then amplify success? I suspect the latter, and that is the lesson. Pick a stack where the community can extend you without your permission. If your engine choice requires an SDK, NDA or proprietary bundle format, you are taxing your evangelists.

Try the math in a browser (no download)

You do not need to install Balatro to train the two skills it rewards: compounding numbers and think-ahead planning. These free browser games isolate one half each:

  • If you want to feel Chips x Mult compounding, play 2048 Blocks Merge. You match and merge block tiles to create increasingly large numbers to 2048 and beyond, with powerups when you misdrop. Treat each merge like a Mult trigger: the lesson is the same as Balatro's — small early combinations snowball, and one mistimed merge early costs you ten moves later.

  • If you want to practice Joker-like planning, play Master Chess. It follows full chess rules with castling, en passant and promotion, plus adjustable AI and local two-player. Balatro is chess with poker hands instead of pieces — control the middle, develop economy first, avoid trapping yourself behind your own discards. A few slow games against the AI make Balatro's hold-back-and-build openings feel natural.

Neither clones Balatro. They separate exponential scoring from positional patience so the original's design reads clearer when you return.

What to steal (and what not to copy)

Steal this if you are solo or small:

  • Choose boring tech that removes categories of work. No 3D, no netcode, no server. LÖVE removed the editor, the asset pipeline and the licensing negotiation.
  • Separate RNG streams from day one. Even if you never expose seeds, you will thank yourself when balancing.
  • Ship one fullscreen shader as identity. Cheap, memorable, portable.
  • Keep game data in human-readable tables. Future modders are future marketers.

Do not romanticize:

  • LÖVE gives you no editor, no visual debugger, no console certification help. Balatro's ten-platform porting required publisher Playstack and porting partners. Solo plus LÖVE does not equal solo to Switch.
  • Lua's dynamic typing and 1-based arrays bite on large teams. What is joyful at 20k lines is fragile at 200k.
  • Deterministic RNG can feel rigged if players discover patterns. Transparency needs UI work — odds displays, run history — or trust erodes.

Verdict

Balatro did not succeed despite LÖVE and Lua. It succeeded because a niche, lightweight stack let one person iterate on cards, numbers and juice for 2.5 years without fighting an engine built for someone else's game. The official site's tagline calls it a hypnotically satisfying deckbuilder where you play illegal poker hands and trigger outrageous combos — that hypnosis is engineering as much as design.

If you are starting a 2D systems game in 2026, ask the Balatro question: what can I delete? If the answer is the editor, the third dimension, and half your RNG, LÖVE plus Lua still deserves a prototype weekend — even if you later port to Godot or Unity for consoles.

What niche constraint would make your game more distinctive, not just cheaper? I do not have a rigorous answer. I think the question is more useful than any benchmark.

Sources and verification date

Core facts verified October 13, 2026 via direct retrieval and re-checked October 18, 2026 (Steam system requirements: 1 GB RAM, 150 MB storage, OpenGL 2.1 graphics; LÖVE homepage lists Balatro first). Analysis and provocations are my own and labeled as such.

  • Engine, release dates, 5M copies, awards and roguelike deck-builder rules
  • LÖVE open-source license, platforms and Balatro as featured game
  • LÖVE C++/Lua/SDL/OpenGL architecture, GLSL shader support and 1.97% Itch.io share
  • LÖVE Lua framework description and repo activity
  • Lua lightweight/embeddable/fast/portable design
  • Steamodded install and mod-creation docs and mobile limitation
  • Official Balatro tagline: hypnotically satisfying deckbuilder
  • Browser-trainer descriptions from EasyHub 2048 Blocks Merge and Master Chess

Top comments (0)