Measured, not marketed
Every number is reproducible. So verify everything.
vodka's protection engine is a committed, reproducible project, not a black box you upload to and trust. Every number below comes from a harness you can run yourself, against the real Luau runtime (not inside a Roblox client), stamped with its seed and date.
The short version
In plain terms: your script is turned into something very hard to read or copy. Everything below is the proof, for the technically curious. You don't need to read any of it to use vodka.
Protection resistance
What survives an attack, measured.
| Metric | Default engine | VM engine |
|---|---|---|
| Strings recovered by grep (plaintext) · lower is better | 4% | 4% |
| Strings recovered by running the decoder · the honest ceiling | 100% | 100% |
| Integer literals surviving as plaintext · lower is better | 9% | 45% |
| Float literals recovered by grep · exact num / 2^k rewrite | 0% | 0% |
| Functions with flattened control flow · count | 61 | 2 |
| Functions virtualized to bytecode · count | 0 | 89 |
| VM bytecode words emitted · count | 0 | 1552 |
| Decoy (junk) functions injected · count | 41 | 41 |
| Renamed locals · count | 676 | 676 |
| Behaviour preserved vs real Luau · differential | 28/28 | 28/28 |
| Semantics still hidden after StyLua beautify | yes | yes |
Source: scripts/deobf_resistance.py (seed 1337) over the 24-program corpus plus three realistic samples (a secrets-like config, an FNV/LCG/bubble-sort algorithm, a Vector2 OOP class). Lower recovery is stronger; the harness deliberately reports where protection is weak.
What it defeats
- Casual grep and string-scraping: strings are byte-encoded, integers rewritten as reversible arithmetic, floats exact-rewritten.
- Readable control flow: flattened into dispatch state-machines by default, lifted into a custom bytecode VM under the VM engine.
- Beautifiers: StyLua re-indents the output but recovers layout only; renamed locals, encoded constants and flattened/virtualized flow stay hidden.
- Scheme-specific lifters and bytecode decompilers: the output is Luau source, not a compiled chunk, and the scheme is distinct, so unluac/luadec and MoonSec/Prometheus/IronBrew lifters do not apply.
What it does not defeat
- Running the loader dumps the entire string pool in plaintext, every pool entry (100%).
- A minimal constant-folder reverses the integer arithmetic; the residual is 0.
- Any secret shipped to a client is recoverable. This is inherent to all client-side obfuscation. It raises cost and defeats casual inspection, it does not make a client a vault.
Runtime overhead
Source rewriting is free. The VM costs only what it virtualizes.
| Protection layer | Median (Luau on Apple arm64) | vs native |
|---|---|---|
| Native (no protection) | 1.95 ms | 1.00× |
| Rename + encoded strings + minify · pure source rewrite, effectively free | 1.93 ms | 0.99× |
| + encoded number constants · a little arithmetic per constant | 2.22 ms | 1.14× |
| + bytecode VM on the hot function · worst case: the single 100k-iteration function fully virtualized; the VM is opt-in per function and bails on hot constructs | 173.30 ms | ≈89× |
Measured 20 Oct 2026 · Apple arm64 · real Luau runtime, not inside a Roblox client · reproduce locally with npm run protection:benchmark
Measure your own script before you publish: the Roblox MicroProfiler, or an os.clock() A/B loop around your hot path. These fixtures are a guide, not a promise about your code.
Luau compatibility
Verified against the real runtime.
Fully transformed, incl. VM
- locals and parameters
- methods (implicit self)
- if / elseif / else
- while, numeric and generic for
- calls and method calls with multi-value args and returns
- index read and write, assignment, compound assignment (+=)
- table constructors
- one level of nested closures
- all arithmetic, comparison, concat, logical and unary operators
VM bails to native, still protected
- varargs
- doubly-nested closures
- repeat … until
- continue / goto
- interpolated strings
- closures that write or capture a reassigned loop-scoped local
Preserved / never renamed
- type annotations including typeof(expr)
- string interpolation (handled at source level)
- globals, table fields, method names, string keys and type names are never renamed
- Luau (default) and a Lua 5.1 compatibility mode
Every build is re-run against the real Luau binary and compared on output and exit code (975 differential runs in the engine’s test suite). If a construct can’t be transformed with certainty the engine bails that function rather than risk miscompiling, which is why a failed build never replaces your working release.
Reproduce it
Run the same harness we did.
Size and throughput, 25 programs, re-verified under the real Luau binary
python3 scripts/benchmark.pyAttack-survival harness (seed 1337)
python3 scripts/deobf_resistance.pyCorrectness: the full differential suite against real Luau
cargo test01Are these numbers independently reproducible?
Yes. Every figure here comes from a committed harness you can run yourself: scripts/benchmark.py for size and throughput, scripts/deobf_resistance.py for attack-survival, and the differential suite for correctness. Each table is stamped with the tool, seed and date it was measured.
02Does obfuscation make my script impossible to inspect?
No, and we will not claim otherwise. Protection defeats casual inspection and raises the cost of reverse-engineering, but running the loader recovers the string pool in plaintext and a constant-folder reverses the integer arithmetic. Any secret shipped to a client is recoverable. Keep secrets and authority on the server.
03What is the runtime cost in game?
Renaming, string and number encoding and minification are pure source rewrites, so their in-game cost is effectively zero. Control-flow flattening adds dispatch cost only to flattened functions, and the bytecode VM adds interpreter cost only to the functions it virtualizes, which is opt-in and bails on hot constructs. Measure your own script with the Roblox MicroProfiler or an os.clock() A/B loop; the fixtures here are a guide, not a promise about your code.
04How does this compare to Luraph, MoonSec or Luarmor?
Those are closed, paid services you upload to and must trust; none publish a runnable benchmark. vodka measures the exact engine that protects every build with a committed harness, stamped with the seeds and dates to reproduce it. This page does not assert a security ranking. It shows measured, reproducible evidence, which is more than a closed competitor can offer.
Keep building
Protect your next build.
Every figure here is reproducible. Bring your source and see for yourself.