From Conditions to Custom Code: How We Built It | Lithic
From Conditions to Custom Code: How We Built It
April 14, 2026
Mirek Klimos
Table of Contents
The challenge of complex conditions
Every card program starts with simple rules. Decline purchases at gambling merchants. Cap daily spend at $1000. Block transactions from countries you don't operate in. These are easy to configure and reason about until a client needs to decline based on more intricate conditions, such as spending patterns relative to their historical data.
That's the challenge our Rules Engine addresses. Built into Lithic's authorization platform, it's a WebAssembly-powered system that allows clients to configure authorization logic directly, eliminating the need for them to maintain their own systems. With templates for common use cases and shadow mode testing, we've expanded its capabilities to include 3DS authentication, ACH transfers, and digital wallet tokenization.
The need for expressiveness
We began with conditional expressions, but as clients built more sophisticated card programs, we faced the limits of simple conditions:
- Relative thresholds: To flag spending patterns, an operator must go beyond static comparisons.
- Fuzzy matching: Merchants often use different descriptors, requiring advanced matching techniques.
- Multi-factor risk scoring: Programs aiming to allocate risk points need more complex scoring than AND/OR conditions allow.
- Per-card behavior: Different rules for different cardholders or tiers complicate rule management.
Lithic’s platform processes events and maintains state—attributes and balances—from which we extract features for rule evaluations.
Why TypeScript
Instead of creating a custom mini-language, we built our engine on WebAssembly and chose TypeScript for its wide usage and rich ecosystem. Clients can leverage any TypeScript library, simplifying complex logic while ensuring safety and reliability.
import { toZonedTime } from 'https://esm.sh/date-fns-tz@3';
import { getDay, getHours } from 'https://esm.sh/date-fns@4';
function isHappyHour(timestamp: string): boolean {
const zonedDate = toZonedTime(timestamp, 'America/New_York');
const isFriday = getDay(zonedDate) === 5;
const hour = getHours(zonedDate);
return isFriday && hour >= 15 && hour < 22;
}
Built for AI agents
TypeScript is also excellent for AI-generated rules. Risk analysts can describe rules in simple language, allowing AI to create TypeScript implementations verified through our Dashboard. Rules undergo testing in shadow mode to ensure safety before being made live.
Deterministic by design
Rules must be explainable and reproducible. Our design ensures every execution is deterministic—features are the only inputs, and we store all evaluated features for auditing and backtesting.
Security first
User code execution requires robust security measures. Our defense-in-depth strategy includes:
- Static analysis of TypeScript programs.
- Controlled compilation to WebAssembly.
- Execution in a sandboxed environment.
- Infrastructure isolation.
Conclusion
With Custom Code, we've removed restrictions on rule complexity. We aim to enhance the expressiveness of rules and gather more contextual data to refine decision-making. Custom Code is available through our Fraud Command suite via API and the Lithic Dashboard. We invite you to explore its potential.