Every real application has a layer of rules that lives uncomfortably between "configuration" and "code." Show this field only if the customer is a business, not an individual. Default the invoice date to the end of the current quarter. Calculate the total as quantity times unit price minus discount. These aren't technical questions; they're product questions. The people who understand them best are usually not the people writing code. An inline expression language puts the answers in their hands.
Our expression engine has been part of the platform since its earliest days and has grown steadily ever since. It's designed to feel obvious to anyone who has used a spreadsheet formula or written a line of any modern scripting language. The syntax supports the operations you'd expect — math, string manipulation, dates and intervals, conditional logic, list and map operations — and handles the edge cases that business applications actually encounter: quarter boundaries, due-date arithmetic with business days, safe null handling across chains of related objects.
What makes the language more than a pocket calculator is scope. The same expression can mean different things in different contexts, and the platform provides that context automatically. Inside a form, currentObject is the record being edited. Inside an automation, it's the record that fired the trigger. Inside a form row in a repeating section, it's the row itself, with the enclosing parent also reachable. Inside a template it's whichever object the template was rendered for. You write a short, readable expression; the platform figures out what it's talking about.
The places you can use expressions reward a moment of attention, because they're what makes the engine feel alive. Conditional visibility on a field — one expression, and the field shows up only when it should. Default values — computed when a record is created, not hard-coded into the form. Validation messages that adapt to the input the user just typed. Filter parameters in saved queries, so a single query can mean "my tasks" for one user and "my team's tasks" for another. Automation conditions that decide whether a trigger should proceed. Template variables in emails and PDFs. View sorting and column formulas. Across the platform, the same language lets the same person configure all of them.
A handful of examples give the flavor. Defaulting a dueDate to two weeks from today is a one-liner. Hiding an invoiceVAT field when the customer is flagged as non-VAT is a condition on the field's visibility. Computing total = quantity * unitPrice - discount is a formula on the total column. Checking whether the current user is in a specific role before showing a button is one call into the user context. Filtering a dropdown of Projects to only those where the selected Customer is a member is a one-hop lookup through a relationship. These are the rules that would otherwise live in a developer's backlog, and they can be typed into a field by someone closer to the business.
Cross-type lookups deserve a brief mention of their own. Because relationships are first-class in the data model, expressions can walk them: customer.country.region.name is a normal thing to write. The engine evaluates each hop safely, returning a null if the chain breaks along the way, so a missing intermediate value doesn't blow up the whole expression. That kind of quiet robustness is what keeps configuration-level logic livable at scale.
Expressions run sandboxed. They can't reach into sensitive internals, can't make external network calls, and have deterministic time and memory bounds. That's intentional: expressions are the low-risk end of the extensibility spectrum, safe for power users to experiment with, safe for the platform to evaluate thousands of times per page render.
There is a point at which expressions stop being the right answer. Long chains of conditional logic, orchestration across several records, anything that needs to call an external system — that territory belongs to automations, or, beyond that, to server-side scripting. But the line moves further out than most people expect. A surprising amount of real-world application logic fits comfortably in a single expression, and every one of those is one fewer request to queue up for a developer.
The automation builder and the canvas page builder both lean heavily on this engine. Reading about those alongside this piece is the best way to get a feel for how much an implementation can do with just configuration.