This guide covers everything about Luau Style Guide Essentials. Luau is the language Roblox runs on. it’s a dialect of Lua with type annotations, performance improvements, and Roblox-specific APIs. Writing Luau well is not exotic โ most of the conventions are general programming hygiene applied carefully โ but Luau has enough quirks that a style guide saves real time on team projects.
Last updated: May 3, 2026
This guide collects the conventions we use across Bloxtra editorial test projects. None of these are mandatory; they are what we found works after a few years of writing Luau. Adopt the ones that fit your team and ignore the rest.
Key Takeaways
- Variables and functions: camelCase.
- Luau’s type system is opt-in but worth using.
- Each ModuleScript should have a single clear responsibility.
- Use pcall around any operation that can fail externally โ DataStore calls, HTTP requests, MarketplaceService queries.
- task.wait() is the modern equivalent of wait() and behaves more predictably under load.
The rest of this article walks through the reasoning behind each of these claims, with specific tools, numbers, and methodology where relevant. Skim the section headings if you are short on time, or read straight through for the full case.
How This Guide Was Built
Everything in this article was tested on real Roblox projects by the editorial team. We use the official Roblox Studio plugin API, OS-level performance settings, and community-built tools that operate within Roblox’s Terms of Service. Bloxtra doesn’t cover, link to, or recommend script executors, exploit tools, or anything that modifies the Roblox client โ those violate the Terms and risk permanent bans. We also don’t link to “free Robux” generators or anything that appears to circumvent Roblox’s economy.
Our coverage standard is consistent: a tool gets covered if it has been actively maintained in the past six months, has clear documentation, and works as advertised when we test it. Read more about our editorial standards on the About page, where we publish our full coverage policy and conflict-of-interest disclosures.
Naming
Variables and functions: camelCase. Constants: SCREAMING_SNAKE_CASE. Modules and types: PascalCase. Boolean variables: prefixed with is, has, or should โ isReady, hasInventory, shouldRetry. These conventions are not enforced by Luau but are widely used in the Roblox community.
Avoid single-letter variable names except for very short loops (i, j, k for indices, x, y, z for coordinates). Even in short loops, descriptive names are better when the variable is used in multiple lines.
Type annotations
Luau’s type system is opt-in but worth using. Annotate function signatures and module exports. Annotate complex local variables. don’t annotate every trivial local โ that’s noise.
A common pattern: define a type alias at the top of the module for any data structure used across multiple functions. This makes the shape of the data explicit and catches bugs at type-check time rather than runtime.
Module structure
Each ModuleScript should have a single clear responsibility. The module returns a table of public functions. Private functions live as locals at the top of the file, outside the returned table.
A consistent module template: imports at the top (services, modules), type aliases, constants, private helpers, public table with attached methods, return the public table. Use the same shape across the project so any developer can read any module quickly.
Error handling
Use pcall around any operation that can fail externally โ DataStore calls, HTTP requests, MarketplaceService queries. don’t pcall everything; the goal is to handle failures at boundaries, not to suppress all errors.
When a pcall fails, log the error with enough context to debug it later. A bare warn(err) is rarely enough. Include what was being attempted and any relevant identifiers.
Avoid wait() in production code
task.wait() is the modern equivalent of wait() and behaves more predictably under load. Replace any wait() calls in your code with task.wait(). it’s one of the easiest single improvements you can make.
Better still, prefer event-driven patterns over time-based waits when possible. A wait followed by a check is usually a sign that an event would be cleaner.
Comments and documentation
Comment why, not what. The code shows what it does. The comment should explain the reason for unusual decisions, the reference for an obscure formula, or a warning about edge cases.
For module-level public APIs, write a short summary at the top: what the module does, what its main public functions are. This is the documentation a developer reads when first encountering the module.
Common pitfalls
Luau’s implicit globals can cause bugs. Always declare locals with the local keyword. Forgetting it makes the variable global, which can be silently shared across scripts in unintended ways.
Loops that yield (use task.wait, RemoteEvent calls, etc.) inside an event handler can cause re-entry issues if the event fires again before the previous handler completes. Be deliberate about where you yield.
Be careful with table references. In Lua and Luau, tables are passed by reference. If you modify a table inside a function, you modify the original. This is fast and useful but causes bugs when developers expect value semantics. When in doubt, copy the table explicitly.
Performance habits
Cache service references at the top of the module rather than calling game:GetService inside hot loops. The service lookup is fast but not free, and it adds up across thousands of calls per frame.
Avoid unnecessary instance creation in tight loops. Reuse parts and tables when possible. Garbage collection pauses are usually invisible, but in heavy loops they become measurable.
Profile before optimising. Studio’s MicroProfiler and Script Performance windows show where time actually goes. Most performance intuitions are wrong; measurement is the only reliable guide.
Frequently Asked Questions
Is Luau type checking strict by default?
No. By default the type checker runs in non-strict mode and treats untyped values as the special any type. You can enable strict mode per file with –!strict at the top. Strict mode catches more bugs but requires more annotations.
Should I use object-oriented patterns?
OOP works in Luau via metatables but is not idiomatic for everything. Use it when you have many instances of the same kind of object (enemies, items, projectiles). Use plain modules with functions for one-off systems. Mixing both is fine.
What linter should I use?
Selene is the most popular external linter and catches issues Studio’s built-in checker misses. Studio has its own analyser called the Script Analysis tool which is good but less thorough. Run both if your project is large.
How do I structure shared code between client and server?
Put it in a module in ReplicatedStorage. Both client and server can require it. Keep server-only logic in modules under ServerStorage or ServerScriptService. Mixing the two is the source of many security bugs.
Are global variables ever acceptable?
_G exists but should be avoided. It creates implicit dependencies that are hard to track. The few legitimate uses (sharing data between scripts that genuinely need to be coupled) are better handled with explicit module imports.
What This Means in Practice
The honest answer for most readers: pick the option that fits your specific situation, test it on real work for at least two weeks before committing, and revisit the decision when the underlying tools change. AI tools update frequently enough that what is correct today may not be correct in six months. Build in a re-evaluation step every quarter for any tool that occupies a meaningful slot in your workflow.
Avoid the temptation to over-stack tools. The friction of switching between five tools eats into the productivity gain that any individual tool provides. The teams that get the most from AI are usually the ones using two or three tools deeply, not the ones with subscriptions to a dozen.
My Take
Style is not pedantry โ it’s the difference between code you can change in six months and code you have to rewrite. Pick conventions, write them down, follow them.
If you have questions about anything covered here, or want us to test a specific tool, email editorial@bloxtra.com. We read every message and reply within a working day. Corrections are dated and public โ when we get something wrong or when a tool changes meaningfully after we publish, we update the article and note the change at the bottom.
Related reading: Luau snippet libraries worth using, Common Roblox Studio mistakes, First Roblox game checklist.
Source: Britannica.