Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A software command can be correct in one situation and wrong in another. Shipping an order is valid after payment, but not before it; repeating a shipping request should not create a second shipment, and a canceled order must not ship. To design software that responds correctly, the system needs to represent the relevant history and use it to control which actions are allowed.

Why a command is not enough

Consider ship_order(order). The command names an operation, but it does not say whether the order is eligible for it. The answer depends on what has already happened: whether payment was captured, whether the order was canceled, and whether it has already shipped.

That is the central idea in Can Burak Sofyalioglu’s introductory explanation of state machines: an entity’s past can affect its valid future behavior. The order lifecycle below is a simplified teaching example, not a claim that every commerce system uses exactly these states or rules.

What state means in this example

Ordinary data describes an entity; behavioral state changes how the entity may respond. An address is usually descriptive data, but changing it may become restricted once a carrier has the package. Whether a field is ordinary data or behaviorally important therefore depends on the rules around it.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

History is the sequence of events that brought the entity to its present situation. State is a useful summary of the consequence of relevant events. A paid label may be enough to determine whether an order is eligible for shipping, but it is not enough to issue a refund: that operation may require payment details.

  • Lifecycle state: helps determine which operations are currently eligible.
  • Supporting data: supplies information needed to perform an operation, such as payment details for a refund.
  • History: records the events that produced the current situation.

As Sofyalioglu puts it, “The state summarizes a relevant consequence of the past. It does not preserve everything that happened.”

The simplified order lifecycle

The example has three states and two forward transitions:

CREATED → PAID → SHIPPED

State What the system knows Eligible next operation Payment data
created The order exists, but payment has not yet moved it to the paid stage. Capture payment; shipping is not eligible. Capture needs payment information. The example does not specify a particular schema.
paid Payment capture has moved the order out of the created stage. Ship the order. Payment details remain relevant for operations such as refunds; the state label alone is insufficient.
shipped The order has moved from paid to shipped. No further forward transition is specified in this simplified example; a repeat shipping request should not create a duplicate shipment. The example does not specify additional payment data for this stage.

The example assumes at most one full-amount payment per order and a single currency. Those assumptions keep the lifecycle easy to follow; more complex payment arrangements require additional modeling.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why a status field does not guarantee correctness

A field named status can record a stage, but by itself it does not make transitions safe. If the field accepts unrestricted strings, it can contain an unknown value. Even a recognized value can be written at the wrong time or alongside inconsistent payment details.

As Sofyalioglu writes, “The status field records the order’s current stage. It does not enforce the rules for reaching that stage.” The application needs to constrain the operations that change state: payment capture moves created to paid, and shipping moves paid to shipped. Requests that do not match the current state need an explicit safe outcome rather than an unconditional update.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Local state and external events can disagree

A stored paid value is not proof that a payment provider captured money. For example, the provider could report success while the application’s local update fails, leaving the provider and the order record out of sync. State describes what the application records; it does not, by itself, establish external reality.

The article is a conceptual introduction with code illustrations. It does not demonstrate production payment integration, automated tests, or guarantees for coordinating external processing with local records. A real system must address those concerns rather than treating a status update as proof that every related operation succeeded.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read the original Part I

Can Burak Sofyalioglu’s “Road to State Machines Part I” was published on DEV Community on September 23, 2026, and edited October 1, 2026. It develops the order example to explain why software behavior depends on state and on the transitions that produced it.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.