Introduction
Traditionally, we associate software rules with coding. But when I recently talked to an Outsystems developer, I discovered that the majority of their work involves defining business rules—despite Outsystems being intended for low or no code development. I had assumed such platforms would simplify this task, but it turns out that a great deal of time is still spent on rule definition.
Still, all rules in Outsystems are static. Whenever you want to add new rules or modify existing ones, a developer must implement these changes and then recompile the application for the user to gain access.
Additionally, deploying new rules can be cumbersome. It often involves creating backups, transferring updated resources, and running tests to ensure everything works correctly.
Dynamic Rules
I’m particularly interested in dynamic systems. We aim to accelerate software development while preserving flexibility at runtime. Consider an example of conditional validations: some rules are fixed and cannot be overridden, yet we also want users to set up custom rules relevant only to their specific cases—like making the notes field mandatory when field1’s value is 1. It’s not ideal to hard-code user-specific changes into the source and then recompile or restart to apply them. Instead, a better approach is to let users define custom rules on the fly, without needing to shut down the server.
AI can also make use of dynamic rule engines to enhance flexibility. AI for example can monitor user behavior and customize rules for that user. It can prevent abuse from the user or streamline operations based on conditions.
Domain Specific Language (DSL)
1. The Need for a Simplified DSL
A rule engine often benefits from using a domain-specific language (DSL) that’s easy to write and understand. While JSON can define complex relationships, it can feel heavy or unwieldy for certain use cases. By contrast, a DSL that reads more like natural language can make rule definitions more user-friendly, especially for non-developers.
2. Balancing Flexibility and Performance
One common concern with any DSL is the runtime cost of parsing and executing its instructions. As rules become more complex, real-time interpretation can create performance bottlenecks. Fortunately, there are ways to mitigate this, such as compiling the DSL into executable code or caching previously parsed instructions. These techniques keep performance overhead in check even when rules get complicated.
3. Consistency in Development and Runtime
The DSL can serve as both a runtime mechanism and a development tool. When analysts, product owners, or other stakeholders use the exact same DSL that developers rely on, the entire team shares a single source of truth. This lowers the barrier for creating and maintaining rules: an analyst could document a rule in DSL form, and that very same definition can be used directly by the application.
4. Compilation and Execution Pathways
A DSL does not have to remain an interpreted language. It can be transformed or compiled into other execution targets—JavaScript, Python, C#, and so on. This flexibility lets you generate optimized code ahead of time, alleviating most performance constraints you might otherwise face. Once generated, the code can be cached and reused, ensuring minimal overhead at runtime.
5. AI Integration and Rule Awareness
AI systems can also leverage a well-defined DSL. With a simpler syntax, AI can more readily parse and adapt to the rules, whether that involves personalizing user experiences, preventing abuse, or automating complex decision flows. The key is to keep the DSL straightforward, so both humans and intelligent systems can understand and act on the rules quickly.
6. Governance, Versioning, and Expansion
As with any rule-driven system, having a clear process for versioning and governance is crucial. Teams should be able to introduce, update, or retire rules without causing disruptions or regressions. By maintaining a simple, lightweight DSL, you make it easier to track changes over time, roll back if necessary, and ensure older rules still function as intended.
Ultimately, the goal is to strike a balance: keep the DSL “simple and stupid” so that it’s easy to read, fast to parse, and adaptable to a wide range of scenarios. Whether you’re defining conditional validations for a single field or setting up an advanced AI-driven decision flow, a minimalistic, well-structured DSL can provide the flexibility and efficiency both users and systems need.
Example
# Example DSL for Conditional Validations or Actions
RULE "RequireNotesIfField1IsOne"
WHEN field1 EQUALS 1
THEN REQUIRE notes
RULE "ApplyDiscountForPremiumUsers"
WHEN userType EQUALS "premium"
AND cartValue GREATER_THAN 100
THEN DISCOUNT 10%
RULE "PreventNegativeStock"
WHEN inventoryLevel LESS_THAN 0
THEN ALERT "Stock cannot be negative"
Usecases
The rule engine is not meant to replace coding but it is meant to streamline efforts in a dynamic way.
You can use the rules engine for:
- Data Validation: ensure that a model’s values are correct before committing it to storage.
- Data Transformation: Update data in the store based on conditional triggers defined in the rule engine. For example, disable product when stock becomes zero.
- Conditional Actions: Perform an action when a condition passes or fails. For example, if the stock quality is less than 5, notify responsible person.
- Access Control and Permissions: For example, inform the user that they don’t have sufficient rights if they are not allowed to access sensitive data.
- Real-Time Monitoring and Alerts: Trigger an alert when sensor data in an IoT device crosses a threshold, or send an SMS notification if system resource usage spikes beyond predefined limits.
In practice, this list can become quite extensive—essentially, any logic you’d write in code can often be managed by a rule engine.
Contextual Rules
Rules should always be defined within a clear, well-defined context—for instance, rules that apply specifically to staff members or those that govern assets. By scoping rules in this way, you not only simplify their design but also strengthen security. Malicious actors can’t exploit a rule engine that’s restricted to a particular domain, because the actions allowed in that domain are tightly controlled. Additionally, it becomes easier to sanitize and validate rules—ensuring they align with the logical and operational boundaries of the context. This compartmentalized approach makes rules more manageable, reduces potential vulnerabilities, and maintains cleaner separation of concerns.
For example, lets look at a JavaScript function that is defined from a rule.
DSL
RULE "CanPerformTask"
WHEN role EQUALS "admin"
THEN RETURN true
Compiled JavaScript
function canPerformTask(person) {
return person.role === "admin";
}
In this setup, the context is defined as the “person,” and all generated code is constrained to that specific context. The code only has access to data passed in as a parameter to the function, ensuring it cannot operate outside the person’s scope.
Although sanitization adds an extra step—and thus some overhead—to the rule evaluation process, it is indispensable for maintaining security. Thoroughly validating and cleaning inputs prevents malicious code injections, data corruption, and other vulnerabilities. The trade-off in performance is usually well worth the heightened protection and system integrity it provides.
Summary
This post introduces the concept of a dynamic rule engine that enables real-time updates to business logic without requiring application restarts or extensive redeployment. Central to this approach is a simple Domain-Specific Language (DSL) designed to be clear and concise, so both technical and non-technical users can easily define or modify rules. By keeping the DSL syntax “simple and stupid,” the system remains flexible for a wide range of applications—from data validation and access control to AI-driven personalization—while still performing efficiently. The blog also covers key considerations such as governance, versioning, and balancing readability with runtime performance, illustrating how a well-defined DSL can streamline rule management and help teams respond quickly to changing requirements.