Risor vs Lua

Lua is the most established embedded scripting language, powering game engines, Redis, Nginx, and many other systems. But Go implementations have largely stopped active development, and Lua's conventions (1-based indexing, global-by-default variables) are unfamiliar to most developers today.

Risor is a newer alternative with TypeScript-like syntax, an opt-in sandbox, native JSON types, and built-in collection operations.

Syntax

Lua:

local users = {
    {name = "Alice", role = "admin", active = true},
    {name = "Bob",   role = "viewer", active = false},
    {name = "Carol", role = "admin", active = true},
}
 
local admins = {}
for _, u in ipairs(users) do
    if u.active and u.role == "admin" then
        table.insert(admins, u.name)
    end
end
table.sort(admins)

Risor:

let users = [
    {name: "Alice", role: "admin", active: true},
    {name: "Bob",   role: "viewer", active: false},
    {name: "Carol", role: "admin", active: true},
]
 
let admins = users
    .filter(u => u.active && u.role == "admin")
    .map(u => u.name)
    |> sorted

Risor also has try/catch as an expression and distinct list/map types that round-trip cleanly to JSON (Lua tables are ambiguous).

Comparison

PropertyLua (via gopher-lua)Risor
Sandbox modelFull access (opt-out)Empty (opt-in)
Feature controlRemove globalsHost chooses which features to enable
Indexing1-based0-based
VariablesGlobal by defaultBlock-scoped (let)
JSONLibrary-dependent, fragileNative list/map types
CollectionsManual loops.map(), .filter(), .reduce(), pipes
SyntaxLuaTypeScript-like
Go ecosystemgopher-lua (stable, not actively developed)Actively developed

Performance

Risor is faster than GopherLua across all three scenarios in our benchmarks, and the memory gap is dramatic.

For simple expressions, Risor evaluates in 15.2 µs versus GopherLua's 29.0 µs (1.9×). At scale the gap widens: Risor processes 10,000 records in 4.20 ms versus 7.62 ms (1.8×), and runs business logic in 273 µs versus 611 µs (2.2×). GopherLua's imperative loop model and heavy per-value boxing add up at scale.

Memory is where it gets stark. A compiled Risor instance uses 2.2 KB for a simple expression; GopherLua allocates a full Lua VM state at 179.8 KB. For business logic, Risor uses 7.6 KB versus GopherLua's 1,889 KB (249×). Running thousands of concurrent instances becomes impractical with GopherLua at those numbers.

ScenarioGopherLuaRisor
Simple expression (warm)29.0 µs15.2 µs
Data processing (10k records)7.62 ms4.20 ms
Business logic (500 records)611 µs273 µs
Heap per instance (simple)179.8 KB2.2 KB
Heap per instance (business)1,889 KB7.6 KB

When to Choose Lua

  • Your users already know Lua (game dev, Redis scripting)
  • You're embedding in C/C++ where Lua's FFI is unmatched
  • You need general-purpose scripting and trust the code

When to Choose Risor

  • Your team knows JavaScript/TypeScript, not Lua
  • You want an opt-in sandbox with host-controlled features
  • You're working with JSON-heavy data

Learn More


Risor © 2026 Deep Noodle