Choosing the Right Rule Engine: 5 Popular Options Compared & How to Pick
This guide explores the core pain point of frequent business rule changes versus system stability, introduces five rule engines (Drools, Easy Rules, QLExpress, Aviator, LiteFlow), compares their performance, advantages, disadvantages, and provides practical selection tips and pitfalls to avoid.
Introduction
Core pain point: frequent business rule changes vs. system stability.
An e‑commerce promotion example shows how hard‑coded if/else quickly becomes unmaintainable.
public BigDecimal calculateDiscount(Order order) {
BigDecimal discount = BigDecimal.ZERO;
if (order.getTotalAmount().compareTo(new BigDecimal("100")) >= 0) {
discount = discount.add(new BigDecimal("10"));
}
if (order.getUser().isVip()) {
discount = discount.add(new BigDecimal("5"));
}
// more nested if‑else ...
return discount;
}When rules grow complex (e.g., "non‑VIP over 200 gets 30 off, VIP over 150 gets 40 off, plus 5% extra on Tuesdays"), the code falls into maintenance hell.
Rule engines solve this by separating rule logic:
External rule storage (DB/file)
Dynamic loading
Declarative rule syntax
Independent execution environment
Below are five commonly used rule engines.
1. Drools – Enterprise‑grade rule engine
Website: https://www.drools.org/
Applicable scenarios
Financial risk control with hundreds of complex rules
Insurance claim calculation
E‑commerce promotion systems
Practical example: discount rule configuration
// rule file discount.drl
rule "VIP user discount 20"
when
$user: User(level == "VIP")
$order: Order(amount > 100)
then
$order.addDiscount(20);
endJava invocation
KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();
KieSession kSession = kContainer.newKieSession("discountSession");
kSession.insert(user);
kSession.insert(order);
kSession.fireAllRules();Advantages:
Full RETE algorithm implementation
Supports complex rule networks
Comprehensive monitoring console
Disadvantages:
Steep learning curve
High memory consumption
Requires Kie container dependency
Suitable for large enterprises with high rule complexity.
2. Easy Rules – Lightweight rule engine
Website: https://github.com/j-easy/easy-rules
Applicable scenarios
Parameter validation
Simple risk control rules
Approval flow engines
Annotation‑based development
@Rule(name = "Rain discount rule", description = "9% off on rainy days")
public class RainDiscountRule {
@Condition
public boolean when(@Fact("weather") String weather) {
return "rainy".equals(weather);
}
@Action
public void then(@Fact("order") Order order) {
order.setDiscount(0.9);
}
}Engine execution
RulesEngineParameters params = new RulesEngineParameters()
.skipOnFirstAppliedRule(true);
RulesEngine engine = new DefaultRulesEngine(params);
engine.fire(rules, facts);Advantages:
Get started in five minutes
No third‑party dependencies
Supports rule composition
Disadvantages:
Does not support complex rule chains
Lacks visual UI
Ideal for small projects or teams with limited resources.
3. QLExpress – Alibaba script engine
Website: https://github.com/alibaba/QLExpress
Applicable scenarios
Dynamic calculation logic
Financial formula computation
Flexible marketing rule changes
Execute dynamic script
ExpressRunner runner = new ExpressRunner();
DefaultContext<String, Object> context = new DefaultContext<>();
context.put("user", user);
context.put("order", order);
String express = "if (user.level == 'VIP') { order.discount = 0.85; }";
runner.execute(express, context, null, true, false);Advantages:
Hot‑update scripts
Java‑like syntax
Robust sandbox security
Disadvantages:
Debugging is difficult
Complex rules are hard to read
Best for business scenarios that require frequent rule modifications.
4. Aviator – High‑performance expression engine
Website: https://github.com/killme2008/aviatorscript
Applicable scenarios
Real‑time pricing engines
Risk metric calculations
Big‑data field processing
Performance comparison (10 k executions)
// Aviator expression
Expression exp = AviatorEvaluator.compile("user.age > 18 && order.amount > 100");
exp.execute(map);
// Groovy script
new GroovyShell().evaluate("user.age > 18 && order.amount > 100");Results: Aviator 28 ms, Groovy 1850 ms.
Advantages:
Performance far exceeds peers
Supports bytecode generation
Lightweight with no dependencies
Disadvantages:
Only expression language, no flow control
Limited to simple expressions
Fits scenarios demanding extreme performance.
5. LiteFlow – Rule orchestration framework
Website: https://liteflow.com/
Applicable scenarios
Complex business processes
Order state machines
Approval workflows
Orchestration example
<chain name="orderProcess">
<then value="checkStock,checkCredit"/>
<!-- parallel execution -->
<when value="isVipUser">
<then value="vipDiscount"/>
</when>
<otherwise>
<then value="normalDiscount"/>
</otherwise>
<then value="saveOrder"/>
</chain>Java invocation
LiteflowResponse response = FlowExecutor.execute2Resp("orderProcess", order, User.class);
if (response.isSuccess()) {
System.out.println("Process succeeded");
} else {
System.out.println("Failure reason: " + response.getCause());
}Advantages:
Visual flow composition
Supports async, parallel, conditional branches
Hot rule updates
Disadvantages:
New framework, limited documentation
Community ecosystem still maturing
Suitable for complex business flows needing flexible orchestration.
Horizontal Evaluation of the Five Engines
Drools: 420 ms, high memory, feature‑rich.
Easy Rules: 38 ms, low memory, lightweight and easy.
QLExpress: 65 ms, medium memory, Alibaba script engine.
Aviator: 28 ms, very low memory, high‑performance expression.
LiteFlow: 120 ms, medium memory, flow‑orchestration specialist.
How to Choose?
Simple scenarios: combine Easy Rules and Aviator.
Financial risk control: use Drools.
E‑commerce operations: adopt QLExpress.
Workflow‑driven processes: pick LiteFlow.
Avoiding Pitfalls
Drools memory overflow – use a stateless session.
// Stateless session to avoid memory buildup
KieSession session = kContainer.newStatelessKieSession();QLExpress security – disable dangerous methods.
// Disable risky methods
runner.addFunctionOfServiceMethod("exit", System.class, "exit", null, null);Rule conflict detection – configure Drools sequential execution.
// Drools conflict handling
KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
config.setProperty("drools.sequential", "true");Conclusion
Rule engines can replace tangled if/else code.
Leverage hot‑update and visualization for advanced use.
Combine orchestration and performance tuning for mastery.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
