Stop Hardcoding Business Logic: Meet Rule Engine JS

~ 6 min read

Table of Contents


Have you ever found yourself buried in nested if-else statements, trying to implement complex business rules that change every other week? Or worse, watched your clean codebase turn into a maintenance nightmare because business logic was scattered across dozens of files?

I’ve been there. And that’s exactly why I built Rule Engine JS.

The Problem That Started It All

Picture this: You’re building an e-commerce platform, and the business team comes to you with “simple” requirements:

  • VIP customers get discounts on orders over $100
  • Regular customers need 1000+ loyalty points for discounts
  • First-time customers get 20% off orders over $50
  • But only during business hours
  • Unless it’s a weekend
  • Or a holiday
  • And the rules change next month…

Sound familiar? 😅

The real kicker came when they said: “Oh, and we need to store these rules in the database so we can update them without deploying.”

That’s when I realized I needed something that could handle JSON-serializable business logic without sacrificing developer experience or performance.

Enter Rule Engine JS

After trying existing solutions and finding them either too complex, too slow, or lacking key features, I decided to build something better. Here’s what makes Rule Engine JS different:

🚀 Zero Dependencies, Maximum Performance

No bloated dependency trees. No security vulnerabilities from third-party packages. Just clean, efficient JavaScript that works everywhere:

import { createRuleEngine, createRuleHelpers } from 'rule-engine-js';

const engine = createRuleEngine();
const rules = createRuleHelpers();

// That's it. You're ready to go.

🎯 Developer Experience That Actually Makes Sense

Remember those nested JSON rules that make your eyes bleed? Not here:

// Instead of this nightmare:
const rule = {
  and: [
    { gte: ['user.age', 18] },
    { eq: ['user.status', 'active'] },
    { in: ['write', 'user.permissions'] },
  ],
};

// Write this:
const rule = rules.and(
  rules.gte('user.age', 18),
  rules.eq('user.status', 'active'),
  rules.in('write', 'user.permissions'),
);

Both compile to the same JSON (perfect for database storage), but only one is actually maintainable.

Dynamic Field Comparison (The Game Changer)

Here’s where things get interesting. Need to compare fields within your data? Most rule engines make you jump through hoops. Rule Engine JS makes it natural:

const orderValidation = rules.and(
  rules.field.lessThan('order.total', 'user.creditLimit'),
  rules.field.equals('order.currency', 'user.preferredCurrency'),
  rules.gte('user.accountAge', 30), // days
);

This was the feature I desperately needed for my original project - and now it’s built right in.

Real World Examples

Let’s solve that e-commerce discount problem from earlier:

const discountEligibility = rules.or(
  // VIP customers with minimum order
  rules.and(rules.eq('customer.type', 'vip'), rules.gte('order.total', 100)),

  // High loyalty points
  rules.gte('customer.loyaltyPoints', 1000),

  // First-time customer bonus
  rules.and(rules.isTrue('customer.isFirstTime'), rules.gte('order.total', 50)),
);

// Later, when business rules change:
const updatedRules = await database.getRules('discount-eligibility');
const result = engine.evaluateExpr(updatedRules, customerData);

No deployments. No code changes. Just update the database and you’re done.

Form Validation Made Simple

const formValidation = rules.and(
  rules.validation.required('email'),
  rules.validation.email('email'),
  rules.field.equals('password', 'confirmPassword'),
  rules.validation.ageRange('age', 18, 120),
  rules.isTrue('agreedToTerms'),
);

// Returns detailed validation results
const result = engine.evaluateExpr(formValidation, formData);
if (!result.success) {
  console.log('Validation failed:', result.error);
}

User Access Control

const accessRule = rules.and(
  rules.isTrue('user.isActive'),
  rules.or(
    rules.eq('user.role', 'admin'),
    rules.and(
      rules.eq('user.department', 'resource.department'),
      rules.in('read', 'user.permissions'),
    ),
  ),
);

// Perfect for middleware
app.get('/api/sensitive-data', (req, res, next) => {
  const hasAccess = engine.evaluateExpr(accessRule, {
    user: req.user,
    resource: { department: 'finance' },
  });

  hasAccess.success ? next() : res.status(403).json({ error: 'Access denied' });
});

Built for Production

Performance That Scales

  • Intelligent LRU caching for repeated evaluations
  • Path resolution caching for nested object access
  • Regex pattern caching for validation rules
  • Typically under 1ms evaluation time

Security First

  • Built-in protection against prototype pollution
  • Safe path resolution (no function execution)
  • Input validation and sanitization
  • Configurable complexity limits to prevent DoS

Monitoring Included

// Built-in performance metrics
const metrics = engine.getMetrics();
console.log({
  evaluations: metrics.evaluations,
  cacheHitRate: metrics.cacheHits / metrics.evaluations,
  averageTime: metrics.avgTime + 'ms',
});

Framework Agnostic

Whether you’re using React, Vue, Express, Next.js, or vanilla JavaScript - Rule Engine JS just works:

// React
function useRuleValidation(rules, data) {
  return useMemo(() =>
    engine.evaluateExpr(rules, data), [rules, data]
  );
}

// Express middleware
const createAccessMiddleware = (rule) => (req, res, next) => {
  const result = engine.evaluateExpr(rule, req.user);
  result.success ? next() : res.status(403).end();
};

// Vue computed property
computed: {
  isEligible() {
    return engine.evaluateExpr(this.businessRules, this.userData).success;
  }
}

Getting Started (30 Seconds)

npm install rule-engine-js
import { createRuleEngine, createRuleHelpers } from 'rule-engine-js';

const engine = createRuleEngine();
const rules = createRuleHelpers();

// Your first rule
const canAccess = rules.and(rules.gte('user.age', 18), rules.eq('user.status', 'active'));

// Test it
const result = engine.evaluateExpr(canAccess, {
  user: { age: 25, status: 'active' },
});

console.log(result.success); // true

That’s it. No configuration files, no complex setup - just clean, working code.

Why I Think You’ll Love It

After using Rule Engine JS in production for several months, here’s what I appreciate most:

  1. It stays out of your way - Simple API, predictable behavior
  2. Debugging is actually pleasant - Clear error messages and built-in logging
  3. Performance is transparent - See exactly how your rules are performing
  4. Security is handled - Protection against common attacks built-in
  5. It scales with your needs - From simple validation to complex business logic

What’s Next?

I’m actively working on Rule Engine JS and would love your feedback. Whether you’re dealing with complex business rules, form validation, or access control - give it a try and let me know what you think.

⭐ Star the repo: github.com/crafts69guy/rule-engine-js
📦 Try it now: npm install rule-engine-js
📚 Full docs: Comprehensive guides and examples included
🐛 Issues: Found a bug or have a feature request? I’d love to hear from you!


Rule Engine JS is MIT licensed and has zero dependencies. It works in Node.js 16+ and all modern browsers. Built by developers, for developers who are tired of hardcoding business logic.