Technology8 min read

Someone Got Doom Running in an SQL Database

A developer rendered Doom in an SQL database using 1,300 lines of SQL and CedarDB tables — generating full-color 640x480 frames at 35 fps. Here's how SQLDoom works.

Someone Got Doom Running in an SQL Database

Key takeaways

  1. 1What Is SQLDoom and Why Does It Exist SQLDoom is not a game you'd ship to production.
  2. 2The result was something considerably humbler: a raycasting engine that produced grayscale ASCII graphics, more reminiscent of Wolfenstein 3D's austere 90-degree corridors than Doom's iconic hellscapes.
  3. 3Where DoomQL could only approximate the look of a pre-Doom era game, SQLDoom generates frames visually indistinguishable from the original 1993 executable.
  4. 4Lukas Vogel looked at a query language designed for business data and asked what it would take to get a 1993 shooter running inside it.
Sections · 6

There's a long, proud, slightly unhinged tradition in software engineering: getting Doom to run on things it has absolutely no business running on. A pregnancy test. A receipt printer. A John Deere tractor dashboard. Each new entry in this catalog of absurdity earns a nod of respect from developers who understand exactly how much creative suffering went into the feat. The latest addition to this hall of fame is Doom in SQL database — specifically, developer Lukas Vogel's SQLDoom project, which renders full-color, 640x480 frames of id Software's 1993 classic using a database query engine as its rendering backbone. It is, by Vogel's own admission, "obviously a bad idea." That's exactly why it matters.

What Is SQLDoom and Why Does It Exist

SQLDoom is not a game you'd ship to production. It is not a framework, a library, or a template for building real-time interactive software. What it is, precisely, is a proof of engineering will: a demonstration that the structured query language — designed in the 1970s to retrieve rows from relational tables — can be bent, stacked, and coerced into rendering a game that defined first-person shooters for a generation.

Vogel built SQLDoom on top of CedarDB, an analytical database system positioned as a high-performance alternative to workhorses like PostgreSQL and SQLite. The distinction matters. Most relational databases are optimized for transactional workloads — lots of small reads and writes, row-level operations, index lookups. CedarDB, by contrast, is built for analytical queries: complex expressions, aggregations across large datasets, and vectorized execution that can crunch numbers fast. That architectural difference is the reason Doom in SQL database is possible at all. Running the same query workload against vanilla SQLite would almost certainly produce slideshow-level performance. CedarDB's query engine can sustain the throughput that animated geometry and per-frame state updates demand.

The project architecture is honest about its compromises. A thin Python client handles the pieces SQL genuinely cannot: capturing keyboard input, managing the game's timing loop, and pushing each rendered frame to the screen. Everything else — the geometry, the game state, the actual pixel-by-pixel frame construction — lives inside the database.

How SQLDoom Actually Works

How SQLDoom Actually Works — a rectangular object with a light on it
How SQLDoom Actually Works — a rectangular object with a light on it

Here's where the engineering gets genuinely impressive. Vogel represents the Doom game world inside a series of CedarDB tables. Map geometry, enemy positions, player state, sector lighting — all of it lives as relational data. Then, on every frame tick, a cascade of SQL queries transforms that data into a rendered image.

Read next Laika's Wildwood: Stop-Motion Fantasy at TIFF 2026

The scale of the query infrastructure is worth sitting with: approximately 1,300 lines of SQL spread across 89 common table expressions, or CTEs. A CTE, for those unfamiliar, is a named subquery that lets you build up complex query logic in readable, reusable chunks — essentially the SQL equivalent of breaking a function into steps. Chaining 89 of them together to implement game logic is not something the SQL standard committee had in mind when they designed the WITH clause, but here we are.

The output of all this query machinery is 35 bitmap framebuffers per second. That's 35 frames per second, each one a complete 640x480 image generated entirely through database query execution. For context, classic Doom itself targets around 35 frames per second on period-correct hardware, so SQLDoom hits the original game's intended cadence — through a query engine. That number isn't just a fun fact; it's evidence that this is a real-time rendering pipeline, not a batch process that spits out images after a delay.

SQLDoom vs DoomQL: A Major Leap Forward

SQLDoom vs DoomQL: A Major Leap Forward — text
SQLDoom vs DoomQL: A Major Leap Forward — text

SQLDoom's achievement looks even larger when you place it next to Vogel's earlier attempt at the same basic problem. DoomQL, released the year prior, set out to build a multiplayer Doom-like shooter running entirely in SQL. The ambition was admirable. The result was something considerably humbler: a raycasting engine that produced grayscale ASCII graphics, more reminiscent of Wolfenstein 3D's austere 90-degree corridors than Doom's iconic hellscapes.

That's not a failure — Wolfenstein 3D is legitimately hard to render in SQL, and ASCII output is still output. But it illustrates the gap that SQLDoom closes. Where DoomQL could only approximate the look of a pre-Doom era game, SQLDoom generates frames visually indistinguishable from the original 1993 executable. Full color. Correct geometry. Recognizable enemies and environments.

The leap from ASCII grayscale to full-color 640x480 represents a qualitative shift, not just a quantitative one. It's the difference between a system that approximates game rendering and one that actually achieves it. The 89-CTE architecture, the CedarDB backend, the refined understanding of how to represent spatial data in relational tables — SQLDoom is the product of lessons learned from DoomQL's limitations.

Technical Challenges of Rendering a Game in SQL

SQL is a declarative language. You describe the data you want; the database figures out how to retrieve it. That design philosophy works beautifully for querying customer records or aggregating sales figures. It's actively hostile to the requirements of real-time game rendering, which is fundamentally procedural: process input, update state, compute geometry, output pixels, repeat sixty times a second.

The core challenge is state mutation. Relational databases, particularly when accessed through pure query layers, want to return results — not maintain mutable, frame-by-frame game state across thousands of tiny updates. Every frame of Doom requires player position updates, enemy AI ticks, projectile physics, and sector visibility calculations. Fitting all of that into a query model means expressing game logic as transformations on relational data rather than imperative instructions.

Common table expressions are the architectural key. Each CTE in Vogel's 89-expression chain represents a stage of the rendering pipeline — one CTE computes visible sectors, another calculates wall projections, another handles sprite sorting. The chain reads like a pipeline, with each stage feeding the next. It's an elegant solution to an ugly problem: using the compositional power of CTEs to simulate the step-by-step nature of a rendering loop within a fundamentally declarative system.

The Python client's role as a timing and I/O shim isn't a cop-out. Keyboard input and screen output are genuinely outside SQL's domain, and pretending otherwise would produce something less honest than what Vogel built. The boundary is clear: Python handles the operating system interface, SQL handles everything that constitutes the game.

What This Project Reveals About SQL's Hidden Power

SQLDoom's existence is a useful corrective to how most developers think about databases. The instinct, reasonable in most contexts, is to treat SQL as a data retrieval tool — get rows, filter them, aggregate them, return them to application code that does the real work. The database is the basement; logic lives upstairs.

What SQLDoom demonstrates is that the query layer itself is computationally expressive enough to implement non-trivial algorithms. The 89-CTE pipeline that renders Doom frames is, in essence, a small program written in SQL. It performs coordinate transforms, visibility culling, lighting calculations, and sprite compositing. None of those are tasks SQL textbooks describe. All of them are tasks SQL can perform, given the right database engine and enough patience.

CedarDB's analytical orientation is central to this. Systems like PostgreSQL and SQLite are not slow — for their intended workloads, they're excellently optimized. But they aren't built to execute 89 chained CTEs 35 times per second while maintaining consistent frame timing. CedarDB's vectorized execution model, which processes data in columnar batches rather than row by row, is precisely the kind of throughput profile that makes query-intensive real-time computation survivable. The choice of backend wasn't incidental to the project's success.

Takeaways for Developers and Database Enthusiasts

The practical applications of Doom in SQL database are, to be direct about it, approximately zero. Nobody is shipping a game engine backed by CedarDB CTEs. The 1,300 lines of SQL that Vogel wrote will not appear in any production codebase.

But that misses the point entirely. Projects like SQLDoom matter because they expand the mental model of what a given tool can do. Every developer who reads Vogel's blog post and traces the 89-CTE rendering pipeline comes away with a different sense of where SQL's limits actually are. Not where convention places them — where physics places them.

For database engineers specifically, SQLDoom is a stress test that reveals something real about CedarDB's query execution capabilities. Sustaining 35 bitmap framebuffers per second under a 1,300-line query workload is not a benchmark any database vendor would design, which makes it unusually honest as performance evidence. The database either keeps up or it doesn't. It kept up.

For everyone else, SQLDoom joins a long line of "can it run Doom" projects that collectively argue something worth remembering: constraints are only limitations until someone decides to treat them as interesting problems. Lukas Vogel looked at a query language designed for business data and asked what it would take to get a 1993 shooter running inside it. The answer turned out to be 89 CTEs, one Python shim, and a clearly documented admission that the whole thing is a bad idea. The best hacks usually are.

Related coverage


Source: Ars Technica - All content

Published

5 October 2026

Author

Editorial

Discussion

Be the first to respond.

No comments yet.

Leave a comment