{
  "generator": {
    "name": "Symvanta",
    "url": "https://symvanta.com"
  },
  "page": {
    "url": "https://symvanta.com/architecture/etcd",
    "title": "etcd Architecture: How It Actually Works",
    "description": "etcd mapped into 148 modules with zero cycles: the etcdserver core that funnels every write into Raft, the mvcc store under it, and the client vocabulary above it, traced by Symvanta.",
    "datePublished": "2026-06-25",
    "dateModified": "2026-08-22"
  },
  "repository": {
    "name": "etcd-io/etcd",
    "url": "https://github.com/etcd-io/etcd",
    "commit": "c34dc7e",
    "license": "Apache-2.0"
  },
  "graph": {
    "modules": 148,
    "dependencyCycles": 0,
    "modularityQ": 0.92,
    "largestCycleFiles": null,
    "mutuallyRecursiveGroups": 11
  },
  "summaryMarkdown": "etcd is a distributed, reliable key-value store built on the Raft consensus protocol: the coordination store that Kubernetes and a long list of other distributed systems rely on to hold cluster state consistently across machines. Clients talk to it over gRPC (`Range`, `Put`, `Delete`, `Txn`, `Watch`, `LeaseGrant`, and friends), and every write that changes the store's state has to be proposed to and committed by Raft before it lands in the underlying storage engine. [Symvanta](https://symvanta.com)'s Louvain community detection organized the codebase's indexed symbols into 148 functional modules (modularity Q=0.92, a clean separation of concerns for a codebase this size, with zero circular dependencies between modules). The largest module that belongs to the server rather than to its harnesses is `etcdserver` (962 symbols), and its hub, [`raftRequest`](https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L1012), is the funnel every mutating client request passes through on its way to a Raft proposal. The modules around it exist to make that funnel safe: `mvcc` holds the versioned data, `wal` makes an entry durable before Raft is allowed to call it committed, `schema` gives the bolt database its bucket layout, and the two `client/v3` modules carry the request vocabulary and the connection every caller reaches the cluster through.",
  "subsystems": [
    {
      "name": "etcdserver",
      "descriptionMarkdown": "The server core. `raftRequest` and `processInternalRaftRequestOnce` turn a client mutation into a Raft proposal and block until it has been applied, the apply loop that executes committed entries in index order lives beside them, and the membership accessors around both (`MemberID`, `AuthStore`, `ToMemberDir`) answer who this node is and who else is in the cluster."
    },
    {
      "name": "mvcc",
      "descriptionMarkdown": "The multi-version key-value store. `NewStore` opens the bolt-backed store, `newTreeIndex` builds the in-memory index that maps a key to the revisions it was written at, and the tombstone and revision helpers around them decide what a read at a given revision returns. Its highest-PageRank member is a teardown fixture from the package's own suite (`cleanup`), which is what happens when a package is exercised from as many directions as etcd exercises this one; the thematic center is the store, the tree index, and the compaction path."
    },
    {
      "name": "client/v3",
      "descriptionMarkdown": "The client library's request vocabulary. `NewOp` and the `OpOption` builders assemble every Get, Put, Delete, and Txn a client sends, and `Cmp.ensureCompare` normalizes the comparison a transaction guards on before it goes out over the wire. At 621 symbols this is the largest module outside the server, and it is the one piece of etcd that ships into every consumer of the store."
    },
    {
      "name": "client/v3 connection",
      "descriptionMarkdown": "The client library's connection layer. `newClient` builds the gRPC connection a `Config` describes, `translateEndpoint` turns an endpoint string into a dial target and its credential requirement, the retry interceptor decides which failures are safe to replay, and `ContextError` maps a dead context onto the error the caller sees. Louvain splits it from the request vocabulary because the two halves call each other far more than either calls anything else: 37 calls one way, 13 back."
    },
    {
      "name": "schema",
      "descriptionMarkdown": "The bucket layout of the bolt database. `UnsafeReadConsistentIndex` reads the applied Raft index etcd stamps into the database on every commit, and the alarm, auth, lease, and membership buckets alongside it carry the server state that must survive a restart. `Validate` and `UnsafeMigrate` are what let one binary open a database another version wrote."
    },
    {
      "name": "rafthttp",
      "descriptionMarkdown": "Peer-to-peer transport. `Transport.Send` hands outbound Raft messages to the right peer, each peer holds a `streamWriter` for the long-lived connection and a `pipeline` for one-shot posts, and `urlPicker` rotates through a peer's advertised URLs when one stops answering. It is the only module on the map whose whole job is talking to other machines."
    },
    {
      "name": "wal",
      "descriptionMarkdown": "The write-ahead log. `Create` and `parseWALName` own the segment files, `encode` frames each record with a chained CRC, and `sync` is the fsync barrier a Raft entry clears before the cluster is allowed to call it committed. The [write-ahead log walkthrough](/architecture/etcd/write-ahead-log) follows one entry through this module to disk and back out again on restart."
    },
    {
      "name": "embed",
      "descriptionMarkdown": "Server configuration. `NewConfig` builds the `Config` an embedded or standalone etcd starts from, and `Validate`, `InitialClusterFromName`, and the advertise-URL accessors decide whether that configuration describes a cluster this node can actually join. Its 20 calls into `etcdserver` are the boot sequence handing a validated config to the server it is about to start."
    },
    {
      "name": "auth",
      "descriptionMarkdown": "The authentication store: users, roles, and the range-permission cache that answers whether a key is in scope for the caller. `Revision` is the auth revision every request header carries, so a proposal built against a stale permission set is rejected instead of applied."
    },
    {
      "name": "cache",
      "descriptionMarkdown": "A watch-backed read cache that sits in front of a cluster. `Cache.Watch` fans one upstream watch out to many local watchers, `demux` keeps the local snapshot current from that stream, and `newRingBuffer` holds a bounded window of recent events so a lagging watcher resyncs from history instead of opening a second upstream watch. Its hub, `enqueueResponse`, is the non-blocking delivery step that returns false when a watcher buffer is full, which is how a slow consumer gets marked lagging instead of stalling the fan-out."
    }
  ],
  "startReading": {
    "symbols": [
      {
        "name": "raftRequest",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L1012"
      },
      {
        "name": "ensureCompare",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/client/v3/compare.go#L119"
      },
      {
        "name": "ContextError",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/client/v3/client.go#L606"
      },
      {
        "name": "String",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/api/rafthttp/stream.go#L85"
      },
      {
        "name": "tail",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/storage/wal/wal.go#L1067"
      },
      {
        "name": "NewConfig",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/embed/config.go#L492"
      },
      {
        "name": "Revision",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/auth/store.go#L1009"
      },
      {
        "name": "enqueueResponse",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/cache/watcher.go#L42"
      },
      {
        "name": "mustClientFromCmd",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/etcdctl/ctlv3/command/global.go#L154"
      },
      {
        "name": "togRPCError",
        "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/api/v3rpc/util.go#L98"
      }
    ],
    "endpoints": []
  },
  "requestFlow": [
    {
      "position": 1,
      "symbol": "v3rpc.kvServer.Put",
      "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/api/v3rpc/key.go#L90",
      "markdown": "`v3rpc.kvServer.Put` ([`server/etcdserver/api/v3rpc/key.go:90`](https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/api/v3rpc/key.go#L90)) is the gRPC entry point. It validates the request with `checkPutRequest`, calls the server's `Put`, routes any failure through `togRPCError` so the client gets a gRPC status code rather than an internal error value, and stamps the cluster and revision header on the way out."
    },
    {
      "position": 2,
      "symbol": "etcdserver.EtcdServer.Put",
      "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L295",
      "markdown": "`etcdserver.EtcdServer.Put` ([`server/etcdserver/v3_server.go:295`](https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L295)) is 14 lines and writes nothing. It wraps the request in an `InternalRaftRequest` and hands it to `raftRequest`."
    },
    {
      "position": 3,
      "symbol": "etcdserver.EtcdServer.raftRequest",
      "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L1012",
      "markdown": "`etcdserver.EtcdServer.raftRequest` ([`server/etcdserver/v3_server.go:1012`](https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L1012)) calls `processInternalRaftRequestOnce` on its first line, then reworks the `traceutil.Trace` that comes back on the result (`GetStartTime`, `SetStartTime`, `InsertStep`, `LogIfLong`) so a slow proposal gets logged against the request's own start time."
    },
    {
      "position": 4,
      "symbol": "etcdserver.EtcdServer.processInternalRaftRequestOnce",
      "sourceUrl": "https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L1058-L1133",
      "markdown": "`etcdserver.EtcdServer.processInternalRaftRequestOnce` ([`server/etcdserver/v3_server.go:1058-1133`](https://github.com/etcd-io/etcd/blob/c34dc7ee0048fd2bcc44d50beff002e5e8069b69/server/etcdserver/v3_server.go#L1058-L1133)) checks `exceedsRequestLimit` first (line 1062), which compares the server's applied and committed Raft indexes so a client cannot propose faster than the server can keep up. It then stamps the request with a unique ID (line 1067), resolves the caller's identity through `AuthInfoFromCtx` (line 1072), classifies the request with `getRequestType` (line 1086), marshals it (line 1093), registers a wait keyed on the request ID (line 1106), and proposes the bytes to the Raft node (line 1113). A proposal that times out is translated by `parseProposeCtxErr` (line 1129) before the error reaches the caller."
    }
  ],
  "deepDives": [
    {
      "title": "etcd Raft Consensus: Put to Committed Write",
      "url": "https://symvanta.com/architecture/etcd/raft-consensus",
      "description": "How an etcd Put travels through a Raft proposal, quorum commit, and the apply loop into the mvcc store, traced by Symvanta."
    },
    {
      "title": "etcd Write-Ahead Log: Entry to Disk and Replay",
      "url": "https://symvanta.com/architecture/etcd/write-ahead-log",
      "description": "How etcd's WAL encodes, CRC-checks, and fsyncs each Raft entry, rotates segments, and replays them after a crash."
    }
  ],
  "diagrams": [
    {
      "url": "https://symvanta.com/architecture/etcd/module-map.svg",
      "encodingFormat": "image/svg+xml"
    }
  ]
}
