If you’ve ever embedded a scripting language into a Go application, you’ve felt the pain. The stack-based C API, the impedance mismatch, the memory bloat that makes you question every life choice that led you to that line of code. You’ve probably tried GopherLua or go-lua, and they worked — until they didn’t. Until your object graph hit 9 MB and your memory usage exploded to 785 MB. That’s not a bug. That’s a design flaw.
Lunar is a new Lua 5.1 VM written entirely in Go, and it just proved that the problem isn’t Lua — it’s the way we’ve been embedding it. The biggest bottleneck in embedded scripting isn’t the script execution — it’s the API impedance mismatch between the host language and the VM. Lunar doesn’t just optimize the old approach; it discards the 30-year-old C stack paradigm entirely.
Here’s what that means in practice: loading the same 9 MB CBOR-derived object graph (hundreds of thousands of tables) allocates about 107 MB versus 785 MB with GopherLua. After garbage collection, Lunar retains 72 MiB while GopherLua holds onto 542 MiB. That’s a 7x improvement in memory efficiency. And it’s faster too — 1.5x to 2x faster in typical benchmarks.
How? Lunar abandons the Lua C API’s stack-based interface in favor of typed Go values and callback frames. Libraries and script-file access are opt-in, meaning the host explicitly controls what Lua code can access. This isn’t an optimization — it’s a fundamental rethinking of what a Go-embedded VM should be. The result is a VM that feels native to Go, not like a foreign object bolted onto the side.
The creator of Lunar, who built this for his own game project (runemud.com), knew the pain firsthand. He spent years working with existing Lua VMs and realized the only way forward was to start from scratch. Sometimes the best way to fix a bottleneck is to burn the old stack to the ground.
This isn’t just about numbers. It’s about the deep satisfaction of seeing a clean, from-scratch rewrite that crushes legacy implementations in both speed and memory. It validates the bold choice to start over rather than patch an existing library. For Go developers who need to embed scripting, Lunar isn’t just an alternative — it’s a wake-up call. The old way is broken. The new way is here.
FAQ
Q: Is Lunar production-ready?
A: Not yet. The public API is still stabilizing. The creator explicitly asks for feedback on the embedding design and Go interface. But the benchmarks are real, and the architecture is solid enough to start experimenting with.
Q: What practical difference does this make for a Go developer?
A: If you're embedding Lua to handle complex configuration, game logic, or user scripts, Lunar cuts memory usage by up to 85% and improves execution speed by 50-100%. That means smaller instances, lower costs, and faster response times.
Q: Isn't this just a niche optimization? Lua in Go is already uncommon.
A: The principle here is bigger than Lua. Lunar proves that the dominant embedding pattern (inherited from C) is fundamentally flawed for modern languages. The same impedance mismatch exists in Python, Rust, and any language that wraps C-based VMs. This is a blueprint for the next generation of embedded scripting.