Skip to content
Back to skills

2565 Distributed Patterns E5145e30

ASecurity

Common patterns for specifying distributed systems in TLA+.

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added May 31, 2026
businessgo

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 2565-distributed_patterns_e5145e30 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2565 Distributed Patterns E5145e30?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2565 Distributed Patterns E5145e30
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2565-distributed-patterns-e5145e30/badge)](https://www.skillsdirectory.com/skills/tools-only-2565-distributed-patterns-e5145e30)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# Distributed Systems Patterns in TLA+

Common patterns for specifying distributed systems in TLA+.

## Pattern 1: Message Passing

### Basic Message Passing

```tla
CONSTANTS Procs, Messages

VARIABLES
  network,    \* Messages in transit
  state       \* Process states

TypeOK ==
  /\ network \in SUBSET Messages
  /\ state \in [Procs -> States]

Init ==
  /\ network = {}
  /\ state = [p \in Procs |-> "Init"]

Send(p, msg) ==
  /\ network' = network \cup {msg}
  /\ UNCHANGED state

Receive(p, msg) ==
  /\ msg \in network
  /\ network' = network \ {msg}
  /\ state' = [state EXCEPT ![p] = ProcessMessage(msg)]
```

### Reliable FIFO Channels

```tla
VARIABLES channels  \* channels[p][q] is queue from p to q

TypeOK == channels \in [Procs -> [Procs -> Seq(Messages)]]

Init == channels = [p \in Procs |-> [q \in Procs |-> <<>>]]

Send(p, q, msg) ==
  /\ channels' = [channels EXCEPT ![p][q] = Append(@, msg)]

Receive(p, q) ==
  /\ channels[q][p] /= <<>>
  /\ LET msg == Head(channels[q][p])
     IN /\ channels' = [channels EXCEPT ![q][p] = Tail(@)]
        /\ ProcessMessage(p, msg)
```

## Pattern 2: Consensus Protocols

### Two-Phase Commit

```tla
CONSTANTS
  RM,           \* Resource managers
  Coordinator

VARIABLES
  rmState,      \* State of each RM: "working", "prepared", "committed", "aborted"
  tmState,      \* State of coordinator: "init", "preparing", "committed", "aborted"
  tmPrepared,   \* Set of RMs that have prepared
  msgs          \* Messages in transit

TypeOK ==
  /\ rmState \in [RM -> {"working", "prepared", "committed", "aborted"}]
  /\ tmState \in {"init", "preparing", "committed", "aborted"}
  /\ tmPrepared \subseteq RM
  /\ msgs \subseteq Messages

Init ==
  /\ rmState = [r \in RM |-> "working"]
  /\ tmState = "init"
  /\ tmPrepared = {}
  /\ msgs = {}

TMPrepare ==
  /\ tmState = "init"
  /\ tmState' = "preparing"
  /\ msgs' = msgs \cup {[type |-> "Prepare", dest |-> r] : r \in RM}
  /\ UNCHANGED <<rmState, tmPrepared>>

RMPrepare(r) ==
  /\ rmState[r] = "working"
  /\ [type |-> "Prepare", dest |-> r] \in msgs
  /\ rmState' = [rmState EXCEPT ![r] = "prepared"]
  /\ msgs' = msgs \cup {[type |-> "Prepared", src |-> r]}
  /\ UNCHANGED <<tmState, tmPrepared>>

TMCommit ==
  /\ tmState = "preparing"
  /\ tmPrepared = RM
  /\ tmState' = "committed"
  /\ msgs' = msgs \cup {[type |-> "Commit", dest |-> r] : r \in RM}
  /\ UNCHANGED <<rmState, tmPrepared>>

RMCommit(r) ==
  /\ [type |-> "Commit", dest |-> r] \in msgs
  /\ rmState' = [rmState EXCEPT ![r] = "committed"]
  /\ UNCHANGED <<tmState, tmPrepared, msgs>>

\* Safety: All RMs reach the same decision
Consistency == \A r1, r2 \in RM :
  /\ rmState[r1] = "committed" => rmState[r2] /= "aborted"
  /\ rmState[r1] = "aborted" => rmState[r2] /= "committed"
```

### Paxos (Simplified)

```tla
CONSTANTS
  Acceptors,
  Values,
  Quorum

VARIABLES
  maxBal,       \* maxBal[a] is highest ballot seen by acceptor a
  maxVBal,      \* maxVBal[a] is ballot of highest vote by acceptor a
  maxVal,       \* maxVal[a] is value of highest vote by acceptor a
  msgs

TypeOK ==
  /\ maxBal \in [Acceptors -> Nat]
  /\ maxVBal \in [Acceptors -> Nat \cup {-1}]
  /\ maxVal \in [Acceptors -> Values \cup {None}]

Init ==
  /\ maxBal = [a \in Acceptors |-> 0]
  /\ maxVBal = [a \in Acceptors |-> -1]
  /\ maxVal = [a \in Acceptors |-> None]
  /\ msgs = {}

Phase1a(b) ==
  /\ msgs' = msgs \cup {[type |-> "1a", bal |-> b]}
  /\ UNCHANGED <<maxBal, maxVBal, maxVal>>

Phase1b(a, b) ==
  /\ [type |-> "1a", bal |-> b] \in msgs
  /\ b > maxBal[a]
  /\ maxBal' = [maxBal EXCEPT ![a] = b]
  /\ msgs' = msgs \cup {[type |-> "1b", acc |-> a, bal |-> b,
                         mbal |-> maxVBal[a], mval |-> maxVal[a]]}
  /\ UNCHANGED <<maxVBal, maxVal>>

Phase2a(b, v) ==
  /\ ~ \E m \in msgs : m.type = "2a" /\ m.bal = b
  /\ \E Q \in Quorum :
       LET Q1b == {m \in msgs : m.type = "1b" /\ m.bal = b /\ m.acc \in Q}
       IN /\ \A a \in Q : \E m \in Q1b : m.acc = a
          /\ \/ \A m \in Q1b : m.mbal = -1
             \/ \E m \in Q1b : /\ m.mval = v
                               /\ \A mm \in Q1b : m.mbal >= mm.mbal
  /\ msgs' = msgs \cup {[type |-> "2a", bal |-> b, val |-> v]}
  /\ UNCHANGED <<maxBal, maxVBal, maxVal>>

Phase2b(a, b, v) ==
  /\ [type |-> "2a", bal |-> b, val |-> v] \in msgs
  /\ b >= maxBal[a]
  /\ maxBal' = [maxBal EXCEPT ![a] = b]
  /\ maxVBal' = [maxVBal EXCEPT ![a] = b]
  /\ maxVal' = [maxVal EXCEPT ![a] = v]
  /\ msgs' = msgs \cup {[type |-> "2b", acc |-> a, bal |-> b, val |-> v]}

\* Safety: At most one value is chosen
Consistency ==
  \A v1, v2 \in Values :
    (\E Q \in Quorum : \A a \in Q : maxVal[a] = v1 /\ maxVBal[a] >= 0) /\
    (\E Q \in Quorum : \A a \in Q : maxVal[a] = v2 /\ maxVBal[a] >= 0)
    => v1 = v2
```

## Pattern 3: Leader Election

### Bully Algorithm

```tla
CONSTANTS Procs

VARIABLES
  state,        \* state[p]: "follower", "candidate", "leader"
  leader,       \* Current leader (or None)
  msgs

TypeOK ==
  /\ state \in [Procs -> {"follower", "candidate", "leader"}]
  /\ leader \in Procs \cup {None}

Init ==
  /\ state = [p \in Procs |-> "follower"]
  /\ leader = None
  /\ msgs = {}

StartElection(p) ==
  /\ state[p] = "follower"
  /\ state' = [state EXCEPT ![p] = "candidate"]
  /\ msgs' = msgs \cup {[type |-> "Election", from |-> p, to |-> q] : q \in Procs, q > p}
  /\ UNCHANGED leader

RespondToElection(p, q) ==
  /\ [type |-> "Election", from |-> q, to |-> p] \in msgs
  /\ p > q
  /\ msgs' = msgs \cup {[type |-> "OK", from |-> p, to |-> q]}
  /\ state' = [state EXCEPT ![p] = "candidate"]
  /\ UNCHANGED leader

BecomeLeader(p) ==
  /\ state[p] = "candidate"
  /\ ~ \E q \in Procs : q > p /\ [type |-> "OK", from |-> q, to |-> p] \in msgs
  /\ state' = [state EXCEPT ![p] = "leader"]
  /\ leader' = p
  /\ msgs' = msgs \cup {[type |-> "Coordinator", from |-> p, to |-> q] : q \in Procs}

\* Safety: At most one leader
LeaderUniqueness == \A p, q \in Procs :
  state[p] = "leader" /\ state[q] = "leader" => p = q
```

## Pattern 4: Replication

### Primary-Backup Replication

```tla
CONSTANTS
  Primary,
  Backups,
  Operations

VARIABLES
  primaryLog,   \* Log at primary
  backupLog,    \* Log at each backup
  committed,    \* Committed operations
  msgs

Replicas == {Primary} \cup Backups

TypeOK ==
  /\ primaryLog \in Seq(Operations)
  /\ backupLog \in [Backups -> Seq(Operations)]
  /\ committed \in SUBSET Operations

Init ==
  /\ primaryLog = <<>>
  /\ backupLog = [b \in Backups |-> <<>>]
  /\ committed = {}
  /\ msgs = {}

ClientRequest(op) ==
  /\ primaryLog' = Append(primaryLog, op)
  /\ msgs' = msgs \cup {[type |-> "Replicate", op |-> op, to |-> b] : b \in Backups}
  /\ UNCHANGED <<backupLog, committed>>

BackupAck(b, op) ==
  /\ [type |-> "Replicate", op |-> op, to |-> b] \in msgs
  /\ backupLog' = [backupLog EXCEPT ![b] = Append(@, op)]
  /\ msgs' = msgs \cup {[type |-> "Ack", op |-> op, from |-> b]}
  /\ UNCHANGED <<primaryLog, committed>>

Commit(op) ==
  /\ op \in DOMAIN primaryLog
  /\ \A b \in Backups : [type |-> "Ack", op |-> op, from |-> b] \in msgs
  /\ committed' = committed \cup {op}
  /\ UNCHANGED <<primaryLog, backupLog, msgs>>

\* Safety: All replicas have same committed operations
Consistency == \A b \in Backups :
  \A i \in DOMAIN backupLog[b] :
    backupLog[b][i] \in committed => backupLog[b][i] = primaryLog[i]
```

## Pattern 5: Distributed Transactions

### Snapshot Isolation

```tla
CONSTANTS
  Txns,         \* Transaction IDs
  Keys,         \* Data keys
  Values

VARIABLES
  store,        \* Versioned key-value store
  snapshots,    \* Snapshot for each transaction
  writeSet,     \* Write set for each transaction
  committed     \* Committed transactions

TypeOK ==
  /\ store \in [Keys -> Seq([val: Values, txn: Txns])]
  /\ snapshots \in [Txns -> [Keys -> Values]]
  /\ writeSet \in [Txns -> [Keys -> Values]]
  /\ committed \in SUBSET Txns

Init ==
  /\ store = [k \in Keys |-> <<>>]
  /\ snapshots = [t \in Txns |-> [k \in Keys |-> InitialValue]]
  /\ writeSet = [t \in Txns |-> [k \in Keys |-> NoValue]]
  /\ committed = {}

BeginTxn(t) ==
  /\ t \notin committed
  /\ snapshots' = [snapshots EXCEPT ![t] = [k \in Keys |-> LatestValue(store[k])]]
  /\ UNCHANGED <<store, writeSet, committed>>

Read(t, k) ==
  /\ t \notin committed
  /\ snapshots[t][k]  \* Returns snapshot value
  /\ UNCHANGED <<store, snapshots, writeSet, committed>>

Write(t, k, v) ==
  /\ t \notin committed
  /\ writeSet' = [writeSet EXCEPT ![t][k] = v]
  /\ UNCHANGED <<store, snapshots, committed>>

CommitTxn(t) ==
  /\ t \notin committed
  /\ NoConflicts(t, writeSet[t])
  /\ store' = ApplyWrites(store, t, writeSet[t])
  /\ committed' = committed \cup {t}
  /\ UNCHANGED <<snapshots, writeSet>>

\* Safety: Snapshot isolation guarantees
SnapshotIsolation ==
  \A t1, t2 \in committed :
    t1 /= t2 => NoWriteWriteConflict(t1, t2)
```

## Tips for Distributed Systems

1. **Model network explicitly** - Use message sets or channels
2. **Handle message loss** - Non-deterministically drop messages
3. **Model failures** - Process crashes, network partitions
4. **Use quorums** - For fault tolerance and consistency
5. **Check safety first** - Then add liveness properties
6. **Start with small models** - N=2 or N=3 processes
7. **Use symmetry** - Reduce state space for identical processes
8. **Abstract data** - Focus on protocol, not data values

Files in this skill

  • README.md917 B
  • skill.md9.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…