High-performance business rules execution system with DSL support
The Dynamic Rules Engine is a high-performance business rules execution system built with Go for maximum performance. It allows business users to define and modify rules without code changes, evaluating complex rule sets in under 1ms.
The Rules Engine uses a simple, expressive DSL that allows business users to define complex rules without programming knowledge.
rule "rule_name"
when
condition1 AND
condition2 OR
condition3
then
action1()
action2(parameter)
end
Operator | Description | Example |
---|---|---|
== | Equality | customer.tier == "gold" |
!= | Inequality | product.status != "discontinued" |
>, <, >=, <= | Comparison | order.total > 100 |
IN | List membership | customer.country IN ["US", "CA", "UK"] |
CONTAINS | String contains | product.tags CONTAINS "premium" |
MATCHES | Regex matching | email MATCHES ".*@company.com" |
// Date/Time Functions
days_since(date) - Calculate days since given date
hours_until(date) - Calculate hours until given date
is_weekend() - Check if current day is weekend
is_business_hours() - Check if within business hours
// Math Functions
percentage(value, total) - Calculate percentage
round(value, decimals) - Round to decimal places
min(a, b) - Return minimum value
max(a, b) - Return maximum value
// String Functions
lowercase(string) - Convert to lowercase
uppercase(string) - Convert to uppercase
trim(string) - Remove whitespace
concat(str1, str2) - Concatenate strings
The Rules Engine exposes a high-performance gRPC API for rule evaluation and management.
syntax = "proto3";
package rulesengine;
service RulesEngine {
// Evaluate rules for given context
rpc EvaluateRules(EvaluateRequest) returns (EvaluateResponse);
// Manage rules
rpc CreateRule(CreateRuleRequest) returns (Rule);
rpc UpdateRule(UpdateRuleRequest) returns (Rule);
rpc DeleteRule(DeleteRuleRequest) returns (Empty);
rpc GetRule(GetRuleRequest) returns (Rule);
rpc ListRules(ListRulesRequest) returns (ListRulesResponse);
// A/B Testing
rpc CreateExperiment(CreateExperimentRequest) returns (Experiment);
rpc GetExperimentResults(GetExperimentRequest) returns (ExperimentResults);
}
Evaluate rules against provided context data.
{
"context": {
"customer": {
"id": "cust_123",
"tier": "gold",
"lifetime_value": 5000
},
"order": {
"total": 150,
"items_count": 3
}
},
"rule_sets": ["pricing", "promotions"]
}
Update an existing rule in real-time.
{
"rule_id": "discount_rule_001",
"dsl": "rule \"updated_discount\"\nwhen\n customer.tier == \"gold\" AND\n order.total > 200\nthen\n apply_discount(20)\nend",
"priority": 10,
"enabled": true
}
The Rules Engine is optimized for high-throughput, low-latency operation in production environments.
BenchmarkRuleEvaluation-8 1000000 892 ns/op 240 B/op 4 allocs/op
BenchmarkComplexRule-8 500000 2341 ns/op 512 B/op 8 allocs/op
BenchmarkRuleWithDB-8 100000 12847 ns/op 1024 B/op 15 allocs/op
BenchmarkConcurrentEval-8 5000000 234 ns/op 64 B/op 1 allocs/op
BenchmarkRuleCompilation-8 10000 145623 ns/op 16384 B/op 124 allocs/op
The Rules Engine can be configured via environment variables or configuration files.
Variable | Description | Default |
---|---|---|
RULES_ENGINE_PORT | gRPC server port | 50051 |
ETCD_ENDPOINTS | Comma-separated etcd endpoints | localhost:2379 |
RULE_CACHE_SIZE | Maximum compiled rules in cache | 1000 |
EVALUATION_TIMEOUT | Max rule evaluation time | 100ms |
METRICS_ENABLED | Enable Prometheus metrics | true |
server:
port: 50051
max_connections: 1000
keepalive_time: 30s
etcd:
endpoints:
- http://etcd1:2379
- http://etcd2:2379
dial_timeout: 5s
request_timeout: 2s
rules:
cache_size: 1000
compilation_workers: 4
evaluation_timeout: 100ms
max_rule_size: 10KB
monitoring:
prometheus_enabled: true
metrics_path: /metrics
metrics_port: 9090
logging:
level: info
format: json
output: stdout
Real-world examples demonstrating common use cases for the Rules Engine.
rule "black_friday_special"
when
date.is_between("2024-11-29", "2024-11-30") AND
customer.is_registered == true
then
apply_discount(25)
set_free_shipping()
add_message("Black Friday Special Applied!")
end
rule "loyalty_discount"
when
customer.tier IN ["gold", "platinum"] AND
customer.purchases_last_30_days > 3 AND
order.subtotal > 100
then
apply_discount(15)
add_loyalty_points(order.subtotal * 2)
end
rule "bulk_order_discount"
when
order.item_count >= 10 OR
order.subtotal >= 500
then
apply_discount(10)
set_priority_handling()
end
rule "high_risk_transaction"
when
transaction.amount > customer.avg_transaction_amount * 5 AND
location.country != customer.home_country AND
time.hours_since_last_transaction < 1
then
set_risk_score(90)
flag_for_review()
send_notification("security_team")
end
rule "velocity_check"
when
customer.transactions_last_hour > 5 OR
customer.failed_attempts > 3
then
set_risk_score(75)
enable_additional_verification()
end
rule "vip_customer_identification"
when
customer.lifetime_value > 10000 AND
customer.account_age_days > 365 AND
customer.churn_probability < 0.2
then
assign_segment("VIP")
enable_premium_features()
assign_dedicated_support()
end
rule "at_risk_customer"
when
customer.last_purchase_days > 90 AND
customer.engagement_score < 30 AND
customer.support_tickets_unresolved > 0
then
assign_segment("At Risk")
trigger_retention_campaign()
escalate_support_tickets()
end
package main
import (
"context"
"log"
"google.golang.org/grpc"
pb "company.com/rulesengine/proto"
)
func main() {
// Connect to Rules Engine
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRulesEngineClient(conn)
// Prepare evaluation context
ctx := context.Background()
req := &pb.EvaluateRequest{
Context: map[string]*pb.Value{
"customer.tier": {Value: &pb.Value_StringValue{"gold"}},
"order.total": {Value: &pb.Value_NumberValue{250.0}},
"order.items": {Value: &pb.Value_NumberValue{5}},
},
RuleSets: []string{"pricing", "promotions"},
}
// Evaluate rules
resp, err := client.EvaluateRules(ctx, req)
if err != nil {
log.Fatalf("Evaluation failed: %v", err)
}
// Process results
for _, action := range resp.Actions {
log.Printf("Action: %s, Parameters: %v", action.Name, action.Parameters)
}
}
For more information or support, contact the engineering team or refer to the internal wiki.