Lukas Vogel ported the original Doom’s game logic and 320×200 renderer to SQL. Python handles only timing, input, and displaying the bitmap. The impressive part isn’t that SQL can run a game; it’s the unusually clear account of where a relational model helps and where it becomes an expensive workaround.

The architecture makes the trade-offs visible:

  • A fixed 35 Hz game loop updates state tables; rendering is a separate query over that state.
  • Doom’s map data and entity behaviors map naturally to tables, joins, and bulk updates. Weapons and animations become inspectable, editable data.
  • The renderer uses 89 CTEs to generate pixels; window functions stand in for mutable clipping state, and a per-pixel MIN resolves overlapping fragments.
  • That depth-resolution step alone costs about 8.2 ms on average. The original renderer avoids the work through careful ordering.

The database earns its keep somewhere less flashy: transactions give multiplayer clients consistent snapshots of each game tic, while restricted roles expose only a small input API. Vogel reports roughly 60 FPS on his laptop in typical scenes, dropping to 35 in busy ones — measurements of this implementation, not an argument to build every game in SQL.

A good constrained-engineering experiment admits which abstractions fit the problem and measures the price of the ones that don’t.