Twenty-six artefacts, all from two git histories and the documents committed
inside them. There is no blog, talk or paper tier here: those hosts were refused by this
session's egress policy, and the ledger names what a reader with open egress should read first.
Decision record
Elastic2026-10
Elasticsearch Requirements for an S3-Compatible Object Store
A clause-by-clause contract with the storage layer, each clause carrying what breaks
without it. Names the register as the foundation of coordination, the two CAS paths, the
read-after-write and listing requirements on the hot path, and the server-side copy that
resharding uses.
Carry forwardWrite this document for your own storage dependency. The clauses you cannot test are the ones that will fail.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/docs/internal/s3-object-store-requirements.md
Decision record
Elastic2026-10
Distributed Area Internals, 3,584 lines
The in-repository architecture guide. Sections used here: stateless roles, serverless
elections, the write path, primary terms and sequence numbers, checkpoints and gaps, and
the translog's acknowledgement rules. It is also where the project distinguishes stateless,
the architecture, from serverless, the offering.
Carry forwardInternal design docs committed beside the code age with the code; a wiki does not.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/docs/internal/DistributedArchitectureGuide.md
Postmortem
Elastic2026-10
Known issues, 9.5.0 to 9.5.2: replicas diverge under indexing pressure
The clearest correctness failure in the record: crossing the indexing-pressure limit mid
bulk request could leave items on the primary unreplicated, with divergent replicas,
blocked translog trimming and replay-everything recoveries. Introduced by a named pull
request, fixed in a named pull request two patch releases later.
Carry forwardReview every load-shedding branch as a correctness change, because it is one.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/docs/release-notes/known-issues.md
Postmortem
Elastic2026-10
Known issues, 9.5.0 and 9.5.1: false positives on non-indexed fields
Time-series and columnar index modes disable indexing on all fields to save storage, and a
Lucene bulk-scorer defect turned that into wrong query results for a specific boolean
shape. The first fix covered two query paths and missed a third.
Carry forwardA cost feature that removes a data structure needs a correctness matrix, not a storage chart.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/docs/release-notes/known-issues.md
Postmortem
Elastic2026-10
Known issues, 9.2.4: CorruptStateException on boot after upgrade
A patch upgrade from 9.1.10 to 9.2.4 could leave a node unable to parse its own persisted
cluster metadata, failing at startup inside GatewayMetaState.start. The entry
also carries two GCS-credential regressions from the same series, each with a workaround
encoded as a base64 policy override.
Carry forwardInternal persisted state is a versioned schema; test its upgrade path like a public API.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/docs/release-notes/known-issues.md
Source code
Elasticv9.3.0
S3BlobContainer.java, the compare-and-exchange operation
Both CAS paths in one file: conditional headers when the store supports them, and the
multipart protocol when it does not, complete with upload-id ordering, position-based
back-off, a clock-skew warning against the store's own initiation timestamps, and a comment
citing FLP to explain why liveness is best effort.
Carry forwardIf your coordination rests on a protocol with no liveness proof, say so in the code, and keep the retry budget generous.
raw.githubusercontent.com/elastic/elasticsearch/v9.3.0/.../S3BlobContainer.java
Source code
Elasticv9.3.0
S3Repository.java, the unsafety switch
The setting unsafely_incompatible_with_s3_conditional_writes defaults to
false, and turning it on logs that the repository "may lead to repository corruption" with
a pointer to the compatibility documentation.
Carry forwardName an escape hatch after its risk. Operators read setting names, not release notes.
raw.githubusercontent.com/elastic/elasticsearch/v9.3.0/.../S3Repository.java
Vendor doc
Elastic2025-10
Release highlight, 9.2.0: conditional writes prevent repository corruption
States that earlier versions carried a small risk of overwriting an object in an S3
repository and corrupting its contents, and that 9.2.0 uses conditional writes to prevent
it. The companion 9.3.0 bundle carries the register change as pull request 139228.
Carry forwardRelease highlights are where a project admits what the old design could lose.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/docs/release-notes/changelog-bundles/9.2.0.yml
Decision record
Elastic2026-04-29
Commit b40e7eb23, "Migrate stateless modules with full file history"
The migration of the private elasticsearch-serverless fork into the public
repository: six modules into x-pack/plugin/, a test framework and a QA module,
history preserved through a two-step git-filter-repo rename, licence headers
rewritten to the Elastic Licence, and the fork point named.
Carry forwardA fork merged back with history is a four-year design record handed to the public in one commit. Read the history, not the diff.
github.com/elastic/elasticsearch/commit/b40e7eb23
Source code
Elastic2026-04-23
Commit 6caac0157, removing out-of-scope modules from the migration
Names the files that stayed serverless-only, including
ServerlessStatelessPlugin.java and the split-state transport actions, which
shows that the public plugin is a subset of what the managed service runs.
Carry forwardWhen a vendor open-sources an architecture, diff the module list before assuming parity.
github.com/elastic/elasticsearch/commit/6caac0157
Source code
Elastic2026-10
StatelessPlugin.java licence header
The merged architecture carries an Elastic Licence 2.0 header, inside a repository whose
top-level licence became a triple licence including AGPL-3.0 in 8.16.0. Public source,
restricted use.
Carry forward"In the public repository" and "open source" are now independent properties. Check the file header.
raw.githubusercontent.com/elastic/elasticsearch/b2f4a538f/.../StatelessPlugin.java
Decision record
Elastic2018-03-16
Commit 708c06896, "Explain why Elasticsearch doesn't support incremental resharding"
A documentation commit written as a design rationale: consistent hashing is the usual
answer, but a shard is a Lucene index, so moving 5% of documents costs far more than in a
key-value store. Hence multiplicative, local splits using hard links.
Carry forwardWrite down why you refused a feature. Eight years later it is the clearest statement of which constraint changed.
github.com/elastic/elasticsearch/commit/708c06896
Source code
Elastic2015 to 2016
Primary terms, sequence numbers and the global checkpoint
Commits b364cf54b (2015-10-09), 5fb0f9a88 (2015-11-03) and 484432592 (2016-06-06) give
every operation a name and a term, and define the safety line across in-sync copies. Ten
years later the same term is what a fence compares against.
Carry forwardYou cannot fence what you cannot name. Identity for writes is the prerequisite for every later move.
github.com/elastic/elasticsearch/commit/484432592
Source code
Elastic2018 to 2019
Soft deletes and shard history retention leases
Commit ac84879a7 (2018-04-19) keeps document history in Lucene rather than the translog;
commit c0f8c8917 (2019-01-07) turns the right to retain that history into an explicit,
expiring lease. Operation-based recovery and cross-cluster replication both depend on it.
Carry forwardRetention is a resource. Make somebody hold a lease on it, with an expiry, or it grows without an owner.
github.com/elastic/elasticsearch/commit/c0f8c8917
Source code
Elastic2018-08
The Zen2 coordination layer
Commits 2176184db and 785b6e824 build the discovery and publication pipeline of the
quorum-based coordination layer that shipped in 7.0 (tag dated 2019-04-10). It is the
mechanism the stateless deployment later sets aside in favour of a lease register.
Carry forwardA consensus layer built for peer nodes is not wasted when state moves: it stays the answer for every deployment without a linearizable store.
github.com/elastic/elasticsearch/commit/2176184db
Source code
Elastic2021-02-05
Commit 50f4a0b77, partial searchable snapshots for a frozen tier
The first production tier whose local disk is only a partial cache of data that lives in
the object store, with allocation restricted to nodes that have a cache (commit 1a432a26d,
2021-03-04). The pattern the stateless engine later generalises.
Carry forwardShip the cache-backed tier at the cold end first. It teaches the eviction and allocation problems at low stakes.
github.com/elastic/elasticsearch/commit/50f4a0b77
Source code
Elastic2022-09-28
Commit e3f86aa0d, "Add stateless skeleton project"
The first commit of the stateless work, in the private fork, now visible in the public
history. The index and search roles arrive three weeks later, behind a feature flag.
Carry forwardFour years from skeleton to self-managed availability is the honest schedule for rebuilding a storage engine's durability.
github.com/elastic/elasticsearch/commit/e3f86aa0d
Source code
Elastic2023-04-04
Commit 3aeeb4584, "Sync translog to object before acking write"
The commit that moves the durability boundary from a local fsync to an object-store upload.
Everything in the failure catalogue's second class follows from this one line of design.
Carry forwardLocate the exact commit where your acknowledgement crosses a new boundary. That is the date your failure modes changed.
github.com/elastic/elasticsearch/commit/3aeeb4584
Source code
Elastic2023-04-17
Commit da214475a, heartbeat leadership into production
The atomic-register pre-vote collector and the blob-store heartbeat service move from test
scaffolding into production code, three weeks after the project taught a leader to stand
down when its heartbeat write fails (commit 3416ce0df).
Carry forwardA leader that cannot write its lease must resign. Make that explicit before you make the lease authoritative.
github.com/elastic/elasticsearch/commit/da214475a
Source code
Elastic2024-12 to 2025-05
Hollow shards and online prewarming
Commits 654e85e39 and 9325e5ca9 make an idle indexing shard evictable from compute on a
time-to-live and recoverable through a hollow engine; commits fa0925518 and 93c893a76 make
cache population a service with its own interface.
Carry forwardThe compute saving and the cold-start penalty are the same feature. Budget for the warming path in the same design review.
github.com/elastic/elasticsearch/commit/654e85e39
Source code
Elastic2026-08-18
Commit 05ef24f05, marking the S3 escape hatch for removal
The non-conditional-write setting "was documented as deprecated as soon as it was
introduced" and now carries an annotation scheduling it for removal in the next major
version. The compatibility window for stores without conditional writes is explicit.
Carry forwardDate your compatibility shims at birth. An undated shim becomes a permanent supported configuration.
github.com/elastic/elasticsearch/commit/05ef24f05
Source code
Elastic2021 to 2024
LICENSE.txt at v7.10.2, v7.11.0 and v8.16.0
Apache-2.0 based through 7.10.2, a dual Server Side Public Licence and Elastic Licence from
7.11.0 (2021-02-10), and a triple licence adding AGPL-3.0 from 8.16.0 (2024-11-08). The
licence boundary is the fork boundary, and the fork is the comparison this guide depends on.
Carry forwardRead a licence change as an architectural event: it determines who else will solve your problem in public.
raw.githubusercontent.com/elastic/elasticsearch/v7.11.0/LICENSE.txt
Source code
OpenSearch2022-04-25
Commit ee7b73197, replication type as an index setting
The fork's first move is to make replication type configurable per index, introducing
segment replication beside document replication rather than removing replication. Feature
flags arrive in the same commit.
Carry forwardPer-index switching lets a storage change ship incrementally; a node-role split does not.
github.com/opensearch-project/OpenSearch/commit/ee7b73197
Source code
OpenSearch2022-06 to 2022-09
Remote store: segments, then translog
Commit fb1375987 uploads segments to a remote store after refresh; commit 57a4aedb0 changes
replica recovery for remote-translog indices. Same conclusion as the other lineage, two
months apart, with the shard still owned by a data node.
Carry forwardMoving segments is the easy half. The write-ahead log and the fence are where the design is decided.
github.com/opensearch-project/OpenSearch/commit/fb1375987
Decision record
OpenSearch2026-09-01
Commit 98da9b425, object-store fencing token
A commit message written as a design document: why replica-based fencing made a replica a
safety requirement, why the fencing token is the CAS chain rather than the term, why a
takeover claims the fence before reading its restore point, and why deleting lower-term
objects is what makes a takeover certain.
Carry forwardDeterminism from the key space beats determinism from winning a race. Design fences so the loser discovers it lost.
github.com/opensearch-project/OpenSearch/commit/98da9b425
Source code
OpenSearch2026-04 to 2026-05
WritableWarm tiered storage
Commits ee6052b64 and bf7bfedc0 build a Lucene directory and index-input layer over
object storage with a file cache, plus prefetch settings and per-query metrics. Compute and
storage separation as a tier, not as a cluster shape.
Carry forwardIf you cannot change your cluster's node roles, a cache-backed directory implementation buys most of the storage economics.
github.com/opensearch-project/OpenSearch/commit/ee6052b64