>_ Analyst Engineering

State Machines for Payments: Every Status, Every Transition

Cover for a guide on state machines for payments, modeling every status and every transition.

A state machine models a payment’s lifecycle as defined states and the allowed transitions between them. It turns a vague description of statuses into an explicit, testable map, and it forces you to decide what the system must never do.

A state machine models an entity’s lifecycle as a set of defined states and the transitions between them, each triggered by an event, and for a payment it specifies exactly which statuses the payment can be in, how it legally moves between them, and which moves are forbidden. Instead of a prose description that says a payment is “received, then processed, then settled or rejected,” the state machine names every state, every allowed transition with its trigger, and every illegal transition that must be blocked. This makes the status behavior precise enough to build and testable enough to verify, which is why it is one of the most valuable tools a functional analyst has for anything with a non-trivial lifecycle.

Payments have exactly the kind of lifecycle that demands this rigor: many statuses, strict rules about valid transitions, and severe consequences when a transition that should be impossible is allowed, money moving when it should not, a final state undone. Modeling the payment as a state machine surfaces all of that explicitly. This is core functional analysis, and the states you uncover feed directly into the functional specification and the test design. The structured artifacts for it are in Real-World BA Deliverables.

What are the parts of a state machine?

A state machine has four parts: states, transitions, triggers, and the rules about which transitions are illegal. Get all four explicit and you have a complete lifecycle model; leave any vague and you have undefined behavior waiting to become a defect.

The states are the distinct conditions the entity can be in. For a payment, that might be received, accepted, settled, rejected, returned, and any intermediate states like pending or in-progress. The transitions are the allowed moves between states: received to accepted, accepted to settled, accepted to rejected. The triggers are the events or conditions that cause each transition: a validation success moves received to accepted, a downstream rejection moves accepted to rejected. And the illegal transitions are the moves the system must prevent: settled to rejected, rejected to accepted, settled to settled again.

Defining all four is the work. The states force you to enumerate every condition a payment can be in, which often surfaces states the prose description missed, the half-processed state, the stuck state, the partially-returned state. The transitions and triggers force you to specify exactly how and why the payment moves. And the illegal transitions force the question prose never asks: what must the system refuse to do. That last question is where state machines earn their keep, and it is the bridge to robust test design, because every illegal transition is a test you must run to confirm it is blocked.

How do you build a state transition table?

Build a state transition table by listing every current-state-and-event combination and recording the resulting next state, or that the transition is not allowed. The table is more rigorous than a diagram because it forces you to consider every combination, including the ones a diagram lets you skip.

The table has states down one axis and events across the other, and each cell answers: if the payment is in this state and this event occurs, what happens. Here is a fragment for a payment:

Current state \ Event   Validate OK   Downstream RJCT   Settle confirmed   Return received
Received                Accepted      Rejected          (illegal)          (illegal)
Accepted                (n/a)         Rejected          Settled            (illegal)
Settled                 (illegal)     (illegal)         (illegal)          Returned
Rejected                (illegal)     (illegal)         (illegal)          (illegal)

Filling every cell is the discipline. A state transition diagram lets you draw the arrows you think of and quietly omit the combinations you did not, which is exactly where undefined behavior hides. The table refuses that: every cell must say either a next state or “illegal” or “not applicable,” so you cannot leave a current-state-and-event combination undefined. When you find yourself unsure what a cell should be, you have found a real requirement gap, a behavior nobody has decided, and resolving it before build is the whole point. This completeness is why I reach for the table for anything important, and it complements the readability of a diagram, which is the sequence diagram sibling for showing flows over time.

Illegal transitions matter as much as legal ones because they define what the system must refuse to do, and in payments an allowed-but-illegal transition can corrupt integrity, mean money moving incorrectly, or undo a final state. Specifying only the valid transitions leaves the forbidden ones undefined, and undefined often means “accidentally permitted.”

Consider the consequences in payments. If the system allows a settled payment to transition to rejected, you have undone a completed settlement, a serious integrity violation with real financial meaning. If it allows a rejected payment to become accepted, you may process a payment that was correctly refused. If it allows a settled payment to settle again, you risk a double settlement. Each of these is a transition that must never happen, and the only way to guarantee that is to specify it as illegal and then test that the system blocks it. A state machine that lists only valid transitions implicitly assumes everything else is prevented, but that assumption is exactly what production defects exploit.

This is why illegal transitions are first-class citizens of the model, not an afterthought. They become explicit negative test cases: the QA analyst deliberately attempts each illegal transition and asserts the system refuses it, which is the state-transition testing described in negative test design. Defining the illegal transitions in the spec and testing them in QA is a tight loop that closes off an entire class of integrity defects. Skipping it is how a system ends up able to do something that should have been impossible, discovered only when a real payment does it.

How does the state machine connect to the rest of the spec?

The state machine is the backbone of the lifecycle, and the rest of the functional spec hangs off it: the transitions reference the triggers and reason codes, the states define what status the customer sees, and the illegal transitions become test cases. It is not a standalone artifact; it organizes the behavior.

Each transition connects to other parts of the spec. The trigger for an accepted-to-rejected transition is a specific failure with a specific reason code, which is the reason code mapping work. Each state corresponds to a status the customer can observe, which drives the requirements for what the channel displays, the difference between showing “accepted” and “settled” that prevents a customer assuming their money has arrived. The events that drive transitions are the same events that flow through the system, connecting the state machine to the payment message flows and the event-driven requirements. And every transition, legal and illegal, becomes an acceptance criterion.

This integrating role is why I model the state machine early when a payment’s lifecycle is non-trivial. It becomes the reference that keeps the rest of the spec coherent: if a new status is needed, it is a new state with defined transitions, not an ad hoc addition that breaks the model. The states and transitions you define here also have to be verified against the real system, because the database often has more states than the spec admits, the discovery you make by testing the system. A state machine grounded in observed behavior, integrated with the codes, the messages, and the tests, is one of the most powerful artifacts a functional analyst produces, and the broader skill set behind it is in The Technical Skills Guide for BAs.

The takeaway

A state machine models a payment’s lifecycle as defined states, allowed transitions with their triggers, and explicitly forbidden transitions. Building it, ideally as a state transition table that forces every combination to be decided, turns a vague status description into a precise, testable map and surfaces the undefined behavior that becomes defects. Illegal transitions matter as much as legal ones, because in payments an allowed-but-illegal move corrupts integrity, and each one becomes a negative test case.

Model the lifecycle explicitly, ground it in the real system, and connect it to the codes, messages, and tests, and the payment’s status behavior stops being a source of surprises. Start with Real-World BA Deliverables for the templates and The Technical Skills Guide for BAs for the depth, or browse everything at The Tech BA Toolkit.

Ahmed is a Senior Technical Business Analyst with 10+ years in banking and payments. He builds practical guides and tools for analysts at The Tech BA Toolkit.

Tags: Functional Analysis, Requirements, Payments, Software Design, Banking

Newsletter

Subscribe

Practical, no-fluff playbooks for technical analysts who analyze, code, test, and support. New articles straight to your inbox.

No spam. Unsubscribe anytime.