Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sequence diagram examples

Six diagrams from systems work. Each uses the notation of the sequence diagram page.

TCP connection: handshake, data and teardown

The three-way handshake, a segment and its acknowledgement, and a graceful close. A lost segment leaves through a lost message.

diagram sequence "TCP connection"

participant "Client" as c
participant "Server" as s

note over c, s: Three-way handshake
c ->> s : SYN seq=x
s ->> c : SYN+ACK seq=y, ack=x+1
c ->> s : ACK ack=y+1
note over c, s: Established
c ->> s : data seq=x+1, len=512
s ->> c : ACK ack=x+513
opt "segment lost" {
  c ->] : data seq=x+513
  c ->> s : retransmit after RTO
}
note over c, s: Graceful close
c ->> s : FIN
s ->> c : ACK
s ->> c : FIN
c ->> s : ACK
note right of c: TIME_WAIT for 2 MSL before the socket is freed.
TCP connection opt [segment lost] Client Server Three-way handshake Established Graceful close TIME_WAIT for 2 MSL before the socket is freed. SYN seq=x SYN+ACK seq=y, ack=x+1 ACK ack=y+1 data seq=x+1, len=512 ACK ack=x+513 data seq=x+513 retransmit after RTO FIN ACK FIN ACK

Raft log replication

The leader appends locally, replicates to followers in parallel and commits once a majority has acknowledged. One follower rejects the entry.

diagram sequence "Raft: replicating one log entry"

actor "Client" as client
participant "Leader" as leader <<raft>>
participant "Follower 1" as f1
participant "Follower 2" as f2
participant "State machine" as sm

client -> leader : command(x) {
  leader -> leader : append to log
  par {
    leader -> f1 : AppendEntries(term, entry) {
      f1 -> f1 : append and persist
      return success
    }
  } and {
    leader -> f2 : AppendEntries(term, entry) {
      alt "log matches prevLogIndex" {
        f2 -> f2 : append and persist
        return success
      } else "prevLogTerm mismatch" {
        return reject (conflict index)
        note right of f2: Leader walks nextIndex back and retries.
      }
    }
  }
  critical "majority acknowledged" {
    leader -> leader : advance commitIndex
    leader -> sm : apply(x) {
      return result
    }
  }
  return result
}
Raft: replicating one log entry alt [log matches prevLogIndex] [prevLogTerm mismatch] par critical [majority acknowledged] Client «raft» Leader Follower 1 Follower 2 State machine Leader walks nextIndex back and retries. command(x) append to log AppendEntries(term, entry) append and persist success AppendEntries(term, entry) append and persist success reject (conflict index) advance commitIndex apply(x) result result

Interrupt handling with a nested IRQ

A device interrupt enters the CPU as a found message, and a higher priority interrupt preempts the handler. The hardware restores context on return from interrupt.

diagram sequence "Nested interrupt handling"

participant "Timer" as timer
participant "CPU core" as cpu
participant "Kernel entry" as entry
participant "UART ISR" as isr
participant "Timer ISR" as tisr
participant "Scheduler" as sched

[-> cpu : UART IRQ {
  cpu ->> entry : vector through IDT
  entry -> entry : save registers
  entry -> isr : uart_isr() {
    isr -> isr : read FIFO
    timer ->> cpu : timer IRQ
    note over cpu, tisr: Higher priority: the ISR is preempted.
    cpu -> tisr : timer_isr() {
      tisr ->> sched : mark reschedule
      return eoi
    }
    return eoi
  }
  entry -> entry : check need_resched
  opt "reschedule pending" {
    entry -> sched : schedule() {
      return next task
    }
  }
  entry ->> cpu : iret
  return resumes interrupted task
}
Nested interrupt handling opt [reschedule pending] Timer CPU core Kernel entry UART ISR Timer ISR Scheduler Higher priority: the ISR is preempted. UART IRQ vector through IDT save registers uart_isr() read FIFO timer IRQ timer_isr() mark reschedule eoi eoi check need_resched schedule() next task iret resumes interrupted task

TLS 1.3 handshake

The handshake with a ServerHello carrying the key share, and Finished from both sides. Application data flows once the keys are in place. A failed verification ends with an alert.

diagram sequence "TLS 1.3 handshake"

participant "Client" as c
participant "Server" as s
participant "CA store" as ca

c -> s : ClientHello(key_share, sni, supported_versions) {
  s -> s : derive handshake secrets
  return ServerHello(key_share)
}
note over c, s: Encrypted from here on: EncryptedExtensions, Certificate, CertificateVerify, Finished
s ->> c : EncryptedExtensions
s ->> c : Certificate
s ->> c : CertificateVerify
c -> ca : verify chain(certificate) {
  return ok
}
alt "certificate valid" {
  s ->> c : Finished
  c ->> s : Finished
  note over c, s: Application data, protected by traffic keys
  c ->> s : HTTP request
  s ->> c : HTTP response
} else "verification failed" {
  c ->> s : alert(bad_certificate)
  c ->] : close connection
}
TLS 1.3 handshake alt [certificate valid] [verification failed] Client Server CA store Encrypted from here on: EncryptedExtensions, Certificate, CertificateVerify, Finished Application data, protected by traffic keys ClientHello(key_share, sni, supported_versions) derive handshake secrets ServerHello(key_share) EncryptedExtensions Certificate CertificateVerify verify chain(certificate) ok Finished Finished HTTP request HTTP response alert(bad_certificate) close connection

RPC with retry and exponential backoff

A client retries a call that times out and gives up after three attempts. A circuit breaker records the outcome.

diagram sequence "RPC with retry"

participant "Client stub" as stub
participant "Circuit breaker" as cb
participant "Service" as svc

loop "(1,3)" {
  stub -> cb : allow? {
    return true
  }
  stub -> svc : GetOrder(id, deadline=200ms) {
    alt "reply before deadline" {
      return order
      break "success" {
        stub ->> cb : record success
      }
    } else "deadline exceeded" {
      stub -> stub : sleep(backoff with jitter)
      stub ->> cb : record failure
    }
  }
}
stub --> stub : surface error to caller
note right of stub: The stub surfaces the last error once retries run out.
RPC with retry break [success] alt [reply before deadline] [deadline exceeded] loop(1,3) Client stub Circuit breaker Service The stub surfaces the last error once retries run out. allow? true GetOrder(id, deadline=200ms) order record success sleep(backoff with jitter) record failure surface error to caller

Page fault in a demand-paged kernel

A page fault handled through a lookup and swap-in, showing creation and destruction of a transient object.

diagram sequence "Page fault"

participant "MMU" as mmu
participant "Kernel" as k
participant "Swap device" as swap

[-> mmu : translate(vaddr)
mmu -> k : page fault(vaddr) {
  k -> new "Fault context" as fc <<per fault>> : allocate
  k -> k : find VMA
  alt "anonymous page" {
    k -> swap : read(slot) {
      note right of swap: The request is queued and the task sleeps.
      return page
    }
    k -> k : map page
  } else "invalid access" {
    k ->] : SIGSEGV to task
  }
  destroy fc
  return retry the access
}
Page fault alt [anonymous page] [invalid access] MMU Kernel Swap device «per fault» Fault context The request is queued and the task sleeps. translate(vaddr) page fault(vaddr) allocate find VMA read(slot) page map page SIGSEGV to task retry the access