Skip to main content
TLA+ is a formal specification language for describing systems, particularly concurrent and distributed ones. Created by Leslie Lamport, it’s built on simple mathematics: set theory and temporal logic. This foundation gives TLA+ remarkable expressive power while keeping the core language small. This guide teaches TLA+ from scratch. You don’t need a math background, but it’ll help as things become more complex. I’ll explain concepts as we go. By the end, you’ll be able to read and write TLA+ specifications.
Reading vs Writing TLA+: Reading specifications is easier than writing them. As you learn, focus first on understanding existing specs before trying to write your own. The examples throughout this guide are meant to be read carefully.
If you want to run specifications, grab MacTLA (native macOS, I wrote it) or the TLA+ Toolbox (cross-platform). For domain-specific examples, see the AD Tier Model specification or aviation systems models.

Set Theory Foundations

TLA+ is fundamentally based on set theory. Understanding sets is essential, they appear everywhere in specifications.

Basic Set Notation

Sets are collections of distinct elements:
Membership is tested with \in (in) and \notin (not in):

Set Operations

Set Constructors

Build sets from conditions or transformations:

Special Set Operations

The range notation a..b creates {a, a+1, ..., b}.

Basic Operators and Expressions

Logical Operators

Precedence (highest to lowest): ~, then /\ and \/ (same level), then <=>, then =>. Use parentheses when in doubt.

Comparison Operators

Arithmetic Operators

Requires EXTENDS Integers or EXTENDS Naturals:

Conditional Expressions

CASE expressions for multiple conditions:

Local Definitions

LET-IN creates local bindings:

Quantifiers

Quantifiers make statements about sets of values.

Universal Quantification

\A means “for all”:

Existential Quantification

\E means “there exists”:

The CHOOSE Operator

CHOOSE picks an arbitrary element satisfying a condition:
CHOOSE always returns the same value for identical inputs within a model run—it’s deterministic in that sense. However, the specification doesn’t define which qualifying value it picks. Your specification shouldn’t depend on a particular choice.

Bounded vs Unbounded

Always use bounded quantifiers (\A x \in S) rather than unbounded (\A x). Unbounded quantifiers can’t be model-checked and should only appear in proofs.

Functions and Records

Functions in TLA+ map elements from a domain to values.

Function Definition

Function Application

DOMAIN

Updating Functions with EXCEPT

EXCEPT creates a new function with some values changed:
Multiple updates:

Records

Records are functions with string domains:

Sequences

Sequences are functions with domain 1..n. Requires EXTENDS Sequences:

MODULE Structure

TLA+ specifications are organized into modules.

Comments

EXTENDS

Standard modules provide common operations:

Defining Operators

Operators are like functions or macros—they name expressions for reuse.

Simple Definitions

Recursive Operators

Higher-Order Operators

Operators can take other operators as arguments:

State and Actions

A state is a snapshot of your system at a moment in time, specifically, the values assigned to all variables. A behavior is a sequence of states, showing how your system evolves over time. TLA+ models systems by describing valid initial states and valid transitions between states.

Prime Notation

The prime symbol (') refers to the value in the next state:
An action is a formula containing primed and unprimed variables. It describes how state changes.

A Simple Example: Counter

Init defines the initial state. Increment and Decrement are actions, each describes a valid state transition.

UNCHANGED

When an action doesn’t modify a variable, say so explicitly:

Enabling Conditions

Actions often have preconditions (guards):
The action is only enabled when counter > 0.

The vars Tuple Pattern

Group all variables into a tuple for convenience:
This simplifies temporal formulas (explained below).

Init and Next

The standard pattern for behavioral specifications:
Next is a disjunction of all possible actions. The system can take any enabled action at each step.

Bank Transfer Example

Temporal Operators

TLA+ can express properties about behavior over time.

Always (Box)

[]P means P holds in every state of every behavior:

Eventually (Diamond)

<>P means P holds in some future state:

Combining Temporal Operators

Leads-To

P ~> Q means whenever P holds, Q eventually follows:

Stuttering and the Spec Formula

A stuttering step is one where nothing changes. Real systems can stutter (e.g., waiting for I/O). The notation [Next]_vars means “either Next happens, or nothing changes”:
The standard specification form:
This says: start in an Init state, then repeatedly take Next steps (or stutter).

Safety vs Liveness

Safety properties say “bad things never happen”:
  • [](balance >= 0) — balance never goes negative
  • []MutualExclusion — two processes never in critical section
Liveness properties say “good things eventually happen”:
  • <>Terminated — system eventually terminates
  • Request ~> Response — requests get responses
Safety can be checked directly. Liveness requires fairness assumptions—telling the model checker that enabled actions eventually execute.

Type Correctness and Invariants

The TypeOK Pattern

Define valid states with a type invariant:
The notation [S -> T] means “the set of all functions from S to T.” So balance \in [{"alice", "bob"} -> Nat] says balance is a function mapping account names to natural numbers. TypeOK should be an invariant: []TypeOK.

Writing Invariants

Invariants are safety properties, conditions that must always hold:

Complete Specification: Mutex

Here’s a complete, runnable specification for mutual exclusion:
To run this, create a configuration file (Mutex.cfg):

Standard Modules Reference

Running Specifications

Configuration Files

A .cfg file tells TLC what to check:

Using MacTLA or TLA+ Toolbox

  1. Write your .tla specification
  2. Create a .cfg configuration
  3. Run TLC (the model checker)
  4. If an invariant fails, TLC shows the counterexample trace
See MacTLA for native macOS verification or the TLA+ Toolbox for cross-platform.

Common Patterns and Idioms

The vars Tuple

Always define a vars tuple grouping all variables:

Guard-Action Pattern

Structure actions as guard (enabling condition) + effect:

Helper Operators

Extract common logic into named operators:

Sets vs Sequences

  • Use sets when order doesn’t matter and duplicates aren’t allowed
  • Use sequences when order matters or you need duplicates
Domain-specific examples: Tools:
  • MacTLA — native macOS verification with TLC and TLAPS, I wrote it
External resources: