Frequently Asked Questions
A comprehensive guide to common questions, edge cases, and best practices for Product-FARM.
Table of Contents
- General Questions
- Getting Started
- AI Assistant
- Rule Engine & JSON Logic
- Performance & Optimization
- Data Model & Validation
- API & Integration
- Security
- Deployment & Operations
- Troubleshooting
- Advanced Topics
General Questions
What exactly is Product-FARM?
Product-FARM is a domain-agnostic rule engine platform that allows you to define, manage, and evaluate business rules without writing code. It combines:
- Visual Rule Builder: Drag-and-drop interface for creating rules
- High-Performance Engine: Sub-microsecond rule evaluation with tiered compilation
- DAG Execution: Automatic parallel execution of independent rules
- Graph Persistence: DGraph-backed storage with LRU caching
- AI Assistance: Natural language to rule translation
Think of it as a “database for business logic” that can power pricing engines, eligibility checks, risk assessments, and any other rule-based system.
How is Product-FARM different from other rule engines?
| Feature | Product-FARM | Drools | Easy Rules | JSON Logic |
|---|---|---|---|---|
| Performance | ~330ns (bytecode) | ~10-50µs | ~5-20µs | ~1-5µs |
| Visual Builder | ✅ Full | ❌ | ❌ | ❌ |
| Parallel Execution | ✅ DAG-based | Limited | ❌ | ❌ |
| AI Assistance | ✅ Built-in | ❌ | ❌ | ❌ |
| Graph Storage | ✅ DGraph | External | External | External |
| Language | Rust + React | Java | Java | JavaScript |
Key differentiators:
- Tiered compilation automatically optimizes hot paths
- DAG-based execution parallelizes independent rules
- Visual interface enables business users to manage rules
- Immutable versioning provides audit trail and safe experimentation
What types of problems is Product-FARM best suited for?
Ideal Use Cases:
- Insurance premium calculations
- Loan eligibility and pricing
- E-commerce dynamic pricing
- Risk scoring and assessment
- Tax calculations
- Discount and promotion logic
- Compliance rule checking
- Feature flag evaluation
Less Suitable For:
- Real-time streaming (sub-100µs requirements)
- Simple if/else that doesn’t change
- Machine learning model inference
- Workflow orchestration (use Temporal, Airflow)
What’s the learning curve like?
| Role | Time to Productivity |
|---|---|
| Business Analyst | 2-4 hours (visual builder) |
| Developer (integration) | 1-2 days (API usage) |
| Developer (self-hosting) | 3-5 days (deployment) |
| DevOps (production) | 1-2 weeks (scaling, monitoring) |
Getting Started
What are the system requirements?
Minimum Requirements:
- CPU: 2 cores
- RAM: 4GB
- Disk: 10GB
- OS: Linux, macOS, or Windows (with WSL2)
Recommended for Production:
- CPU: 8+ cores
- RAM: 16GB+
- Disk: 100GB+ SSD
- OS: Linux (Ubuntu 22.04+ or RHEL 8+)
Software Dependencies:
- Rust 1.75+ (for building)
- Node.js 18+ (for frontend)
- DGraph v25+ (for persistence)
Why won’t DGraph start?
Common causes and solutions:
1. Port Already in Use:
# Check what's using the ports
lsof -i :5080 # Zero
lsof -i :8080 # Alpha HTTP
lsof -i :9080 # Alpha gRPC
# Kill existing processes
pkill -f dgraph
2. Permission Issues:
# DGraph needs write access to data directory
chmod -R 755 /path/to/dgraph/data
3. Previous Unclean Shutdown:
# Remove WAL files and restart
rm -rf /path/to/dgraph/w /path/to/dgraph/zw
4. Memory Issues:
# Check available memory
free -h
# DGraph needs at least 2GB RAM
# Set memory limit if containerized
Can I run Product-FARM without DGraph?
Yes! Product-FARM supports multiple storage backends:
// In-Memory (development/testing)
StorageBackend::InMemory
// File-based (single instance, simple deployment)
StorageBackend::File
// DGraph (production, scalable)
StorageBackend::DGraph
// Hybrid (DGraph + LRU cache)
StorageBackend::Hybrid
For local development or small deployments, the file-based backend is sufficient. DGraph is recommended for production workloads requiring horizontal scaling.
How do I configure the backend?
Key environment variables:
# Server configuration
RUST_LOG=info # Log level (trace, debug, info, warn, error)
API_HOST=0.0.0.0 # Bind address
API_PORT=8081 # REST API port
GRPC_PORT=50051 # gRPC port
# DGraph connection
DGRAPH_ENDPOINT=http://localhost:9080
# Cache configuration
CACHE_PRODUCTS_SIZE=100 # Max cached products
CACHE_ATTRIBUTES_SIZE=10000 # Max cached attributes
CACHE_RULES_SIZE=10000 # Max cached rules
CACHE_COMPILED_SIZE=10000 # Max cached bytecode
AI Assistant
What can the AI assistant do?
The AI assistant is a built-in feature that helps you work with rules more efficiently:
| Capability | Description | Example |
|---|---|---|
| Create Rules | Generate rules from natural language | “Create a rule that adds 20% if age > 60” |
| Explain Rules | Get plain English explanations | “Explain how the premium calculation works” |
| Analyze Impact | See what’s affected by changes | “What would change if I modify vehicle_value?” |
| Optimize | Get improvement suggestions | “Suggest optimizations for my rules” |
How do I create a rule using AI?
Simply describe your rule in plain English:
You: "Create a rule: if customer_age > 65 AND income < 50000, apply senior discount of 15%"
AI: I've created a rule based on your description:
Name: apply_senior_discount
Expression: IF (age > 65 AND income < 50000) THEN price * 0.85 ELSE price
Inputs: [customer_age, income, price]
Outputs: [discounted_price]
Tips for better results:
- Be specific about conditions and values
- Mention input and output names if you have preferences
- Use common business terms (discount, premium, rate, factor)
How accurate is the AI rule generation?
The AI understands common patterns well:
| Pattern | Accuracy | Example |
|---|---|---|
| Simple conditions | High | “if age > 30” |
| Percentages | High | “add 20%”, “discount by 15%” |
| AND/OR logic | High | “if A and B or C” |
| Nested conditions | Medium | “if A then (if B then X else Y)” |
| Complex math | Medium | “calculate compound interest” |
Always review generated rules in the visual editor before activating.
Can AI explain my existing rules?
Yes! The AI can explain any rule or the entire DAG:
You: "Explain how premium calculation works"
AI: The premium calculation follows a multi-step process:
1. **Base Premium** (Level 0)
- Calculated from coverage_amount × rate_per_1000
2. **Risk Factors** (Level 0, parallel)
- age_factor: 0.9x (under 30), 1.0x (30-50), 1.2x (over 50)
- smoker_factor: 1.3x if smoker, 1.0x otherwise
3. **Final Premium** (Level 1)
- base_premium × age_factor × smoker_factor
4. **Monthly Payment** (Level 2)
- final_premium ÷ 12
How does impact analysis work?
When you ask about changing an attribute, the AI traces all dependencies:
You: "What would be affected if I change base_rate?"
AI: Changing base_rate would impact:
┌─ Direct Dependencies ─────────────────────┐
│ • calculate_base_premium (uses base_rate) │
│ • calculate_tier_premium (uses base_rate) │
└───────────────────────────────────────────┘
┌─ Downstream Effects ──────────────────────┐
│ • final_premium (depends on base_premium) │
│ • monthly_payment (depends on final) │
│ • annual_cost (depends on final) │
└───────────────────────────────────────────┘
⚠️ Total: 5 rules affected across 3 DAG levels
What optimization suggestions does the AI provide?
The AI analyzes your rules and identifies:
Performance Issues:
- Rules that could be combined
- Duplicate calculations
- Unnecessary dependencies
Maintainability Issues:
- Missing descriptions
- Duplicate logic patterns
- Confusing naming
Potential Bugs:
- Impossible conditions (dead code)
- Missing edge cases
- Type mismatches
Does the AI require an internet connection?
The AI assistant requires connectivity to process your requests. Your rule data is sent to the AI service for analysis.
Data Privacy:
- Only rule definitions and metadata are sent
- No customer/transaction data is transmitted
- Requests are not stored or used for training
Can I disable the AI assistant?
Yes, the AI assistant panel can be hidden. Click the AI button in the top right to toggle it off. The core rule engine functionality works completely without AI.
Why did the AI generate an incorrect rule?
The AI may misunderstand complex or ambiguous requirements:
Common Issues:
| Problem | Solution |
|---|---|
| Wrong variable names | Specify exact names: “use customer_age not age” |
| Wrong direction | Be explicit: “add 20%” vs “reduce by 20%” |
| Missing conditions | List all conditions: “if A AND B AND C” |
| Wrong operators | Specify: “greater than or equal” vs “greater than” |
Best Practice: Use AI for first drafts, then refine in the visual editor.
Rule Engine & JSON Logic
What JSON Logic operations are supported?
Product-FARM supports 60+ JSON Logic operations:
Arithmetic:
{"+": [1, 2]} // 3
{"-": [5, 3]} // 2
{"*": [4, 5]} // 20
{"/": [10, 2]} // 5
{"%": [7, 3]} // 1
{"min": [1, 2, 3]} // 1
{"max": [1, 2, 3]} // 3
Comparison:
{"==": [1, 1]} // true (loose equality)
{"===": [1, "1"]} // false (strict equality)
{"!=": [1, 2]} // true
{">": [5, 3]} // true
{">=": [5, 5]} // true
{"<": [3, 5]} // true
{"<=": [5, 5]} // true
Logic:
{"and": [true, true]} // true
{"or": [false, true]} // true
{"!": [true]} // false
{"!!": [1]} // true (truthy check)
{"if": [cond, then, else]} // conditional
Arrays:
{"map": [[1,2,3], {"*": [{"var":""}, 2]}]} // [2,4,6]
{"filter": [[1,2,3,4], {">": [{"var":""}, 2]}]} // [3,4]
{"reduce": [[1,2,3], {"+": [{"var":"acc"}, {"var":"cur"}]}, 0]} // 6
{"all": [[1,2,3], {">": [{"var":""}, 0]}]} // true
{"some": [[1,2,3], {">": [{"var":""}, 2]}]} // true
{"none": [[1,2,3], {"<": [{"var":""}, 0]}]} // true
{"merge": [[1,2], [3,4]]} // [1,2,3,4]
{"in": [2, [1,2,3]]} // true
Strings:
{"cat": ["Hello", " ", "World"]} // "Hello World"
{"substr": ["Hello", 0, 3]} // "Hel"
{"in": ["ello", "Hello"]} // true
Data Access:
{"var": "customer.age"} // Get nested value
{"var": ["customer.age", 0]} // With default
{"missing": ["a", "b"]} // Missing fields
{"missing_some": [1, ["a", "b", "c"]]} // At least 1 missing
How does type coercion work?
Product-FARM uses loose equality (JavaScript-style) by default:
// These are all true with "=="
{"==": [1, "1"]} // true (string to number)
{"==": [true, 1]} // true (bool to number)
{"==": [false, 0]} // true
{"==": [null, null]} // true
{"==": ["", false]} // true (both falsy)
// Use "===" for strict comparison
{"===": [1, "1"]} // false
{"===": [true, 1]} // false
Type Conversion Rules:
- Strings to numbers:
"123"→123,"abc"→NaN - Booleans to numbers:
true→1,false→0 - Null handling:
nullequals onlynullorundefined - Array to string:
[1,2,3]→"1,2,3"
What happens with division by zero?
Division by zero is handled gracefully:
{"/": [10, 0]} // Returns error, not Infinity
{"/": [0, 0]} // Returns error, not NaN
The engine returns a DivisionByZero error that you can catch and handle.
How deep can expressions be nested?
The bytecode VM has a stack depth limit of 1024. This prevents:
- Stack overflow attacks
- Infinite recursion
- Runaway expressions
In practice, this allows expressions ~200 levels deep, which is far more than any real-world use case.
Can I create custom operations?
Not directly in JSON Logic. However, you can:
- Compose existing operations into complex expressions
- Create helper rules that other rules reference
- Use the AI assistant to generate complex logic
If you need truly custom operations, you would need to modify the Rust source code in crates/json-logic/src/operations.rs.
How do I handle missing variables?
Several approaches:
1. Default values:
{"var": ["customer.discount", 0]} // Returns 0 if missing
2. Check existence first:
{
"if": [
{"missing": ["discount"]},
0,
{"var": "discount"}
]
}
3. Use missing_some for optional fields:
{
"if": [
{"missing_some": [1, ["field1", "field2", "field3"]]},
"insufficient data",
"proceed"
]
}
Performance & Optimization
How does tiered compilation work?
Product-FARM uses a two-tier compilation strategy:
flowchart LR
subgraph Tier0["Tier 0: AST Interpretation"]
T0["~1.15µs per eval"]
end
subgraph Tier1["Tier 1: Bytecode VM"]
T1["~330ns per eval"]
end
Tier0 -->|"After 100 evals"| Tier1
style Tier0 fill:#fef3c7,stroke:#f59e0b,color:#000
style Tier1 fill:#d1fae5,stroke:#10b981,color:#000
- Tier 0 (AST): First 100 evaluations use direct AST interpretation
- Tier 1 (Bytecode): After 100 evals, expression is compiled to bytecode
- Promotion is automatic: No configuration needed
- Speedup: 3.5x faster (1.15µs → 330ns)
What’s the expected throughput?
| Configuration | Throughput | Latency (p99) |
|---|---|---|
| Single-threaded, Tier 0 | ~870K/sec | ~1.5µs |
| Single-threaded, Tier 1 | ~3M/sec | ~400ns |
| Multi-threaded (8 cores), Tier 1 | ~22M/sec | ~600ns |
Real-world performance depends on:
- Rule complexity (number of operations)
- DAG depth (sequential dependencies)
- Cache hit rate
- Network latency (if using remote storage)
How do I optimize slow rules?
1. Check DAG structure:
GET /api/products/{id}/execution-plan
Look for rules that could be parallelized but are sequential.
2. Reduce rule complexity:
- Split complex rules into simpler ones
- Use lookup tables instead of long if/else chains
- Avoid deeply nested expressions
3. Ensure bytecode compilation:
- Rules need 100+ evaluations to promote
- Pre-warm with batch evaluation on startup
4. Optimize cache settings:
# Increase cache sizes for frequently accessed rules
CACHE_RULES_SIZE=50000
CACHE_COMPILED_SIZE=50000
Why are my rules running sequentially?
Rules run sequentially when they have dependencies:
flowchart TB
A["base_price"] --> C["final_price"]
B["discount"] --> C
C --> D["monthly_payment"]
In this DAG:
base_priceanddiscountrun in parallel (Level 0)final_priceruns after both complete (Level 1)monthly_paymentruns last (Level 2)
To maximize parallelism:
- Keep DAG “wide” not “deep”
- Minimize cross-rule dependencies
- Use inputs directly when possible
How does caching work?
Product-FARM uses a write-through LRU cache:
flowchart LR
Request["Request"] --> Cache{"LRU Cache"}
Cache -->|"Hit ~1µs"| Response["Response"]
Cache -->|"Miss"| DGraph["DGraph ~1-5ms"]
DGraph --> Update["Update Cache"]
Update --> Response
Cache Layers:
- Compiled Rules Cache: Bytecode stored in memory
- Rule Definition Cache: Rule metadata and expressions
- Attribute Cache: Attribute definitions and types
- Product Cache: Product configurations
Cache Invalidation:
- Automatic on write operations
- Manual via
POST /api/cache/invalidate - Full clear via
POST /api/cache/clear
Data Model & Validation
What naming conventions must I follow?
Product-FARM enforces strict naming patterns:
| Entity | Pattern | Example | Max Length |
|---|---|---|---|
| Product ID | ^[a-zA-Z][a-zA-Z0-9_]*$ |
insurance_premium_v1 |
51 |
| Product Name | ^[a-zA-Z0-9,.\-_:' ]+$ |
Insurance Premium Calculator |
50 |
| Component Type | ^[a-z][-a-z]*$ |
customer-info |
51 |
| Attribute Name | ^[a-z][a-z0-9.\-]*$ |
base.premium.amount |
101 |
| Tag Name | ^[a-z][-a-z]*$ |
pricing-rule |
51 |
| Enum Value | ^[A-Z][A-Z0-9_]*$ |
PREMIUM_TIER |
51 |
Common Mistakes:
- Starting with number: ❌
123product - Uppercase in IDs: ❌
MyProduct(usemy-product) - Spaces: ❌
my product(usemy-productormy_product) - Special characters: ❌
product@v1(only alphanumeric,-,_,.)
How do attribute paths work?
Attributes use a hierarchical path structure:
{productId}:{componentType}:{componentId}:{attributeName}
Examples:
insuranceV1:customer:main:age
insuranceV1:policy:basic:coverage_amount
insuranceV1:premium:calculated:final_amount
Abstract vs Concrete:
- Abstract: Template attributes without specific component instance
- Concrete: Instantiated attributes with actual values
# Abstract (template)
insuranceV1:abstract-path:customer:age
# Concrete (instance)
insuranceV1:customer:cust-001:age
What datatypes are supported?
Primitive Types:
| Type | Description | Example |
|——|————-|———|
| boolean | True/false | true, false |
| integer | Whole numbers | 42, -17 |
| decimal | Precise decimals | 123.45 |
| string | Text | "hello" |
| date | Date only | "2024-01-15" |
| datetime | Date and time | "2024-01-15T14:30:00Z" |
Complex Types:
| Type | Description | Example |
|——|————-|———|
| array | List of values | [1, 2, 3] |
| object | Key-value map | {"a": 1, "b": 2} |
| enumeration | Predefined values | "PREMIUM" from [BASIC, STANDARD, PREMIUM] |
Custom Datatypes: You can create custom datatypes with constraints:
{
"id": "percentage",
"primitive": "decimal",
"constraints": {
"min": 0,
"max": 100,
"precision": 2
}
}
How do I handle complex nested data?
Use dot notation in variable paths:
// Input data
{
"customer": {
"profile": {
"age": 35,
"income": 75000
},
"policies": [
{"type": "auto", "premium": 500},
{"type": "home", "premium": 800}
]
}
}
// Access nested values
{"var": "customer.profile.age"} // 35
{"var": "customer.profile.income"} // 75000
{"var": "customer.policies.0.premium"} // 500 (first policy)
For array operations:
// Sum all premiums
{"reduce": [
{"var": "customer.policies"},
{"+": [{"var": "accumulator"}, {"var": "current.premium"}]},
0
]}
// Result: 1300
API & Integration
REST vs gRPC: Which should I use?
| Aspect | REST | gRPC |
|---|---|---|
| Use Case | Management, CRUD | High-throughput evaluation |
| Latency | ~2-5ms | ~0.5-1ms |
| Streaming | ❌ | ✅ |
| Browser Support | ✅ | Limited (gRPC-Web) |
| Debugging | Easy (curl, Postman) | Harder (need tools) |
Recommendation:
- Use REST for admin operations (create products, rules)
- Use gRPC for evaluation in production services
- Use REST for prototyping and debugging
How do I handle batch evaluations?
For high throughput, use batch evaluation:
POST /api/products/{id}/batch-evaluate
Content-Type: application/json
{
"functionality": "quote",
"batch_inputs": [
{"customer_age": 25, "coverage": 100000},
{"customer_age": 35, "coverage": 200000},
{"customer_age": 45, "coverage": 300000}
]
}
Response:
{
"results": [
{"outputs": {"premium": 1200}, "success": true},
{"outputs": {"premium": 2400}, "success": true},
{"outputs": {"premium": 4800}, "success": true}
],
"total_time_ms": 15,
"avg_time_ms": 5
}
Best Practices:
- Batch size: 100-1000 items optimal
- Max batch size: Limited by 16MB message size
- Use gRPC streaming for unlimited batch sizes
What’s the API rate limit?
Current State: No built-in rate limiting.
Recommended Setup: Use a reverse proxy (nginx, Envoy) for rate limiting:
# nginx.conf
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;
location /api/ {
limit_req zone=api burst=200 nodelay;
proxy_pass http://localhost:8081;
}
How do I integrate with my existing system?
Option 1: Direct API Calls
import requests
def evaluate_premium(customer_data):
response = requests.post(
"http://product-farm:8081/api/products/insurance-v1/evaluate",
json={
"functionality": "quote",
"inputs": customer_data
}
)
return response.json()["outputs"]
Option 2: gRPC Client
use product_farm_client::ProductFarmClient;
let client = ProductFarmClient::connect("http://product-farm:50051").await?;
let result = client.evaluate("insurance-v1", "quote", inputs).await?;
Option 3: Event-Driven (Future) Product-FARM roadmap includes webhook support for event-driven integration.
How do I handle API errors?
All errors return structured responses:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input",
"details": [
{
"field": "customer_age",
"code": "OUT_OF_RANGE",
"message": "Value must be between 0 and 150"
}
]
}
}
Error Codes:
| Code | HTTP Status | Description |
|——|————-|————-|
| VALIDATION_ERROR | 400 | Invalid request data |
| NOT_FOUND | 404 | Resource doesn’t exist |
| CONFLICT | 409 | State conflict (e.g., duplicate) |
| IMMUTABLE | 409 | Cannot modify active product |
| INTERNAL_ERROR | 500 | Server error |
Security
Is Product-FARM secure for production?
Current Security Features:
- ✅ Input validation (strict regex patterns)
- ✅ Sandboxed expression evaluation (no code injection)
- ✅ Stack depth limits (DoS protection)
- ✅ Type-safe operations (no arbitrary code execution)
Missing (Must Add for Production):
- ❌ Authentication (add via reverse proxy)
- ❌ Authorization (no RBAC yet)
- ❌ Rate limiting (add via reverse proxy)
- ❌ Audit logging (planned)
- ❌ Encryption at rest (DGraph configuration)
How do I add authentication?
Product-FARM doesn’t have built-in authentication. Add it via reverse proxy:
Option 1: nginx with JWT
location /api/ {
auth_jwt "Product-FARM API";
auth_jwt_key_file /etc/nginx/jwt-key.pem;
proxy_pass http://localhost:8081;
}
Option 2: OAuth2 Proxy
# docker-compose.yml
oauth2-proxy:
image: quay.io/oauth2-proxy/oauth2-proxy
args:
- --provider=oidc
- --upstream=http://product-farm:8081
- --cookie-secret=...
Option 3: API Gateway (Kong, Envoy) Use your existing API gateway with authentication plugins.
Can JSON Logic expressions be malicious?
JSON Logic is sandboxed by design:
- ❌ No file system access
- ❌ No network calls
- ❌ No code execution
- ❌ No global state modification
- ❌ No infinite loops (stack limit)
Expressions can only:
- Access data from the provided context
- Perform mathematical/logical operations
- Return computed values
However, malicious expressions could:
- Consume CPU (complex nested expressions)
- Return unexpected results (logic errors)
Mitigations:
- Validate expressions before saving
- Set execution timeouts
- Monitor evaluation times
How do I secure DGraph?
Network Security:
# Bind to localhost only
dgraph alpha --my=localhost:7080 --security whitelist=127.0.0.1
TLS Encryption:
dgraph alpha \
--tls_cacert=/path/to/ca.crt \
--tls_cert=/path/to/server.crt \
--tls_key=/path/to/server.key
Access Control:
# Enable ACL (Enterprise feature)
dgraph alpha --acl_secret_file=/path/to/secret
Deployment & Operations
What’s the recommended production architecture?
flowchart TB
subgraph LB["Load Balancer"]
nginx["nginx/HAProxy"]
end
subgraph API["API Tier (Stateless)"]
api1["Product-FARM 1"]
api2["Product-FARM 2"]
api3["Product-FARM 3"]
end
subgraph Storage["Storage Tier"]
dg1["DGraph Alpha 1"]
dg2["DGraph Alpha 2"]
dgz["DGraph Zero"]
end
nginx --> api1
nginx --> api2
nginx --> api3
api1 --> dg1
api2 --> dg1
api3 --> dg2
dg1 --> dgz
dg2 --> dgz
Key Points:
- API nodes are stateless (can scale horizontally)
- Each API node has its own LRU cache
- DGraph handles data replication
- Load balancer distributes requests
How do I monitor Product-FARM?
Current Logging:
# Set log level
RUST_LOG=info cargo run
# Log levels: trace, debug, info, warn, error
Planned Metrics (Roadmap):
- Prometheus endpoint
- Evaluation latency histogram
- Cache hit/miss ratio
- Rule execution counts
DIY Monitoring:
# Health check endpoint (gRPC)
grpcurl -plaintext localhost:50051 product_farm.ProductFarmService/HealthCheck
# Simple HTTP health (REST)
curl http://localhost:8081/api/health
How do I backup and restore?
File-based Backend:
# Backup
cp -r /path/to/data /path/to/backup/
# Restore
cp -r /path/to/backup/ /path/to/data/
DGraph Backend:
# Export (backup)
curl -X POST localhost:8080/admin -d '{
"query": "mutation { export(format: \"json\") { response { code } }}"
}'
# Import (restore)
dgraph live -f export.json -a localhost:9080 -z localhost:5080
How do I scale horizontally?
API Tier:
- Deploy multiple API instances
- Configure load balancer
- Each instance connects to same DGraph cluster
- LRU caches are per-instance (eventually consistent)
DGraph Tier:
- Add Alpha nodes for read scaling
- Add Zero nodes for HA (3 recommended)
- Use replication for fault tolerance
Cache Considerations:
- Each API instance has its own cache
- Write operations invalidate local cache
- Other instances may serve stale data briefly
- Use short TTLs or disable caching for critical paths
Troubleshooting
Why is my rule returning unexpected results?
1. Check variable names:
// Wrong - case mismatch
{"var": "Customer_Age"} // Returns null if data has "customer_age"
// Correct
{"var": "customer_age"}
2. Check type coercion:
// May behave unexpectedly
{"==": [{"var": "age"}, "25"]} // String comparison
// Be explicit
{"==": [{"var": "age"}, 25]} // Number comparison
3. Use the simulation panel: The UI provides step-by-step execution traces to debug logic.
Why is evaluation slow?
Checklist:
- Is bytecode compilation happening? (need 100+ evals)
- Is the DAG too deep? (many sequential dependencies)
- Are cache sizes adequate?
- Is DGraph responding slowly?
Diagnostic Steps:
# Check execution plan
GET /api/products/{id}/execution-plan
# Check cache stats
GET /api/cache/stats
# Enable debug logging
RUST_LOG=debug cargo run
Why can’t I modify my product?
Products in ACTIVE or DISCONTINUED status are immutable.
To make changes:
- Clone the product:
POST /api/products/{id}/clone - Modify the clone (which is in
DRAFTstatus) - Submit for approval:
POST /api/products/{id}/submit - Approve:
POST /api/products/{id}/approve - Discontinue the old version if needed
Why is my rule validation failing?
Common Validation Errors:
| Error | Cause | Solution |
|---|---|---|
CYCLE_DETECTED |
Rule depends on its own output | Remove circular dependency |
MISSING_INPUT |
Referenced attribute doesn’t exist | Create attribute first |
TYPE_MISMATCH |
Operation incompatible with datatype | Check input/output types |
INVALID_EXPRESSION |
JSON Logic syntax error | Validate JSON structure |
How do I debug DAG execution?
1. Get execution plan:
GET /api/products/{id}/execution-plan
Returns:
{
"levels": [
{"level": 0, "rules": ["base_premium", "age_factor", "smoker_factor"]},
{"level": 1, "rules": ["final_premium"]},
{"level": 2, "rules": ["monthly_payment"]}
],
"total_rules": 5,
"max_parallel": 3
}
2. Use the DAG visualization in the UI
3. Check for unexpected dependencies: Rules at higher levels may indicate unnecessary dependencies.
Advanced Topics
How do I implement A/B testing for rules?
Option 1: Product Cloning
- Clone your product:
insurance-v1→insurance-v1-experiment - Modify rules in the experiment
- Route traffic based on user segment
Option 2: Conditional Rules
{
"if": [
{"==": [{"var": "experiment_group"}, "B"]},
{"*": [{"var": "base_price"}, 0.9]}, // 10% discount
{"var": "base_price"} // Control
]
}
Can I use Product-FARM for real-time pricing?
Yes, with caveats:
Suitable for:
- ~1ms latency acceptable
- 10K-100K requests/second
- Rules change infrequently
May need optimization for:
- Sub-100µs requirements
- 1M+ requests/second
- Rules change every minute
Tips for real-time:
- Pre-warm bytecode cache
- Use gRPC for lower latency
- Deploy API nodes close to consumers
- Consider read replicas for DGraph
How do I version control my rules?
Current Approach:
- Products have immutable versions (clone to modify)
- Each product has status lifecycle
- No built-in diff/merge
Recommended Workflow:
- Export rules to JSON:
GET /api/products/{id}/export - Store in Git repository
- Use CI/CD to deploy rule changes
- Track changes via Git history
Future (Roadmap):
- Built-in rule versioning
- Diff visualization
- Rollback to previous versions
How do I handle multi-tenant scenarios?
Option 1: Product Naming Convention
{tenant}-insurance-v1
acme-insurance-v1
globex-insurance-v1
Option 2: Separate Instances Deploy separate Product-FARM instances per tenant.
Option 3: Wait for Multi-Tenant Support (Roadmap) Built-in tenant isolation is planned.
What’s the maximum rule complexity?
Practical Limits: | Metric | Limit | Reason | |——–|——-|——–| | Stack depth | 1024 | VM limit | | Bytecode size | 65535 ops | u16 addressing | | Rules per product | 10,000 | DoS protection | | Attributes per product | 100,000 | DoS protection | | Nested depth | ~200 levels | Stack limit |
If you hit limits:
- Split into multiple products
- Use helper rules to reduce complexity
- Contact maintainers for enterprise support
Getting Help
Where can I get support?
- GitHub Issues: Bug reports and feature requests
- GitHub Discussions: Questions and community help
- Documentation: Product-FARM Docs
How can I contribute?
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
See CONTRIBUTING.md for details.