Skip to content
Historical revision
State2026-07-24 15:14 UTC
rev_1146c9f571c84898bdf8cd6597648916

State

What is state in programming? A system is described as stateful, meaning it retains state, when it is designed to remember previous events or user interactions. The information it remembers is called the system's state. How did state become a technical term through calculators, control engineering, logic circuits, and automaton theory, and how did it later extend to variables and objects in programming languages, and to sessions and UI models in web applications?

What is state?

In general English, state means the way something exists or its condition, that is, a "mode or condition of being." Merriam-Webster's definition of state also lists this as its primary meaning. This is the sense at work when we say water is in a liquid or gaseous state, or that a door is in an open or closed state.

In computing, state can be defined more narrowly as follows.

The state of a system is the set of information the system holds at a given point in time that can change the system's behavior and outcomes in response to subsequent inputs or events.

Here is an example. In the following C code, failedAttempts is the state of the login function. After initializing with LoginState state = {0};, calling recordLoginFailure repeatedly produces different results depending on the prior number of failures. Whether the account is locked can be computed from failedAttempts >= maxLoginFailures, so it does not need to be stored separately.

C
#include <stdbool.h>
#include <stddef.h>

enum {
    maxLoginFailures = 5,
};

typedef struct {
    unsigned int failedAttempts;
} LoginState;

LoginState state = {0};

bool recordLoginFailure(LoginState *state) {
    if ((state == NULL) ||
        (state->failedAttempts >= maxLoginFailures)) {
        return false;
    }

    state->failedAttempts++;
    return state->failedAttempts < maxLoginFailures;
}

The first four failures return true, but after the fifth failure the account is locked and false is returned. Subsequent calls also return false without incrementing the failure count further. What makes this difference? Not just the input of the current call, but the state left behind by previous failures.

An elevator's current floor, direction of travel, and whether its door is open all change how it responds to the next button press. Whether a user is logged in, their permissions, their shopping cart, and whether payment has been approved all determine whether the next request is allowed. This kind of information is state.

State is not synonymous with a single variable; a single logical state can be spread across multiple variables, tables, or messages, and conversely, not all stored data is state. The same value can be a mere input or record, or it can be state that determines future behavior, depending on the system boundary and how it is used. The "state" this post refers to is not a storage location for a value, but the role of information that changes over time and influences future behavior.

The reason we use this term is to describe situations where the same current input leads a system to behave differently depending on what happened in the past. State is often a summary that the system preserves in the present so it does not have to re-read that past every time. However, information that cannot be viewed purely as a trace of past events, such as the current time, external environment, configuration, or sensor readings, can also qualify as state depending on the system boundary.

Therefore, the question "when was the word 'state' first used?" requires tracing how it was used, in what context, and when.

  • State of a machine: what must be remembered right now in order to continue a computation?

  • State in a state machine: a finite internal mode that determines the next action based on input

  • State of a program: information stored in variables, memory, and the environment that affects the results of subsequent execution

  • State in semantics: an abstract snapshot of a store used to compare a program's conditions before and after execution

  • Application state: current information distributed across users, sessions, databases, and browsers

To summarize the conclusion of this document in advance:

State is the current information needed to determine future behavior within a given system boundary, and it can often be viewed as a compressed summary of the effects left by past inputs and events.

Why was state necessary?

Consider a device that simply looks at the current input and produces an output.

Loading animated diagram...
Text
Output = f(Current Input)

Such a device is called combinational logic. Like an adder or logic gate, it computes results from the current input alone, but calculators, telephone exchanges, elevators, and communication protocols cannot determine their behavior from the current input alone.

  • What number was entered previously?

  • Has a coin already been inserted?

  • Is the system waiting for a call to connect?

  • How many fragments of a packet have been received so far?

  • Has a file been opened and not yet closed?

To avoid re-reading every past event, only the information needed going forward must be retained at the current position. That, precisely, is state.

Loading animated diagram...

Text
Next State = δ(Current State, Input)
Output = λ(Current State, Input)

State is a mechanism for representing the passage of time, and it is often used as information that compresses the past. If the summary needed for future behavior can be expressed as one of a finite number of equivalent states, the system can be modeled as a finite state machine. Conversely, if the system requires information whose possible values keep growing, such as detailed past history or an accumulating integer count, the state space can become infinite. Having a compact representation and having a finite number of possible states are not the same thing. There are also designs, such as Event Sourcing, that preserve the entire history of past events.

A personal note: in programming, "occupying state" is not simply the act of writing a value to a specific memory address. It is "the process of irreversibly reducing the degrees of freedom in the State Space that the system can reach in the future."

As computer science continues to advance, I find it unfortunate that these fundamental, original meanings are gradually fading away.

1936: Turing's state of mind and the Machine's Configuration

Alan Turing's 1936 paper On Computable Numbers, with an Application to the Entscheidungsproblem, published in 1937, is the starting point that defined what we now call the "Turing machine."1

Turing explained that the actions of a person performing a computation are determined by the symbol currently being observed and the current state of mind, but he later transposed this structure onto the machine's m-configuration. The m-configuration is closer to the machine's internal control state. The complete computational situation (configuration) at any given moment encompasses not only that internal state but also the contents of the tape and the position of the read/write head. (The tape here is not the magnetic tape once used as a storage device, but rather an abstract workspace that simplifies the process of a person computing on paper. The author understands it to mean a linearly arranged space that can expand infinitely.)

So what is the distinction worth drawing here?

  • Turing was not the first to formally declare the term state machine as it appears in today's textbooks.

  • He did, however, clearly articulate a computational model in which "the action at each step is determined by the current input and the internal state."

  • The idea of distinguishing between the state in a State Machine and the full execution snapshot (configuration) also traces back to this lineage.

Some who speak of Turing's contribution to the concept of state say that it lies not so much in inventing the name "state" as in constructing the framework that computational behavior can be described in terms of current internal conditions and transition rules.

1938: Switching Circuits Expressed as Logical Formulas

In his 1938 paper A Symbolic Analysis of Relay and Switching Circuits, Claude Shannon analyzed the behavior of relay and switching circuits using Boolean algebra.2

The paper demonstrated how to analyze and synthesize relay and switching circuits using Boolean algebra. It is therefore an important precursor to Combinational Logic and digital circuit design, but it should not be read as a paper that directly formalizes the state of today's sequential machines: the state and transition model for Sequential Circuits was worked out later, through subsequent research on automata and through the contributions of Huffman, Mealy, Moore, and others.

Building a sequential system requires distinguishing between the following two layers.

Loading animated diagram...
Text
Combinational Logic: computes the current input
Memory Elements: preserve the results of previous computations

State is an abstraction of the information stored in memory elements that determines future behavior. Flip-flops, relays, registers, and memory cells physically encode and preserve that state, while in software, variables, the heap, files, databases, and session stores play that role.

Mid-1950s: The Sequential Machine Model Takes Shape Through Huffman, Mealy, and Moore

The expression "State Machine" and the model it describes became widely established in the mid-1950s. That said, research on automata and sequential circuits had existed before then, and it is more accurate to view Huffman, Mealy, and Moore not as inventors of the State Machine but as the figures who codified the sequential circuit and output models into a standard form and brought them into wide circulation.

1954: Huffman's Synthesis of Sequential Switching Circuits

In The Synthesis of Sequential Switching Circuits (1954), David A. Huffman presented a procedure for reducing the requirements of sequential circuits with memory to the requirements of combinational circuits. In doing so, he introduced the flow table as a precise description of sequential circuits and addressed methods for identifying and minimizing redundant requirements.3

Huffman's work served as the connecting link between abstract state tables and actual switching circuits. It is therefore a significant step in the lineage just before Mealy and Moore, systematically addressing state assignment, state reduction, and circuit synthesis.

1955: Mealy's Sequential Circuit Model

George H. Mealy published A Method for Synthesizing Sequential Circuits in 1955. The paper introduces a model for sequential circuits along with state diagrams, and rules for state reduction and state transitions.4

In the Mealy Machine, the output is determined by both the current state and the current input.

Loading animated diagram...

Text
Next State = δ(Current State, Input)
Output = λ(Current State, Input)

1956: Moore's Finite Sequential Machine

In Gedanken-Experiments on Sequential Machines, published in Automata Studies, Edward F. Moore treats sequential machines with a finite number of states, input symbols, and output symbols. In the Moore Machine, the next state is likewise determined by the current state and the current input, but the output is determined by the current state alone.5

Execution layers
Loading animated diagram...
Text
Next State = δ(Current State, Input)
Output = λ(Current State)

(The key difference between the Mealy Machine and the Moore Machine is this: the state transition mechanism is identical, and only the output function differs. At first glance, they can easily be mistaken for the same thing.)

Mealy and Moore represent two standard sequential machine models that differ in the dependency of their output functions. The Mealy Machine's output depends on both the current state and the input, while the Moore Machine's output depends on the current state alone. With appropriate state partitioning and output timing conventions, the two models can be converted into each other, though the initial output or the temporal alignment of output sequences does not always match exactly. Through this period, state acquired a meaning beyond a simple "current condition": it came to denote the internal position of a mathematical machine equipped with inputs and transition rules.

That said, it would be incorrect to assert that "Mealy was the first to use the term state machine" or that "Moore invented state." The related concepts were continuous with earlier work in logic circuits and automata theory, and the right view is that the papers by Mealy and Moore are important documents that organized those concepts into standard models and brought them into wide circulation.

Personal note: I have seen references suggesting that earlier mentions exist, but I was unable to locate them. This is something I should look into again at some point.

Late 1950s to Early 1960s: State Expressed Through Variables and Assignment Statements in High-Level Languages

If state in hardware was embodied in memory circuits, then in high-level programming languages, variables and assignment statements became the fundamental tools for expressing state. ALGOL 60 is a clear example of this trend made explicit in a language specification.

The ALGOL 60 report describes a variable as a designation referring to a single value, and specifies that this value may be changed by an assignment statement. An own variable is defined as a variable that retains its previous value when a block is re-entered.6

ALGOL
x := x + 1

This statement does not simply compute a value; rather, the state after execution differs depending on whether the store state before execution has x = 3 or x = 4.

Text
σ = { x ↦ 3 }
x := x + 1
σ' = { x ↦ 4 }

Here, σ and σ' are not the original notation from the ALGOL report but rather modern program semantics notation for store state, used here for explanatory purposes. A program is not merely something that takes input and produces output; it is a process that transforms the store from one state to another.

Lisp pointed in a different direction.

John McCarthy's 1960 Lisp paper foregrounded function application and recursive symbolic computation as the central mode of expression.7

This trajectory left future generations with the question: "Must all computation be expressed as a sequence of instructions and assignments?"

However, early Lisp itself was not a purely functional language. The LISP 1.5 Programmer's Manual introduces imperative elements such as PROG, variables, storage, SET, and SETQ.8 The significant shift was not a rejection of state, but rather a separation of two distinct styles of computation into distinct conceptual categories.

Text
Imperative computation: directly mutates Store State
Functional computation: composes values and functions, keeping State changes at the boundary

The subsequent functional programming tradition developed not by eliminating the physical state of computers, but by exposing or constraining state changes through explicit arguments, return values, and boundaries such as effect types and monads. The actor model is less a subcategory of functional programming and more a concurrency model that isolates mutable state within individual actors and allows influence to flow only through message passing. External storage likewise makes the owner and lifetime of state explicit at the boundaries of the system.

1960: State-Space Representation in Control Engineering

Control engineering also developed state-space representations that compute the next state and output from a system's current state and input. Rudolf E. Kalman's 1960 paper applied state-transition methods to the analysis of dynamic systems, addressing problems of filtering and prediction.9

A discrete-time linear state-space model is typically written as follows.

Text
xₜ₊₁ = Aₜxₜ + Bₜuₜ
yₜ   = Cₜxₜ

Here, x is the state vector, u is the external input, and y is the observation or output. This notation is an example of how the perspective that "current state and input determine future behavior" was formalized in the language of control engineering.

Late 1960s to 1970s: State as the Subject of Program Semantics

After variables and assignment statements had established themselves as concrete language features, a question emerged: how could one mathematically describe and prove the fact that a program changes the store state as it executes?

Robert Floyd's 1967 Assigning Meanings to Programs attached propositions to control-flow points in a program and explained how conditions on variable values are maintained throughout execution.10

C. A. R. Hoare's 1969 An Axiomatic Basis for Computer Programming systematized axioms and inference rules for assignment statements, conditionals, and loops.11

At this point, state becomes not merely the current contents of memory, but the subject against which program correctness is asserted.

Text
{ P } C { Q }

P: Condition that must be satisfied before execution (Precondition)
C: Command that changes the state
Q: Condition that must be satisfied after execution (Postcondition)

From this perspective, a deterministic, sequential imperative program can be viewed as the following partial state transformation:

Text
Program C: State Σ ⇀ State Σ

Here, denotes a partial function.

For certain input states, the program may not terminate and thus produce no resulting state. To express this explicitly, can be added to denote non-termination or undefinedness, writing C : Σ → Σ⊥.

To distinguish exceptions or failure types, an error space E must be included separately, as in C : Σ → (Σ + E)⊥. Incorporating I/O and concurrency makes this even more complex, but the model that "programs transform state" became the foundational framework for describing imperative languages.

At the same time, Scott and Strachey's 1971 Toward a Mathematical Semantics for Computer Languages sought to treat the meaning of programs as mathematical objects independent of any specific machine implementation12; state was now no longer confined to hardware registers, but had become an abstract space in which the meaning of a language itself is defined.

1960s–1980s: Concurrency and Distributed Environments Turn State into a Shared Problem

In a single thread of execution, x := x + 1 can be explained as the relationship between the current store and the next store. When multiple threads read and write the same mutable value, however, the result varies depending on the order in which each operation interleaves. State now becomes a question not only of the value itself, but of who can read and write it, and when.

Dijkstra addressed the problem of concurrent programming control in 1965, and in his 1968 Cooperating Sequential Processes systematically described cooperating processes and semaphore operations.13 Semaphores, mutual exclusion, and critical sections are mechanisms that unconditionally prevent uncontrolled access to shared mutable state. Rather than automatically dismantling race conditions, they force the programmer to explicitly design the ordering of state access and the invariants that must hold.

When processes are separated by a network, each node observes local state at a different point in time. Lamport's 1978 paper shows that the happened-before relation forms a partial order based on causality, and that a logical clock can construct an event ordering consistent with that causality.14

Text
a happened-before b  ⇒  C(a) < C(b)
C(a) < C(b)          ⇏  a happened-before b

What this reasoning reveals is that scalar logical clocks cannot fully determine causal relationships. Concurrent events may share the same timestamp or carry different timestamps. To assign a total order to all events, one can combine logical timestamps with an arbitrary tiebreaking rule such as process ID, but the ordering between concurrent events in the resulting sequence reflects a choice made by the system, not a causal fact. This means that in a general asynchronous distributed system, one cannot assume that all nodes instantly share the same global present or the absolute ordering of events. Distributed state is not a single memory snapshot; it is the set of relationships among the states each node maintains and reconciles under message passing, ordering rules, and replication and consensus protocols. (This is the theoretical background behind why distributed programming is notoriously difficult.)

Database transactions addressed this problem by treating it as a matter of boundaries on state transitions. Gray's 1981 work describes transactions as state transformations and identifies atomicity, consistency, and durability as their core properties.15 The widely adopted acronym ACID also includes isolation, and this term was formalized in Härder and Reuter's 1983 paper.16 In short, providing state transitions that satisfy defined integrity constraints and isolation levels under failure and concurrent access requires separate contracts: concurrency control mechanisms such as locking or MVCC, commit/abort boundaries, logging and recovery, and, when multiple participants are involved, atomic commit protocols.

In this lineage, state is no longer simply a value recorded in memory; it has become a system resource that must be defined together with its owner, transition ordering, observability, and recovery after failure. In subsequent designs dealing with distributed state, options such as Event Sourcing and Eventual Consistency came into wide use. Each of these solutions is not a complete answer to the whole problem, but rather a different design choice addressing event recording and replica convergence.

Object-Oriented Programming Bound State and Operations Under a Single Owner

One strand of object-oriented programming evolved not by eliminating state, but by moving in the direction of bundling state together with the ownership of the operations that manipulate it.

Text
Procedural Style
  External function → modifies external data

Object Style
  Object → preserves its own state and modifies it according to messages

From this perspective, an object that holds state is not merely a data structure; it preserves its current state and transitions to the next state in response to permitted messages. Immutable objects and value objects are not counterexamples to this description but rather a different design that expresses state changes externally as the creation of new values. Encapsulation in object-oriented programming is therefore also a design discipline that hides the representation of state and restricts the channels through which state can be modified.

Of course, object-oriented programming is only one of several designs that place state within the boundaries of modules or objects.

Loading animated diagram...

The web is Stateless, yet it has not eliminated state.

HTTP is officially a stateless protocol. RFC 9110 states that the semantics of each request must be understood independently, without depending on the context of other requests or connections.17

This is commonly taken to mean that web servers cannot hold state, but it simply means that the protocol imposes no rule requiring a server to remember previous requests in order to understand the meaning of the current one.

In practice, web applications therefore place state elsewhere, and the locations where state is typically stored are as follows.

  • Cookies and session storage

  • Databases and caches

  • Access tokens and refresh tokens

  • The browser's DOM, History API, and local storage

  • Server memory and distributed caches

In other words, the web's "statelessness" is not the absence of state but a design choice to separate the location and responsibility of state. Statelessness can simplify connection reuse and load balancing, but whether retries are safe depends on a separate idempotency contract. User sessions and workflows still require their own policies for storage, identification, and expiration.

Modern state management is a problem of partitioning state

What is called "state management" in today's frontend work is likely not as simple as storing a single variable. It is the work of separating and synchronizing pieces of state that have different lifetimes and different owners.

Text
Component State → Values needed only within a single screen
Page State → Values tied to routes and History
Server State → Values owned by a remote API
Session State → Values tied to login, permissions, and expiration
Persistent State → Values that remain in a DB, file, or local storage
Cache State → Values derived from the source but reproducible on demand

Putting all of them into a single global object erases the ownership and lifetime of each piece of state. Conversely, splitting state too finely scatters transitions and synchronization across the codebase. Modern solutions such as Redux, MVVM, reactive systems, Event Sourcing, and State Machine libraries each address the same problem in different ways.

How should state be managed

When reading code that has state, variable names matter of course, but the following questions are what truly count.

  1. Who owns it? Which holds the source of truth: an object, a request, a process, a server, or a database?

  2. How long does it live? Is its lifetime scoped to a single function, a single request, a session, a process, or persistent storage?

  3. What triggers transitions? Is it a command, an event, time, an external response, or another thread?

  4. Which states are valid? Are all combinations of values permitted, or are there transition rules like Paid → Shipped?

State bugs are usually not a matter of one value being wrong; they arise when these four contracts get mixed up. The State pattern collects transitions into objects, typestate encodes transition rules into the type system, and database transactions group the boundaries of multiple state changes together — each of these points matters.

State and data play different roles

Some courses claim that state and data are the same thing, but state and data are not so much fundamentally different kinds of things as they are values that play different roles within a system. When a value is used only as input, configuration, or a record, it is closer to data; when subsequent behavior and outcomes depend on the current value, it functions as state.

Text
Immutable input data
  Same input → same raw material for computation

State
  Current value → alters subsequent behavior and results

For example, the value username = Hong Gildong might be simple input data in one system. Yet if the UI uses it to display the currently logged-in user, or if authorization checks and cache-key decisions depend on it, then that same value functions as part of the state within that system's boundary.

Conversely, an immutable configuration file or a historical log is closer to input or record data rather than state, as long as it does not directly determine future transitions in the system. Login status, permissions, the shopping cart, and payment approval status all affect which future requests are permitted, so they become application state.

A status field is also not the same as the full state. The label Paid may be part of observable state, but for a real system to operate safely, it may also need the payment authorization ID, the amount, a version number, an expiration time, and a retry flag. Whenever you compress state into a single-word enum, check what is being hidden.

Tracing state back to its origins: the questions of each era

Question

Historical answer

The origin of state as a general term

It predates programming and has no single inventor

When the current internal condition of a computation model was described

Turing's 1936 state of mind and m-configuration are an important starting point

When the Mealy and Moore State Machine models of Sequential Circuits became established as standard forms

The mid-1950s

When mutable state in programs became commonplace

Alongside variables and assignment statements in high-level languages of the 1950s

When program state was formally verified

Around Floyd 1967, Hoare 1969, and Scott–Strachey 1971

When the ordering and consistency of state in concurrent and distributed environments became a central problem

From the 1960s onward as multiprogramming spread, with Lamport 1978 and database transaction research serving as important milestones

When application state management grew into a distinct design problem

It grew gradually from the 1960s onward alongside advances in databases, interactive systems, GUIs, and distributed systems, becoming especially prominent in the web and frontend space from the 1990s onward

Question

The origin of state as a general term

Historical answer

It predates programming and has no single inventor

Question

When the current internal condition of a computation model was described

Historical answer

Turing's 1936 state of mind and m-configuration are an important starting point

Question

When the Mealy and Moore State Machine models of Sequential Circuits became established as standard forms

Historical answer

The mid-1950s

Question

When mutable state in programs became commonplace

Historical answer

Alongside variables and assignment statements in high-level languages of the 1950s

Question

When program state was formally verified

Historical answer

Around Floyd 1967, Hoare 1969, and Scott–Strachey 1971

Question

When the ordering and consistency of state in concurrent and distributed environments became a central problem

Historical answer

From the 1960s onward as multiprogramming spread, with Lamport 1978 and database transaction research serving as important milestones

Question

When application state management grew into a distinct design problem

Historical answer

It grew gradually from the 1960s onward alongside advances in databases, interactive systems, GUIs, and distributed systems, becoming especially prominent in the web and frontend space from the 1990s onward

The concept of state in computation and control took shape in physical systems and computation models that required memory, evolved through the internal conditions of Sequential Circuits and the storage and semantics of programs, and has expanded today into a temporal contract shared across multiple systems.

Footnotes

  1. Alan M. Turing, "On Computable Numbers, with an Application to the Entscheidungsproblem," Proceedings of the London Mathematical Society, 1937, 2nd series, 42(1), 230–265. (Volume 42 is cited as 1936–1937 in some bibliographic records.) DOI · Oxford Academic
  2. Claude E. Shannon, "A Symbolic Analysis of Relay and Switching Circuits," Transactions of the American Institute of Electrical Engineers, 1938. IEEE bibliographic record
  3. https://doi.org/10.1016/0016-0032(54)90574-8
  4. George H. Mealy, "A Method for Synthesizing Sequential Circuits," Bell System Technical Journal, 1955. DOI
  5. Edward F. Moore, "Gedanken-Experiments on Sequential Machines," in Automata Studies, 1956. Chapter PDF
  6. Peter Naur, ed., "Revised Report on the Algorithmic Language ALGOL 60," Communications of the ACM 6(1), 1963. Computer History Museum archive
  7. John McCarthy, "Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I," Communications of the ACM, 1960. Stanford archive
  8. John McCarthy et al., LISP 1.5 Programmer's Manual, MIT Press, 1962. Bibliographic record
  9. https://doi.org/10.1115/1.3662552
  10. Robert W. Floyd, "Assigning Meanings to Programs," 1967. Paper PDF
  11. C. A. R. Hoare, "An Axiomatic Basis for Computer Programming," Communications of the ACM, 1969. ACM
  12. Dana Scott and Christopher Strachey, "Toward a Mathematical Semantics for Computer Languages," Oxford Programming Research Group, 1971. Oxford archive
  13. Edsger W. Dijkstra, "Solution of a Problem in Concurrent Programming Control," Communications of the ACM 8(9), 1965; "Cooperating Sequential Processes," 1968. 1965 DOI · 1968 manuscript
  14. Leslie Lamport, "Time, Clocks, and the Ordering of Events in a Distributed System," Communications of the ACM 21(7), 1978, 558–565. Microsoft Research
  15. Jim Gray, "The Transaction Concept: Virtues and Limitations," Tandem Technical Report 81.3, 1981. PDF
  16. Theo Härder and Andreas Reuter, "Principles of Transaction-Oriented Database Recovery," ACM Computing Surveys 15(4), 1983, 287–317. DOI · IBM Research
  17. IETF, RFC 9110: HTTP Semantics, 2022. RFC Editor
Revision history — State