Hard-Coded Pricing Logic: Why Pricing Takes 5 Days
In competitive industries like aviation, e-commerce, and fintech, the speed of decision-making is often more critical than the decision itself. When a competitor drops prices or a new risk factor emerges, the window to react is measured in hours.
However, in many enterprise architectures, business logic, the specific rules determining pricing, eligibility, or risk, is tightly coupled with the application code.
This architectural pattern creates a bottleneck: every adjustment to a pricing model triggers a full Software Development Life Cycle. A change that should take minutes ends up taking to days due to development, testing, code reviews, and deployment pipelines.
This case study analyzes the impact of decoupling pricing logic using a Business Rules Engine (BRE) like DecisionRules, using a live Flight Booking application as a reference implementation.
Logic Embedded in Code
The traditional approach to implementing dynamic pricing involves writing conditional logic directly into backend services (e.g., Node.js or Python). While this works for simple applications, it becomes unmanageable at scale.
Consider a standard pricing function. The logic is typically scattered across multiple files with nested conditionals.
The "Hard-Coded" Implementation
Below is a simplified example of how pricing rules typically look inside a Node.js or Python service:
// ⚠️ THE ANTI-PATTERN: Business logic coupled with application code
function calculateTicketFare(origin, destination, cabinClass, type, adults) {
let baseFare = 0;
// Logic explicitly defined in code
if (origin === "HND" && destination === "IST") {
baseFare = cabinClass === "Economy" ? 800 :
cabinClass === "Business" ? 2000 : 3500;
} else if (origin === "ATL" && destination === "DXB") {
// ... logic repeats for hundreds of routes
baseFare = 900;
}
// Hard-coded multipliers require redeployment to change
if (type === "Round") baseFare *= 1.8;
// Complex calculation hidden in the backend
return (adults * baseFare) + (children * baseFare * 0.75);
} The Operational Cost
This approach introduces significant friction:
- High Latency: Responding to a market change requires a developer to modify the code, update unit tests, pass code review, and deploy.
- Test Churn: A minor change in a variable (e.g., changing the round-trip multiplier from 1.8 to 1.7) requires updating regression tests, increasing the risk of introducing bugs.
- Opaque Logic: Business stakeholders (Revenue Managers) cannot validate the logic directly; they must rely on developers to interpret the code.
The Solution: Decoupling Logic via API
The alternative architecture applies the Separation of Concerns principle. The application handles the workflow (UI, DB, Orchestration), while a dedicated Business Rules Engine (like DecisionRules) handles the logic. The pricing function is transformed from a calculation into an I/O operation: the application sends the context (Trip Details), and the engine returns the decision (Price).
The Flight Booking Reference App
To measure the impact of this architecture, we examined a fully functional Flight Booking sample application. The system processes a 3-step flow:
- Trip Selection: Origin, Destination, Class.
- Ancillaries: Seat selection, Luggage, Insurance.
- Pricing: Final calculation.
By migrating the logic to DecisionRules, the application code was reduced significantly, and the control of pricing parameters was handed over to business users.
Implementation: From Code to Configuration
In the Flight Booking reference application, we abstract the variables to avoid "magic numbers" in the code. Instead of embedding values, we define specific Rule Variables in the engine that business users can manage.
1. Defining the Input/Output Model
The first step is abstracting the variables. In DecisionRules, we define a JSON structure that the rule expects. This acts as the contract between the application and the engine.
- Input Model: origin, destination, class, passengers, ancillaryServices
- Output Model: baseFare, taxes, totalPrice, breakdown
2. Building the Decision Table
Instead of if-else statements, the logic is represented in a Decision Table. The engine matches input rows (Conditions) to determine the output (Results).
Key Business Variables (Configured in Engine):
- roundTripMultiplier: 1.8
- seatPrice: 35
- childFarePercentage: 0.85
- additionalLuggagePricePerBag: 55
- airportLoungePricePerAdult: 60
If the price of a seat increases, a user updates the seatPrice variable, and it propagates across all rules immediately without code deployment.
Key Feature: Complex Functions
DecisionRules supports advanced functions for dynamic calculations. For example, calculating the price of selected seats doesn't require external code. It is handled directly in the rule result column using array functions:
// ✅ THE MODERN PATTERN: Delegating logic to the engine
const response = await fetch(
`https://api.decisionrules.io/rule/solve/flight-tickets-pricing`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.DECISION_RULES_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
data: {
tripDetails: {
origin: "HND",
destination: "IST",
classOfService: "Business",
passengers: { adults: 2, children: 1 }
},
ancillaryServices: {
loungeAccess: true,
extraBags: 2
}
}
})
}
);
const pricing = (await response.json())[0];
// Result: pricing.grandTotalPrice = 5450 Technical Deep Dive: Performance & Architecture
When evaluating a BRE for enterprise use, three non-functional requirements are paramount: latency, versioning, and security.
Latency and Caching
Offloading logic introduces a network hop, but efficient BREs mitigate this. The DecisionRules Solver API typically executes complex decision tables in milliseconds.
- Caching Strategy: The engine caches rule definitions. If the same rule is called repeatedly, the engine does not need to re-fetch the rule structure from the database, significantly reducing processing time.
- Regional Edge: API calls can be routed to the nearest data center to minimize network latency.
Versioning and Rollbacks
In a hard-coded environment, rolling back a pricing error requires reverting a Git commit and re-deploying.
In DecisionRules, every save creates a new immutable version.
- The API allows pinning a specific version (e.g., v1.2) for stability or using the latest version for agility.
- If a new pricing strategy underperforms, the business can revert to the previous version instantly via the UI, with zero downtime.
Audit Trails and Security
Financial and pricing systems require strict auditability.
- RBAC (Role-Based Access Control): Granular permissions ensure that only authorized personnel (e.g., Senior Revenue Managers) can publish changes to production rules.
- Event Logs: Every change is logged with a timestamp, user ID, and a diff of the values changed. This provides a complete compliance trail that is difficult to achieve with standard code repositories.
Comparative Analysis
The following table compares the operational metrics of maintaining pricing logic in code versus using a dedicated engine.
| Metric | Hard-Coded Architecture | Business Rules Engine |
|---|---|---|
| Change Workflow | Code → Unit Test → QA → Deploy | Edit Value → Save → Publish |
| Time-to-Market | 3-5 Days | < 65 Seconds |
| Testing Scope | Full Regression Required | Isolated Rule Test Bench |
| Maintenance Cost | High (Technical Debt) | Low (Configuration) |
| Metric | Hard-Coded Architecture | Business Rules Engine |
| Change Workflow | Code → Unit Test → QA → Deploy | Edit Value → Save → Publish |
Real-World Workflow Scenario
To illustrate the speed difference, consider a scenario where a competitor drops Business class fares on the HND → IST route, and the pricing team needs to match it immediately.
Workflow with Business Rules Engine:
- Revenue manager opens decision table: 10 sec
- Finds HND → IST Business class row: 20 sec
- Updates Price ($2000 → $1700): 30 sec
- Clicks "Publish": 5 sec
- Total Time: 65 Seconds
Conclusion
Hard-coding business logic is a sustainable practice only for static, unchanging rules. For dynamic systems like pricing, fraud detection, or eligibility scoring, "Logic as Code" becomes a liability that hampers business agility.
By adopting "Logic as Configuration" via a tool like DecisionRules, organizations achieve:
- Agility: Reacting to market changes in real-time.
- Transparency: Logic is visible and understandable to business owners.
- Efficiency: Developers are freed from maintenance tasks to focus on feature innovation.
The Flight Booking case study demonstrates that complex pricing does not belong in the codebase. It belongs in a system designed to manage complexity.
About the Author: Lukas Martincek is a Fullstack Developer at DecisionRules with over 4 years of experience in full-stack web development. He currently specializes in integrating Large Language Models (LLMs) with business rules engine to automate rule generation, expression writing, and documentation search.
Lukas Martincek
Fullstack Developer