Design paper
Programmable payments: conditional money flows as event-driven state machines
Abstract
Marketplaces, subscriptions, usage billing and multi-party payouts need money to move when something happens, not on a fixed calendar. We describe a design for a programmable payments engine in which payouts, holds, splits, refunds and reserves are written as declarative rules over commerce events and compiled to finite state machines. The design has six parts: a payment graph of parties and accounts, a rule language, an event subscription layer, a jurisdictional policy layer, a risk-informed condition layer, and an execution layer with idempotent steps and compensating actions, plus an audit record that explains every transfer and every hold. We argue each part from published work on smart contracts and their failures, long-lived transactions, model checking, messaging without distributed transactions, fraud detection under delayed labels, two-sided platforms and explanations of automated decisions. We give a component map, a worked split model with its inputs shown, and the measurements a deployment would need before any outcome could be claimed. This is a design proposal, not a measured result.
Method. Design paper: the architecture is argued from the cited literature; we report no measurements of our own. Table 2 is a worked model with its inputs shown and labelled hypothetical.
1Context and motivation
The simplest card payment has two parties and one schedule: the buyer pays, the processor settles after a fixed delay, and a refund is handled by hand. Many commerce models no longer fit that shape. A marketplace divides one payment among a seller, the platform, an affiliate, a carrier and a tax authority. A subscription with metered usage charges a fixed fee plus a variable amount that depends on events recorded during the period. A creator or on-demand platform pays out per job or per milestone. In each case the question is not only how much moves but when, and the answer depends on events: shipment, delivery, the end of a return window, a usage record, a dispute.
Platforms of this kind serve two groups at once, and must keep both on board: payment systems are one of the standard examples of such two-sided markets1. Payout timing is part of that balance. Releasing funds early helps sellers' cash flow and raises the platform's exposure to reversals; holding them protects the platform and pushes the cost onto sellers. Fast payment services, which make funds available to the payee immediately and around the clock2, remove the technical reason for long settlement delays, so the remaining delay becomes a policy choice that ought to be stated.
When that policy lives in application code, each new business model needs new code, schedules drift from the events they are meant to follow, and an affected party cannot see why a payout did or did not happen. We propose instead that conditional money flows be written as rules over events and executed by a dedicated engine. This paper describes that design and the reasons for each part. We do not report its effects, because we have not measured them.
2Background
The idea of encoding a contractual relationship in a program is older than the current payment rails. Smart contracts were proposed as protocols that formalise and secure relationships over computer networks, with payment systems and credit among the intended applications3. Blockchain platforms later made such programs executable, and their record shows the risk: a study of contracts on Ethereum found that a symbolic execution tool flagged 8,833 of 19,336 existing contracts as potentially vulnerable, including the bug behind a reported 60 million US dollar loss4. Our design does not use a blockchain, but it takes the lesson: money logic written as general-purpose code is hard to get right, so the language should be narrow and the result should be checkable before it runs.
Two older lines of work supply the checking and the execution model. Model checking verifies that a finite-state system meets a temporal-logic specification, with an algorithm linear in the size of the specification and of the state graph5. Sagas treat a long-lived transaction as a sequence of smaller transactions, each with a compensating transaction that amends a partial execution if a later step fails6. A payout that waits days for a delivery event is a long-lived transaction in exactly this sense.
3Design principles
- Events, not calendars. A flow advances when a named event arrives. A time limit (a return window, a dispute deadline) is itself modelled as an event.
- Declarative and narrow. Flows are written in a small rule language whose programs compile to finite state machines. Arbitrary computation is not allowed inside a flow.
- Verified before it runs. Every compiled flow is checked against invariants before deployment.
- Compensate, do not roll back. A step that cannot be undone is paired with a compensating step that restores the balance.
- Policy outranks optimisation. Jurisdictional rules are hard constraints. Learned parameters may tune a flow only inside them.
- Every movement is explained. Each transfer and each hold records the rule, the events and the values that caused it.
4Architecture
4.1Payment graph
The payment graph lists the parties (buyer, merchant, sub-merchant, partner, platform, tax account) and the accounts through which money may move between them. An edge exists only where the contract and the licence allow it. A flow cannot move money along an edge that is not in the graph, which turns an entire class of mistakes into a compile-time error.
4.2Rule language
A flow is a set of rules of the form "on event, if condition, then action". Actions are drawn from a fixed set: transfer, hold, release, split, refund, adjust, top up reserve, collect fee. A typical rule reads: on delivery confirmed, if the return window has elapsed and no dispute is open and the risk band is not high, then release the seller's share. The compiler turns the rules into a state machine whose states (pending, captured, held, released, refunded, disputed) and transitions are explicit.
4.3Verification
Before deployment, the compiled machine is model-checked against invariants written as temporal-logic properties5. Examples: the sum of all splits equals the captured amount; no state releases funds while a dispute is open; every held amount is eventually either released or refunded; no transition sends money along an edge outside the payment graph. A flow that fails a property is rejected with the counterexample path. The state machines we expect are small enough for this to be practical, which is one reason the rule language is kept narrow.
4.4Event subscription
The engine subscribes to order, fulfilment, usage, support and dispute events, and to external notices such as bank returns and chargebacks. Large systems that avoid distributed transactions coordinate through messages between separately owned pieces of data7, and messages in such systems can arrive twice or late. Every action therefore carries an idempotency key, so that a repeated event cannot pay twice, and the engine processes events by event time with an explicit rule for late arrivals8.
4.5Execution and compensation
Each flow runs as a saga6. A release that has been sent to a bank cannot be recalled by the engine, so its compensating step is a recovery entry against the receiving party's balance or reserve. A split that fails after the platform fee is collected compensates by reversing the fee entry. The ledger records both the forward and the compensating entries, so the history is never overwritten.
4.6Policy layer
Jurisdictional rules sit above every flow. They cover who may hold funds and for how long, which parties need a licence, tax withholding at source, and anti-money-laundering checks. The policy layer validates a flow for each region in which it runs and blocks deployment where a rule would be breached. These rules come from legal review per country; the engine enforces them but does not decide them.
4.7Risk-informed conditions
Some conditions depend on a prediction: the probability that an order will be reversed, that a new seller is fraudulent, or that a usage spike is an error. Fraudsters adapt to fixed controls over time, which is why statistical detection is needed alongside prevention9. Fraud models also learn under verification latency: only a small share of transactions is checked by investigators in time, and confirmed labels arrive late10. That delay is the main reason a hold exists at all, and the design makes it explicit: a hold lasts until either the relevant labels would normally have arrived or a release condition is met.
Learned models supply inputs to conditions (a risk band, a reserve fraction); they do not write rules. A change to a learned parameter, such as the reserve fraction for a cohort, is tested as a controlled experiment with guardrail metrics before it is adopted11. Protected attributes are not inputs.
4.8Audit and explanation
Every state change records the rule that fired, the events that satisfied it and the parameter values used. Each party sees a statement in its own terms: "Your payout of this order is held because the return window closes on 14 March; it will be released then unless a return is opened." This follows the argument that an explanation of an automated decision can be useful without exposing the model, if it tells the person what would have to change for a different outcome12. Every hold can be appealed, and an appeal reaches a person.
Table 1 summarises the components.
| Component | Problem it addresses | Evidence |
|---|---|---|
| Narrow rule language, no general code | Money logic in general-purpose programs is often vulnerable | 3, 4 |
| Model checking of compiled flows | Splits that do not sum, releases during disputes | 5 |
| Saga execution with compensating steps | A long-running flow fails part way through | 6 |
| Idempotency keys, event-time processing | Duplicate and late events pay twice or out of order | 7, 8 |
| Holds sized to label delay | Fraud is confirmed only after funds have moved | 9, 10 |
| Explicit payout timing policy | Two-sided platforms trade seller cash flow against platform risk | 1 |
| Counterfactual payout statements | Parties cannot see why money did or did not move | 12 |
| Experiments for learned parameters | Reserve or delay changes judged on anecdote | 11 |
Source: our design, with the works cited in the table.
5A worked split model
Table 2 shows how one marketplace order would pass through a split flow. Every input is hypothetical and chosen only to make the arithmetic visible.
| Item | Value | Type |
|---|---|---|
| Captured amount | 100.00 | Input |
| Platform fee rate | 10% | Input |
| Affiliate share rate | 5% | Input |
| Tax withholding rate on seller share | 2% | Input |
| Reserve fraction for this risk band | 20% | Input |
| Platform fee | 10.00 | Computed: 100.00 x 10% |
| Affiliate share | 5.00 | Computed: 100.00 x 5% |
| Seller gross share | 85.00 | Computed: 100.00 less fee and affiliate share |
| Tax withheld | 1.70 | Computed: 85.00 x 2% |
| Seller net | 83.30 | Computed: 85.00 less 1.70 |
| Released on delivery | 66.64 | Computed: 83.30 x (1 less 20%) |
| Held until return window closes | 16.66 | Computed: 83.30 x 20% |
Source: Worked model; inputs in the table.
The invariant that the parts sum to the captured amount holds: 10.00 + 5.00 + 1.70 + 66.64 + 16.66 = 100.00. If a return is opened before the window closes, the compensating path refunds the buyer from the held 16.66 first and records any shortfall as a recovery entry against the seller balance. The model shows the structure only; it says nothing about which reserve fraction is appropriate, which would have to be estimated from measured reversal rates.
6Evaluation a deployment would need
We make no outcome claim. To make one, a deployment would need to measure, against the existing static flows and per region:
- Time to funds for sellers and workers, as a distribution, not an average.
- Platform loss from reversals and fraud per unit of volume, with the label delay stated.
- Manual interventions per thousand flows and the share of payouts that needed one.
- Disputes and appeals about payout timing, and how many appeals were upheld.
- Verification coverage: the share of deployed flows checked against the full invariant set.
Changes to learned parameters would be pre-registered with these as target and guardrail metrics11. Differences in time to funds across seller cohorts would be reported, so that a reserve policy that falls hardest on small or new sellers is visible.
7Fairness and contestability
Conditional rules give whoever writes them power over when other parties are paid. Three safeguards follow from that. First, rules are published to the parties they affect, in the statement form above. Second, a hold has a stated end condition and a maximum duration, so it cannot become indefinite by omission. Third, learned risk bands are audited for systematic differences between cohorts that the rules do not justify. Behavioural and risk data used in conditions are limited to what a rule needs and kept in the region where they were collected.
8Limitations
- No measurements. We have not run this engine on real flows. Every benefit implied by the design is a hypothesis to be tested by the evaluation above.
- Verification covers the model, not the world. Model checking shows that the compiled state machine meets its properties5. It does not show that the properties are the right ones, or that external systems behave as the model assumes.
- Compensation is not reversal. Funds released to a bank cannot be recalled by the engine; a compensating entry creates a claim, which may not be recovered.
- Expressiveness. A narrow rule language will not express every contract. Flows that need more must be split or handled outside the engine.
- Legal variation. Licensing, safeguarding and withholding rules differ by country and change. The policy layer is only as current as the legal review behind it.
- Model risk. Risk inputs trained on delayed and imbalanced labels can be wrong in ways that delay honest parties10. The appeal path is a mitigation, not a fix.
- Parameters unset. Reserve fractions, hold durations and risk bands are left as parameters because setting them needs data we do not have.
9Conclusion
We have described a design in which conditional money flows are written as rules over commerce events, compiled to state machines, checked against invariants before they run, executed as sagas with idempotent steps, constrained by jurisdictional policy, and explained to every affected party. Each part rests on published work, summarised in Table 1. What the design lacks is evidence of its own effect. The next step is to run one flow, delivery-conditioned marketplace payouts, against the static schedule it would replace, and report what is measured.
References
- 1
Rochet, J.-C., & Tirole, J. (2003). Platform competition in two-sided markets. Journal of the European Economic Association, 1(4). doi.org/10.1162/154247603322493212
- 2
Committee on Payments and Market Infrastructures (2016). Fast payments: Enhancing the speed and availability of retail payments (CPMI Papers No. 154). Bank for International Settlements. www.bis.org/cpmi/publ/d154.htm
- 3
Szabo, N. (1997). Formalizing and securing relationships on public networks. First Monday, 2(9). doi.org/10.5210/fm.v2i9.548
- 4
Luu, L., Chu, D.-H., Olickel, H., Saxena, P., & Hobor, A. (2016). Making smart contracts smarter. Proceedings of the 2016 ACM SIGSAC Conference on Computer and Communications Security. doi.org/10.1145/2976749.2978309
- 5
Clarke, E. M., Emerson, E. A., & Sistla, A. P. (1986). Automatic verification of finite-state concurrent systems using temporal logic specifications. ACM Transactions on Programming Languages and Systems, 8(2). doi.org/10.1145/5397.5399
- 6
Garcia-Molina, H., & Salem, K. (1987). Sagas. Proceedings of the 1987 ACM SIGMOD International Conference on Management of Data. doi.org/10.1145/38713.38742
- 7
Helland, P. (2016). Life beyond distributed transactions. ACM Queue, 14(5). doi.org/10.1145/3012426.3025012
- 8
Kleppmann, M. (2017). Designing data-intensive applications: The big ideas behind reliable, scalable, and maintainable systems. O'Reilly Media. dataintensive.net/
- 9
Bolton, R. J., & Hand, D. J. (2002). Statistical fraud detection: A review. Statistical Science, 17(3). doi.org/10.1214/ss/1042727940
- 10
Dal Pozzolo, A., Boracchi, G., Caelen, O., Alippi, C., & Bontempi, G. (2018). Credit card fraud detection: A realistic modeling and a novel learning strategy. IEEE Transactions on Neural Networks and Learning Systems, 29(8). doi.org/10.1109/TNNLS.2017.2736643
- 11
Kohavi, R., Tang, D., & Xu, Y. (2020). Trustworthy online controlled experiments: A practical guide to A/B testing. Cambridge University Press. doi.org/10.1017/9781108653985
- 12
Wachter, S., Mittelstadt, B., & Russell, C. (2017). Counterfactual explanations without opening the black box: Automated decisions and the GDPR. arXiv:1711.00399 (Harvard Journal of Law & Technology, 2018). arxiv.org/abs/1711.00399
Cite this paper
Tanqory Research (2025). Programmable payments: conditional money flows as event-driven state machines. Tanqory. https://tanqory.com/research/programmable-payments-conditional-flows