LinkedIn data platform  / field guide
Practitioner field guide · 15 September 2026

Own the layer above the engine: ten years of LinkedIn's data platform

Reconstructed from 135 public repositories, their dated release histories on four package registries, and the security advisories filed against them: which parts of a derived-data platform LinkedIn kept building between 2015 and 2026, which it handed to a foundation, and which it let die without ever saying so. A reader leaves able to date any organisation's platform decisions from artefacts rather than announcements, and to argue the precompute, query and embed choices on the read path with numbers attached.

55 primary sources 12 production systems 5 incident records Evidence through September 2026 Read: 22 min
01

The territory

A member-facing page is assembled from data that was computed somewhere else, minutes or hours earlier, and it has a few milliseconds to arrive. The architectural question is not how to compute it. It is which parts of the machinery that stores and serves it you should own, given that the engines underneath will be replaced twice in a decade.

100k+
queries per second served at millisecond latency by Pinot at LinkedIn, across 50+ user-facing products
< 1ms
stated latency of the Venice client that keeps the dataset in the application process, at zero network hops
2018
year LinkedIn stopped all production use of Voldemort, the key-value store it published in 2009
123.7M
pulls of a LinkedIn container image that has not been updated since April 2024

LinkedIn is a useful subject for this question because almost everything it decided is dated in public. The company published its storage engine, its change-capture system, its stream processor, its OLAP store, its service framework and its metadata catalogue, and each of those repositories now carries a release history, an archive notice, a fork, a transfer or an unexplained silence. Read together, the artefacts say something the announcements do not: the software LinkedIn still writes is not engines. It is the layer directly above them. Coral translates SQL dialects. Transport makes user-defined functions portable. OpenHouse reconciles table state. Hoptimator plans pipelines across Kafka, Flink and Venice. The engines those things sit on are Apache projects, several of which LinkedIn invented and gave away.

The finding that surprised me

The registry record inverts the production record. Voldemort, which LinkedIn stopped running in 2018, is fully downloadable. Venice, which LinkedIn runs now, is not on Maven Central at all: its own README tells you to add a separate repository because "Venice dependencies are not published on Maven Central". Rest.li, deprecated in 2026, last published an artefact to Central on 17 December 2019, while its repository kept shipping releases up to 29.85.15 on 29 June 2026. If you judge a dependency's health by the registry, you will get LinkedIn exactly backwards.

What this guide covers: the derived-data half of LinkedIn's platform, meaning ingestion, change capture, materialisation and online serving of data computed elsewhere, plus the catalogue and translation layers around it, between roughly 2015 and September 2026. What it deliberately does not cover: Espresso, the online document store that holds primary member data and has never been published; the feed, search and advertising serving stacks; anything about ranking or model training beyond where it touches storage; and the internal economics, because no cost figure for any of this exists in public.

Figure 1 · Four exit routes, and what stayed

Deprecated in place

Voldemort
stopped 2018

Databus
no notice

rest.li
archived 2026

Transferred out

DataHub
now datahub-project

Feathr
now LF AI and Data

Donated to Apache

Kafka

Helix

Pinot

Samza

Gobblin

Retained and still shipping

Venice
derived KV serving

Ambry
blob store

Coral + Transport
SQL and UDF semantics

OpenHouse + Hoptimator
table and pipeline control

Deprecated in place

Voldemort
stopped 2018

Databus
no notice

rest.li
archived 2026

Transferred out

DataHub
now datahub-project

Feathr
now LF AI and Data

Donated to Apache

Kafka

Helix

Pinot

Samza

Gobblin

Retained and still shipping

Venice
derived KV serving

Ambry
blob store

Coral + Transport
SQL and UDF semantics

OpenHouse + Hoptimator
table and pipeline control

Every system LinkedIn published took one of four routes, and the group that stayed is two stores with no open equivalent plus three control and translation layers that sit above other people's engines. Reconstructed from the public repository listing and the release histories in section 5.
Diagram source
02

How it is actually built

One shape recurs across every LinkedIn repository that touches derived data: compute offline or nearline, materialise into a store whose write path is a log, and then argue about how many network hops remain between the application and the bytes.

Venice's own write-path document is the clearest statement of the shape, and it is worth noticing how little of it is Venice. A store has versions; each version is a Kafka topic, called the version topic, and nearline writes arrive on a second topic, the real-time topic. Apache Helix assigns partitions to servers and decides which replica leads. ZooKeeper holds the metadata. The Venice server's job is to consume its partitions, apply them to local RocksDB, and report ingestion state back through Helix views. In other words, the system LinkedIn kept is a coordination and serving layer over three components it did not have to write, one of which, Helix, it wrote and then gave to the Apache Software Foundation in 2013 and still consumes from Maven Central today.

The read path is where the real design argument lives, and Venice's documentation prices it honestly. Three clients read the same data with the same API. The Thin Client takes two network hops through a router and is documented at under 10 milliseconds. The Fast Client takes one hop by routing straight to the partition and is documented at under 2 milliseconds. The Da Vinci Client takes zero hops, because it "eagerly loads Venice data into local RocksDB storage" inside the application process, and is documented at under 1 millisecond. The documentation states the price of the last one in the same breath: "Higher memory/disk footprint (stores full dataset locally)" and "Higher startup time (must bootstrap full dataset on first launch)". That is the entire precompute argument in two bullet points. Latency is bought with copies, and copies are paid for in bootstrap time and disk.

Figure 2 · The reference architecture, with ownership marked

controls

replicates

governs

rewrites

deploys

Batch compute
Hadoop, Spark

Version topic
(Kafka)

Nearline compute
Samza, Flink

Real-time topic
(Kafka)

Brooklin
change capture

Venice server
RocksDB per partition

Helix + ZooKeeper
partition assignment

Router

Thin client
2 hops

Fast client
1 hop

Da Vinci client
0 hops, local RocksDB

OpenHouse
table control plane

Coral + Transport
dialect and UDF layer

Hoptimator
pipeline planner

controls

replicates

governs

rewrites

deploys

Batch compute
Hadoop, Spark

Version topic
(Kafka)

Nearline compute
Samza, Flink

Real-time topic
(Kafka)

Brooklin
change capture

Venice server
RocksDB per partition

Helix + ZooKeeper
partition assignment

Router

Thin client
2 hops

Fast client
1 hop

Da Vinci client
0 hops, local RocksDB

OpenHouse
table control plane

Coral + Transport
dialect and UDF layer

Hoptimator
pipeline planner

The engines in the middle row are other people's; the boxes with heavy borders are what LinkedIn still writes. Reconstructed from Venice's write-path document, the Hoptimator README and the OpenHouse README.
Diagram source

The engine layer is rented, including the engines LinkedIn built

Kafka, Helix, Pinot, Samza and Gobblin all began at LinkedIn and now live at Apache. LinkedIn consumes them like everyone else, with one difference: it runs a patched fork of Kafka and says so plainly. The branch is "Apache Kafka trunk (upstream) up to some branch point", plus cherry-picks, plus "Patches that are on their way upstream but we have deployed internally in the meantime", plus "Patches that are of no interest to upstream".

Evidence: linkedin/kafka README, Helix releases 2013 to 2026

The semantic layer is owned, and ships constantly

Coral defines an intermediate representation for SQL "independently of any SQL dialect" and converts between HiveQL, Spark SQL and Trino SQL. It published 343 versions of its Trino module between April 2021 and September 2026, which is the highest release cadence of anything LinkedIn puts on Maven Central. Transport does the same for user-defined functions. Neither stores a byte.

Evidence: Coral README, coral-trino release listing

The serving layer is owned where no open equivalent exists

Two stores survived a decade of replacement: Venice, for data computed elsewhere and read by key, and Ambry, for "trillions of small immutable objects (50K -100K) as well as billions of large objects". Both have an ingestion shape that general-purpose databases handle badly: a full dataset swap from a grid job, and immutable blobs at media scale.

Evidence: Venice README, Ambry README

The control plane is the newest layer and the one that best explains the pattern. OpenHouse is described as "an open source control plane designed for efficient management of tables within open data lakehouse deployments", and its published contract is an HTTP API that puts Iceberg snapshots against a base table version. It does not own the table format; Apache Iceberg does. It owns the reconciliation loop: the README says OpenHouse "reconciles the observed state of Tables with the desired state by orchestrating various data services". Hoptimator sits one level further out and turns a CREATE MATERIALIZED VIEW statement into "running, multi-hop data pipelines that span Kafka, Flink, Venice, and anything else you plug in". Both are the same architectural bet: the durable asset is the description of what should be true, not the machinery that makes it true.

There is one honest complication, and it is expensive. Owning the layer above an engine does not keep you out of the engine. LinkedIn also maintains a fork of Iceberg whose repository description is simply "A home for LinkedIn's changes to Apache Iceberg", whose default branch is named openhouse-1.2.0, and which has published 85 versions to Maven Central since June 2022. On 28 August 2026 it published two of them, one on the 1.2.0 line and one on the 1.5.2 line, which means two supported forks of somebody else's format are alive at the same time. Nobody wrote that decision down anywhere public. The artefacts are the only record that it was made.

Figure 3 · The decade, measured in public release dates

2014201520162017201820192020202120222023202420252026Helix at Apache rest.li on Maven Central Gobblin at LinkedIn Samza at Apache Gobblin at Apache TonY Pinot at Apache Dagli Coral Trino module Transport UDF API Feathr LinkedIn Iceberg fork Venice public images Serving and frameworkDonated enginesSemantic and table layerMachine learningPublic release spans, from Maven Central listings
2014201520162017201820192020202120222023202420252026Helix at Apache rest.li on Maven Central Gobblin at LinkedIn Samza at Apache Gobblin at Apache TonY Pinot at Apache Dagli Coral Trino module Transport UDF API Feathr LinkedIn Iceberg fork Venice public images Serving and frameworkDonated enginesSemantic and table layerMachine learningPublic release spans, from Maven Central listings
Each bar runs from a component's first public release to its last, taken from Maven Central directory listings. The gap between rest.li's last artefact (2019) and its archive notice (2026) is the reason to read registries rather than repositories. Source: com.linkedin on Maven Central.
Diagram source
03

The decisions that matter

Four forks in the road, each one visible in an artefact with a date on it, and the condition that would flip the answer for a different organisation.

Decision: precompute and serve by key, or keep the data queryable at read time?

Chosen
  • Both, in two systems with different contracts. Venice serves values that a grid job or a stream processor already decided, by key. Pinot answers analytical queries over freshly ingested events.
  • Venice's five stated properties are all about ingestion shape rather than query power: batch and streaming ingestion, low-latency reads, active-active replication with CRDT conflict resolution, multi-cluster, multi-tenant.
Rejected
  • One store for both. Voldemort tried to be the read-only serving store and the read-write one, with "Pluggable storage engines, to cater to different workloads", and LinkedIn stopped running it in 2018.
  • Venice inherited most of the read-only use cases; the read-write ones only partly moved, according to the Voldemort notice.
Flips when
  • Your access pattern is not known at write time. If consumers arrive with unpredictable predicates, precomputing every answer is a combinatorial trap and the query engine wins.
  • Your dataset is small enough that a read-time scan is under budget, in which case one store is cheaper than two.

Decision: how many network hops should stay between the application and the bytes?

Chosen
  • Let the application choose, and publish the price list: two hops under 10ms, one hop under 2ms, zero hops under 1ms with the dataset resident in the process.
  • The stated reason the Fast Client is faster is not fewer packets but "eliminating an entire JVM from the hot path", which is why the next proposal removes the last one.
Rejected
  • A single canonical client. Venice's docs keep all three on the same read API precisely so the choice can be revisited per use case.
  • Caching in front of the router, which does not remove the garbage-collected hop that VIP-3 identifies as the tail-latency source.
Flips when
  • The dataset stops fitting on the application host, or the bootstrap time on a cold start exceeds your deployment budget. Embedding is a copy per process, and copies restart.
  • Write rates are high enough that every embedded replica pays the ingestion cost of the whole dataset.

Decision: keep a bespoke framework, or move to the industry standard?

Chosen
  • Move. Rest.li, LinkedIn's REST and JSON framework with type-safe bindings, was deprecated with the reason stated in the README: gRPC "will offer better performance, support for more programming languages, streaming, and a robust open source community".
  • The repository was archived read-only on 22 July 2026.
Rejected
  • Keeping it alive for external users. Issue #1178 says "We are not providing a drop-in replacement" and tells adopters to "plan to move to a framework that fits your needs".
  • A compatibility shim: gRPC is described as "a different model (binary RPC vs REST+JSON), not a direct migration path".
Flips when
  • The standard still lacks something your framework gives you. Rest.li's own list, backward-compatibility checking on every API change and a browsable API catalogue, is the part the replacement does not obviously carry.
  • Your migration cost exceeds the remaining maintenance cost. LinkedIn's answer was automation: the README describes "advanced automation to enable a seamless, LinkedIn-wide migration".

Decision: donate the component, transfer it, or keep it?

Chosen
  • Donate the general capability: Kafka, Helix, Pinot, Samza and Gobblin all went to Apache, and Helix is still publishing releases thirteen years later.
  • Keep the thing that encodes LinkedIn's own semantics: Coral, Transport, OpenHouse, Hoptimator, Venice, Ambry.
Rejected
  • Archiving as the exit route. Only four repositories in the whole organisation are archived, and one of them is a test repository.
  • Keeping the catalogue: DataHub moved to its own organisation and a company, and LinkedIn kept only the metadata model repository, datahub-gma.
Flips when
  • The component's value is in its ecosystem rather than its behaviour. A format or a protocol gains from donation; a serving system with one serious operator does not.
  • Nobody outside will staff it. Feathr went to a foundation in 2022 and stopped publishing artefacts in June 2023.
DecisionChosenRejectedBecauseEvidence
Storage engine ownershipServe derived data from an in-house storeA general-purpose key-value store for both derived and primary dataFull-dataset swaps and region-local CRDT replication are not ordinary database featuresVoldemort notice, 2018
Read-path shapeThree clients at two, one and zero hopsOne canonical clientLatency requirements differ by product surface, and the JVM hop dominates the tailVIP-3, under discussion
Serving runtimeProposal to rewrite the server read path in RustContinued JVM tuningTarget is a p99.99 under 1ms end to end, which garbage collection makes unpredictableVIP-3 problem statement
Table formatAdopt Apache Iceberg and fork itAn in-house formatInteroperability with Spark, Trino and Flink is the point of the format85 fork releases since 2022
Table governanceA declarative control plane over the formatExtending the catalogue inside each engineReconciliation must span engines that do not agree on anything elseOpenHouse Tables API spec
SQL portabilityOne intermediate representation, many dialectsStandardising on a single engineViews outlive engines, and rewriting them per migration is unbounded workCoral README
Change captureA multi-tenant streaming system with change capture as one connectorA dedicated change-capture productMirroring and capture share the same operational surface and fault isolation needsBrooklin README
PublicationShip the live system from a private repositoryPublishing Venice to Maven CentralNot stated anywhere public; the consequence is that the healthiest system leaves the weakest public trailVenice dependency instructions

Figure 4 · Where a derived dataset should live

no

yes

yes

yes

no

no

yes

no

Is the answer
known at write time?

Ingest events into an
OLAP store and query
at read time

Does one process need
the whole dataset?

Does it fit on local disk,
including bootstrap time?

Embed the dataset
in the process
(zero hops)

Route directly to the
partition owner
(one hop)

Is a 10ms budget
acceptable?

Read through a router
(two hops)

no

yes

yes

yes

no

no

yes

no

Is the answer
known at write time?

Ingest events into an
OLAP store and query
at read time

Does one process need
the whole dataset?

Does it fit on local disk,
including bootstrap time?

Embed the dataset
in the process
(zero hops)

Route directly to the
partition owner
(one hop)

Is a 10ms budget
acceptable?

Read through a router
(two hops)

The decision tree implied by Venice's client table and Pinot's role, with the terminal nodes stated as actions. Derived from the read-API comparison and the Pinot README.
Diagram source
04

What broke in production

LinkedIn publishes no postmortems for these systems. What exists instead is the defect record: five advisories and one abandoned pull request, which between them describe three failure classes an architect can plan against.

Read this before the cards

An advisory is not an incident report. It records what a defect made possible, who fixed it and when, and nothing about blast radius, detection time or whether anyone was hit. Every "blast radius" line below is therefore the exposure the defect created, not a measured impact. If a reader knows of a published LinkedIn postmortem for any of these systems, it belongs in this guide and I could not find one.

Class 1: the engine that assumed a trusted network

Advisory

The analytics engine ran scripts because that was the default

AssumptionAn OLAP store deployed behind the company firewall can safely accept a query language that includes a scripting escape hatch.
What happenedPinot shipped with "Groovy Function support enabled by default" on the query endpoint and the real-time ingestion path, which is code execution reachable by anyone who can send a query.
Blast radiusEvery deployment before 0.11.0, rated CVSS 9.8, no privileges and no user interaction required.
FixThe default was inverted in 0.11.0, with disabling Groovy offered as the workaround for anyone who could not upgrade.
Design ruleWhen an internal engine becomes a product surface, its defaults are now your security policy. Audit the defaults at the moment of promotion, not at the next review.
Advisory

Authentication depended on the shape of the path

AssumptionA path-based rule can decide which requests need credentials.
What happenedIn Pinot, "If the path does not contain / and contain., authentication is not required", so a request shaped to match that rule reached administrative functions, including adding accounts.
Blast radiusVersions 0.8.0 to before 1.3.0 of the broker, controller and common modules, rated CVSS 9.3.
FixCorrected in 1.3.0. The earlier 2024 advisory in the same family was fixed by introducing role-based access control in 1.0.0.
Design ruleAuthorisation that is computed from a string rather than from an identity will eventually be bypassed by a different string. Decide on the principal, not the route.
Advisory

The same default returned, wearing an AI tool interface

AssumptionA tool server that only exposes an existing engine inherits that engine's protections.
What happenedAn MCP server for Pinot defaulted to binding 0.0.0.0:8080 with authentication off, so any network-adjacent caller could invoke every tool, including schema creation and table mutation, using the server's own Pinot credentials.
Blast radiusVersions up to 3.0.1, rated CVSS 10.0, described as a confused-deputy path to full read and write access on the configured cluster.
FixPatched in 3.1.0.
Design ruleEvery new access layer over an old engine re-opens the default question. The agent tier in front of your data platform is a new front door, and it will ship with the same trusting defaults the platform had in 2015.
Advisory

The catalogue believed tokens it never verified

AssumptionA metadata service is a directory, so an authentication defect there is less serious than one in a database.
What happenedDataHub's token service parsed JSON Web Tokens without verifying their signature, accepting tokens regardless of algorithm, which let an attacker authenticate as any user.
Blast radiusAll versions before 0.8.45, rated CVSS 9.9. A catalogue knows where every dataset lives and who owns it, so the compromise is a map of everything else.
FixSignature verification added in 0.8.45.
Design ruleA control plane inherits the blast radius of everything it controls. Give the catalogue the same authentication review as the stores it indexes.

Class 2: the correctness fix that ran out of attention

Unmerged

A version swap that could drop records, closed after 37 days of silence

AssumptionSwapping a store from version N to version N+1 partition by partition is safe if each partition swaps when it sees the swap message.
What happenedA pull request against Venice's Da Vinci record transformer argued that consumers acted on swap messages from other regions, that re-pushed versions could replay older swap messages, and that the future version could consume past the swap point while the current one lagged. It proposed a coordinator that gates cutover until every partition has seen the message from every region.
Blast radiusUnknown in production. The change was gated behind a configuration flag defaulting to false, and the pull request was closed by automation with the comment "Closing this pull request due to 37 days of inactivity. This is not a judgment on the value of the work."
FixNone merged from this pull request as of 15 September 2026.
Design ruleA cutover between dataset versions is a distributed agreement problem, not a per-partition one. Write down who is allowed to swap first, and test the case where one side is ahead.
Artefact

The most-pulled image in the estate stopped moving two years ago

AssumptionA container image published under a large company's namespace is maintained for as long as the project is.
What happenedDataHub moved out of LinkedIn's namespace. The linkedin/datahub-gms image has 123,682,069 pulls and a last update of 2 April 2024; the live acryldata/datahub-gms image has 5,308,970 pulls and was updated on the day this guide was written.
Blast radiusAny deployment still resolving the LinkedIn-namespace tag is two and a half years behind on a component whose authentication defects are in the record above.
FixNone available in the old namespace; the fix is to repoint.
Design rulePin dependencies to a namespace you have verified is still the publishing one. A project transfer breaks no build and produces no error, which is exactly why it is missed.

Class 3: death without a notice

The third class is the one this method was built to find, and it has no advisory attached because nothing malfunctioned. Databus, LinkedIn's change-capture system with 3,700 stars, carries no deprecation banner of any kind; its successor Brooklin has been the published system for years, and a reader arriving at Databus today would find an ordinary repository. Feathr, the feature store LinkedIn open sourced in 2022 and placed under the LF AI and Data Foundation, still says in its README that it "is widely used in production at LinkedIn for many years", while its last Maven artefact is dated 30 June 2023. Venice's own README recommends Feathr as the feature store it backs. Dagli stopped at a beta in October 2021. TonY stopped in May 2022. None of them is archived, because only four repositories in the whole organisation are.

The design rule is mechanical and worth adopting: absence of an archive notice is not evidence of maintenance. The reliable signal is the registry, because publishing a release is an act somebody has to perform. Before adopting any component, look up its last release date on Maven Central, PyPI, npm, the Go proxy or Docker Hub, and compare that date with the last commit. A repository with recent commits and no release in two years is a project whose maintainers have moved on from shipping it to others.

Figure 5 · The swap race that the closed pull request describes

Consumer, partitionBConsumer, partitionAVersion topicPush jobConsumer, partitionBConsumer, partitionAVersion topicPush jobA serves N+1, B still serves Ncutover complete, one record shortpublish version N+1version swap messageswap message (region 1)swap to N+1, prefetchaheaddelayed by lagrecord past swap pointrecord discardedswap message arrives lateswap to N+1
Consumer, partitionBConsumer, partitionAVersion topicPush jobConsumer, partitionBConsumer, partitionAVersion topicPush jobA serves N+1, B still serves Ncutover complete, one record shortpublish version N+1version swap messageswap message (region 1)swap to N+1, prefetchaheaddelayed by lagrecord past swap pointrecord discardedswap message arrives lateswap to N+1
Two partitions swap independently, so a record written after the swap point on the fast partition is discarded while the slow partition is still serving the old version. Reconstructed from the description in Venice pull request 2795; no incident report confirms this occurred in production.
Diagram source
05

Numbers you can plan against

Everything quantitative in this guide, with the date it was true and the artefact it came from. Latency figures are documentation targets, not measurements taken by this author.

MetricValueAtContextAs ofSource
Query rate100k+ per secondLinkedInPinot, millisecond latency, 50+ user-facing products2026-09Pinot README
Kafka fleetthousands of brokersLinkedInDelivering trillions of messages per day on a patched fork2026-09linkedin/kafka README
Blob store scaletrillions of objectsLinkedInAmbry, objects of 50KB to 100KB plus billions of large ones2026-09Ambry README
Read latency, two hops< 10 msVeniceThin client through the router2026-09Venice read APIs
Read latency, one hop< 2 msVeniceFast client, partition-aware routing2026-09Venice read APIs
Read latency, zero hops< 1 msVeniceDa Vinci client, dataset resident in local RocksDB2026-09Da Vinci client doc
Tail-latency targetp99.99 < 1 msVeniceGoal of the proposed Rust read path, end to end at the client2026-09VIP-3
Public repositories135LinkedInOf which 4 are archived2026-09-15Archived listing
Maven Central presence36 artifact groupscom.linkedinNo venice directory among them2026-09-15Group listing
rest.li public release span2013-02-15 to 2019-12-17Maven Central34 versions, last is 27.7.182026-09-15restli-server listing
rest.li repository version29.85.15GitHubReleased 2026-06-29, 23 days before the archive date2026-09-15CHANGELOG
Coral release cadence343 versionsMaven Centralcoral-trino, 2021-04-09 to 2026-09-042026-09-15coral-trino listing
Iceberg fork releases85 versionsMaven Central2022-06-02 to 2026-08-28, two lines alive at once2026-09-15iceberg-core listing
Samza last release1.8.0, 2023-01-13ApacheStream processor donated by LinkedIn2026-09-15samza-core listing
Gobblin handover gap11 monthsMaven Centralcom.linkedin ends 2017-07-21, org.apache begins 2018-06-202026-09-15Apache listing
Feathr last release2023-06-30Maven Central78 versions from 2022-04-26; README still claims production use2026-09-15feathr listing
DataHub releases1,271PyPIacryl-datahub, 2021-04-02 to 2026-09-152026-09-15PyPI metadata
Frozen image pulls123,682,069Docker Hublinkedin/datahub-gms, last updated 2024-04-022026-09-15Docker Hub metadata
Venice image pulls4,320Docker Hubvenicedb/venice-router, registered 2022-09-242026-09-15Docker Hub metadata
Read these carefully

Measured by nobody here: every latency figure is a target published in project documentation, and no independent benchmark of Venice, Pinot or Ambry appears in this corpus. Stated by the operator: the Pinot, Kafka and Ambry scale figures are LinkedIn's own claims in README files, with no date attached beyond the day the file was checked, so treat them as order-of-magnitude and current. Derived here: the eleven-month Gobblin handover gap and the twenty-three-day interval between rest.li's last release and its archive date are arithmetic on dated listings. Unknown: cost, cluster sizes, node counts, replication factors, and the actual production latency distribution of any of these systems. Nothing public answers those.

06

The evidence wall

Twenty of the 55 sources behind this page, graded. The full ledger, with the quote supporting each claim, ships beside this file as sources.md. This corpus contains no conference talks, no papers and no engineering-blog posts, because the network policy in force during the research reached repositories and registries only; that limit is stated here rather than hidden.

Decision record LinkedIn2026-07

rest.li README deprecation banner

States the decision, the date the repository goes read-only, and the reason: gRPC for performance, more languages, streaming and a community. Also states that no drop-in replacement is offered.

Carry forwardA deprecation notice that names the replacement and refuses a shim is more useful to an adopter than a migration guide that pretends the models match.
raw.githubusercontent.com/linkedin/rest.li/master/README.md
Decision record LinkedIn2026-06-30

Issue 1178: rest.li is deprecated and will be archived

The announcement thread. Confirms artefacts stay on Maven Central, that issues and pull requests stop being accepted, and that adopters should choose their own replacement.

Carry forwardAsk a vendor or an upstream what happens to the artefacts, not just to the repository. Those are different promises.
github.com/linkedin/rest.li/issues/1178
Source LinkedIn2026-06-29

rest.li CHANGELOG, versions 29.85.x

The final year of a deprecated framework is xDS work: subscribing the discovery client to an observer cluster over xDS, and adding metrics that detect clients approaching gRPC's per-message size limit.

Carry forwardThe last commits to a dying framework tell you what replaced it. Read the changelog backwards to date a migration nobody announced.
raw.githubusercontent.com/linkedin/rest.li/master/CHANGELOG.md
Source Maven Central2019-12-17

com.linkedin.pegasus:restli-server version listing

Thirty-four versions, the first in February 2013 and the last in December 2019. The repository went on to 29.85.15. The public artefact trail ends seven years before the project does.

Carry forwardA registry directory listing is a dated decision log. It is the cheapest archaeology available and almost nobody runs it.
repo1.maven.org/maven2/com/linkedin/pegasus/restli-server/
Source LinkedIn2018

Voldemort README archive notice

Records the end of the Dynamo-style era in two sentences: production use stopped in 2018, read-only use cases moved to Venice, and only some of the read-write ones did.

Carry forwardWhen a store is replaced, the residue is the read-write workload. Plan the migration around the cases the successor was not designed for.
raw.githubusercontent.com/voldemort/voldemort/master/README.md
Source LinkedIn2026-09

Venice README and dependency instructions

Defines Venice as a derived data storage platform with batch and streaming ingestion, active-active CRDT replication and multi-tenancy, and tells consumers to add a separate artifact repository because it is not on Maven Central.

Carry forwardActive-active replication with CRDT conflict resolution is the feature that makes a derived store multi-region. Ask for it by name.
raw.githubusercontent.com/linkedin/venice/master/docs/README.md
Source LinkedIn2026-09

Venice read API comparison

Three clients, two, one and zero network hops, documented at under 10ms, under 2ms and under 1ms, all sharing get, batchGet and compute so a use case can move between them.

Carry forwardPublish the hop count next to the latency target. It makes the trade-off arguable by people who do not know the internals.
raw.githubusercontent.com/linkedin/venice/main/docs/user-guide/read-apis/index.md
Source LinkedIn2026-09

Da Vinci client documentation

The embedded option: eager load of the whole dataset into local RocksDB, zero network hops, and the stated costs of disk footprint and bootstrap on first launch.

Carry forwardBefore embedding a dataset in a service, measure cold-start bootstrap. It is the number that decides whether the design survives a deployment.
raw.githubusercontent.com/linkedin/venice/main/docs/user-guide/read-apis/da-vinci-client.md
Decision record LinkedIn2026-09

VIP-3: Rust Server Read Path

Proposes replacing the Java serving path with Rust to remove garbage collection, with a stated goal of p99.99 under 1ms end to end and a minimal scope of batch gets over gRPC and RocksDB. Justified by growth in AI workloads.

Carry forwardTail latency targets, not averages, are what justify a runtime change. State the percentile you cannot hit and the argument writes itself.
raw.githubusercontent.com/linkedin/venice/main/docs/contributing/proposals/vip-3.md
Decision record LinkedIn2026-09

Venice Improvement Proposals index

Six proposals, two accepted and four under discussion, covering authentication, per-record offset metadata, the Rust read path, lifecycle hooks, facet counting and Kubernetes.

Carry forwardAn open proposal list is the best available forecast of a dependency's next two years. Read it before adopting, not after.
raw.githubusercontent.com/linkedin/venice/main/docs/contributing/proposals/index.md
Source LinkedIn2026-08-05

Venice pull request 2795, closed unmerged

Describes three safety defects in per-partition version swap, including records discarded at the swap point, proposes a cross-region barrier, and is closed by a bot after 37 days without review.

Carry forwardSearch the unmerged pull requests of any system you depend on. They describe the failure modes the maintainers have heard about and not yet fixed.
github.com/linkedin/venice/pull/2795
Source LinkedIn2026-09

Venice write-path architecture note

Version topics and real-time topics on Kafka, ZooKeeper for metadata, Helix for partition assignment and leader election, one ingestion task per store per version.

Carry forwardA derived store is mostly a consumer. If you are designing one, the interesting decisions are in ingestion topology, not in the storage engine.
raw.githubusercontent.com/linkedin/venice/main/docs/contributing/architecture/write-path.md
Case study Apache2026-09

Apache Pinot README, LinkedIn production scale

States the query-side numbers: 50+ user-facing products, millions of events per second ingested, more than 100,000 queries per second at millisecond latency.

Carry forwardUser-facing analytics is a different workload from internal dashboards; concurrency, not query complexity, is the binding constraint.
raw.githubusercontent.com/apache/pinot/master/README.md
Advisory GitHub Advisory DB2022-09-25

GHSA-qj9p-jvmw-82rh: Groovy enabled by default in Pinot

Critical, CVSS 9.8, affecting every version before 0.11.0. Script execution reachable from the query endpoint and the ingestion path because the feature shipped on.

Carry forwardAudit the defaults of any engine you expose beyond the team that built it. Defaults are a security decision made by someone who did not know your network.
github.com/advisories/GHSA-qj9p-jvmw-82rh
Advisory GitHub Advisory DB2024-07-24

GHSA-8gj9-r4hv-3jjw: unauthorised endpoint exposed configuration

High, CVSS 8.7. Pinot's controller exposed operating system details, heap size and ZooKeeper paths on an endpoint anyone could reach; the fix was role-based access control in 1.0.0.

Carry forwardConfiguration endpoints are reconnaissance. Treat them as authenticated surface from the first deployment.
github.com/advisories/GHSA-8gj9-r4hv-3jjw
Advisory GitHub Advisory DB2025-04-01

GHSA-6jwp-4wvj-6597: authentication bypass by path shape

Critical, CVSS 9.3, versions 0.8.0 to before 1.3.0. A request whose path avoided a slash and contained a dot skipped authentication entirely, up to adding accounts.

Carry forwardPath-pattern authorisation is a parser problem in disguise. Decide access on an authenticated principal instead.
github.com/advisories/GHSA-6jwp-4wvj-6597
Advisory GitHub Advisory DB2026-05-25

GHSA-73cv-556c-w3g6: unauthenticated tool invocation in front of Pinot

Critical, CVSS 10.0. An MCP server defaulted to an open bind with authentication off, handing every tool, including table mutation, to any network-adjacent caller using the server's credentials.

Carry forwardThe agent layer in front of a data platform is a new privileged client. Give it the identity model you gave the platform, on day one.
github.com/advisories/GHSA-73cv-556c-w3g6
Advisory GitHub Advisory DB2022-10-28

GHSA-r8gm-v65f-c973: DataHub accepted unsigned tokens

Critical, CVSS 9.9. The metadata service parsed JSON Web Tokens without verifying signatures, so any user could be impersonated while authentication appeared to be on.

Carry forwardA catalogue is a map of every dataset and owner you have. Review its authentication as if it were the datastore itself.
github.com/advisories/GHSA-r8gm-v65f-c973
Source LinkedIn2026-09

linkedin/kafka README, the 3.0-li branch

Documents a production fork in four categories: upstream trunk to a branch point, cherry-picks, patches on their way upstream, and patches of no interest to upstream. External contributions are not accepted.

Carry forwardIf you fork an engine, classify each patch by whether it is going upstream. The fourth category is the one that decides whether you can ever stop forking.
raw.githubusercontent.com/linkedin/kafka/3.0-li/README.md
Decision record LinkedIn2026-09

OpenHouse Tables API specification

The control plane's published contract: an HTTP interface that applies Iceberg snapshots against a base table version, with the declarative catalogue reconciling observed state against desired state.

Carry forwardOwning the reconciliation loop over an open format is a cheaper long-term position than owning a format. Formats get standardised; policies do not.
raw.githubusercontent.com/linkedin/openhouse/main/docs/specs/catalog.md
Source Docker Inc2024-04-02

linkedin/datahub-gms image metadata

123,682,069 pulls, registered May 2020, last updated April 2024, against 5,308,970 pulls on the live acryldata image that was updated the day this guide was written.

Carry forwardContainer registry metadata dates a project transfer to the day, and shows how much of the world is still pointed at the old namespace.
hub.docker.com/v2/repositories/linkedin/datahub-gms/
Source Feathr, LF AI and Data2023-06-30

Feathr repository against its Maven release history

The README describes a platform "widely used in production at LinkedIn for many years" under a foundation; the last published artefact is from June 2023 and the repository is not archived.

Carry forwardCompare the README's tense with the registry's last date. When they disagree, the registry is right.
github.com/feathr-ai/feathr
07

Build a miniature, then productionise it

Six rungs. The first three are an evening each and teach the read-path trade-off by making you pay for it; the last three are where a toy becomes something you would put a product on.

Materialise a dataset behind a version topic

Compute a keyed dataset in a batch job, write it to a topic named for its version, and have a server consume the topic into a local embedded store. Serve reads by key.

Done when: a second batch run produces version 2 and a reader can still read version 1 throughout.  Teaches: why a derived store's unit of change is a dataset version, not a row.

Add the swap, then break it deliberately

Cut readers over from version 1 to version 2 partition by partition. Then delay one partition and write a record that arrives after the swap point on the fast partition.

Done when: you can demonstrate a key that is briefly missing or stale, and then fix it with a barrier that waits for every partition.  Teaches: the failure described in Venice pull request 2795, at a scale you can debug.

Remove a hop, and measure what you removed

Add a client that routes straight to the partition owner instead of through a router, then a client that keeps the whole dataset in-process. Record p50 and p99 for all three.

Done when: you have three latency distributions and a measured cold-start bootstrap time for the embedded client.  Teaches: that the hop you remove is often a runtime rather than a network round trip.

Put a nearline write path next to the batch one

Add a second topic for streaming updates applied on top of the batch version, with a rule for what happens when both touch a key. Give it a conflict resolution strategy you can state in one sentence.

Done when: a batch push does not erase nearline updates written during the push.  Teaches: why active-active derived stores reach for conflict-free data types rather than timestamps.

Declare the table, and let a control plane reconcile it

Move the dataset onto an open table format, then write a small service that accepts a declared desired state, such as retention or schema, and runs jobs until the observed state matches.

Done when: changing the declaration causes the reconciler to act without anyone running a job by hand.  Teaches: the OpenHouse position, that the durable asset is the description rather than the machinery.

Run the dependency audit on your own stack

For every third-party component you depend on, record the last release date from its registry, the last commit date, whether the namespace has changed hands, and the count of open advisories.

Done when: you can name the three dependencies whose registry has been quiet longest and say what you would do if each stopped tomorrow.  Teaches: the method this guide is built on, applied to your own risk.

08

Keep hunting

These are the searches and the fetches that produced this page. None of them needs a search engine, which is why they still work when a blog is offline or a network policy blocks it.

Dating a decision from artefacts

  • https://repo1.maven.org/maven2/com/<org>/
  • curl -s https://pypi.org/pypi/<package>/json | jq '.releases | keys'
  • curl -s https://registry.npmjs.org/<package> | jq '.time'
  • curl -s https://hub.docker.com/v2/repositories/<org>/<image>/
  • curl -s https://proxy.golang.org/github.com/<org>/<repo>/@v/list

Finding the decision the blog post never explained

  • github.com/orgs/<org>/repositories?q=archived%3Atrue&sort=updated
  • repo:<org>/<repo> is:pr is:closed is:unmerged sort:comments-desc
  • path:docs/contributing/proposals OR path:beps OR path:docs/adr
  • raw.githubusercontent.com/<org>/<repo>/master/CHANGELOG.md
  • raw.githubusercontent.com/<org>/<repo>/master/gradle.properties

Incident evidence when nobody publishes postmortems

  • github.com/advisories?query=<project>
  • github.com/<org>/<repo>/security/advisories
  • "enabled by default" advisory <project>
  • repo:<org>/<repo> is:issue label:bug sort:reactions-+1-desc

Vocabulary that unlocked this domain

  • "derived data" platform serving store
  • "version topic" OR "version swap" ingestion
  • "control plane" table lakehouse reconcile
  • "multi-hop" materialized view pipeline planner
  • xDS D2 discovery migration gRPC
09

References

  1. LinkedIn, rest.li README and deprecation banner GitHub, repository archived 2026-07-22. Checked 2026-09-15.
  2. LinkedIn, rest.li is deprecated and will be archived on July 22, 2026 (issue 1178) GitHub, opened 2026-06-30. Checked 2026-09-15.
  3. LinkedIn, rest.li CHANGELOG GitHub, last entry 2026-06-29. Checked 2026-09-15.
  4. LinkedIn, rest.li gradle.properties GitHub, master branch. Checked 2026-09-15.
  5. Maven Central, com.linkedin.pegasus:restli-server directory listing Sonatype, versions 2013-02-15 to 2019-12-17. Checked 2026-09-15.
  6. Maven Central, com.linkedin.pegasus:restli-client directory listing Sonatype. Checked 2026-09-15.
  7. Voldemort README, archive notice GitHub. Checked 2026-09-15.
  8. LinkedIn, Venice README GitHub. Checked 2026-09-15.
  9. LinkedIn, Venice read APIs GitHub. Checked 2026-09-15.
  10. LinkedIn, Venice Da Vinci client GitHub. Checked 2026-09-15.
  11. LinkedIn, Venice Improvement Proposals index GitHub. Checked 2026-09-15.
  12. LinkedIn, VIP-3: Rust Server Read Path GitHub, status under discussion. Checked 2026-09-15.
  13. LinkedIn, VIP-4: Store Lifecycle Hooks GitHub, status accepted. Checked 2026-09-15.
  14. LinkedIn, Venice write path GitHub. Checked 2026-09-15.
  15. LinkedIn, Venice pull request 2795, closed unmerged GitHub, closed 2026-08-05. Checked 2026-09-15.
  16. LinkedIn, Venice closed unmerged pull requests GitHub listing. Checked 2026-09-15.
  17. Apache Software Foundation, Apache Pinot README GitHub. Checked 2026-09-15.
  18. Maven Central, org.apache.pinot:pinot-core directory listing Sonatype, 2019-02-15 to 2026-06-04. Checked 2026-09-15.
  19. GitHub Advisory Database, GHSA-qj9p-jvmw-82rh (CVE-2022-26112) Published 2022-09-25. Checked 2026-09-15.
  20. GitHub Advisory Database, GHSA-8gj9-r4hv-3jjw (CVE-2024-39676) Published 2024-07-24. Checked 2026-09-15.
  21. GitHub Advisory Database, GHSA-6jwp-4wvj-6597 (CVE-2024-56325) Published 2025-04-01. Checked 2026-09-15.
  22. GitHub Advisory Database, GHSA-73cv-556c-w3g6 (CVE-2026-49257) Published 2026-05-25. Checked 2026-09-15.
  23. GitHub Advisory Database, GHSA-r8gm-v65f-c973 (CVE-2022-39366) Published 2022-10-28. Checked 2026-09-15.
  24. Docker Hub, linkedin/datahub-gms repository metadata Docker Inc. Checked 2026-09-15.
  25. Docker Hub, acryldata/datahub-gms repository metadata Docker Inc. Checked 2026-09-15.
  26. PyPI, acryl-datahub release metadata Python Software Foundation. Checked 2026-09-15.
  27. LinkedIn, linkedin/kafka README, branch 3.0-li GitHub. Checked 2026-09-15.
  28. LinkedIn, Ambry README GitHub. Checked 2026-09-15.
  29. LinkedIn, Coral README GitHub. Checked 2026-09-15.
  30. Maven Central, com.linkedin.coral:coral-trino directory listing Sonatype, 343 versions. Checked 2026-09-15.
  31. LinkedIn, OpenHouse README GitHub. Checked 2026-09-15.
  32. LinkedIn, OpenHouse Tables API specification GitHub, spec v0.1. Checked 2026-09-15.
  33. LinkedIn, Hoptimator README GitHub. Checked 2026-09-15.
  34. LinkedIn, Brooklin README GitHub. Checked 2026-09-15.
  35. LinkedIn, Databus repository GitHub, no deprecation notice. Checked 2026-09-15.
  36. LinkedIn, fork of Apache Iceberg GitHub, default branch openhouse-1.2.0. Checked 2026-09-15.
  37. Maven Central, com.linkedin.iceberg:iceberg-core directory listing Sonatype, 85 versions. Checked 2026-09-15.
  38. Feathr, LF AI and Data Foundation project repository GitHub. Checked 2026-09-15.
  39. Maven Central, com.linkedin.feathr directory listing Sonatype, last release 2023-06-30. Checked 2026-09-15.
  40. Maven Central, org.apache.samza:samza-core directory listing Sonatype, last release 2023-01-13. Checked 2026-09-15.
  41. Maven Central, org.apache.gobblin:gobblin-distribution directory listing Sonatype. Checked 2026-09-15.
  42. Maven Central, com.linkedin.gobblin:gobblin-core directory listing Sonatype. Checked 2026-09-15.
  43. Maven Central, org.apache.helix:helix-core directory listing Sonatype, 2013-01-09 to 2026-06-30. Checked 2026-09-15.
  44. Maven Central, com.linkedin.transport directory listing Sonatype. Checked 2026-09-15.
  45. Maven Central, com.linkedin group directory Sonatype, 36 artifact groups. Checked 2026-09-15.
  46. LinkedIn, public repository listing GitHub, 135 repositories. Checked 2026-09-15.
  47. LinkedIn, archived repository listing GitHub, 4 repositories. Checked 2026-09-15.
  48. npm, dustjs-linkedin package metadata npm Inc, 55 versions to 2021-12-29. Checked 2026-09-15.
  49. Go module proxy, github.com/linkedin/burrow version list Google. Checked 2026-09-15.
  50. Docker Hub, venicedb/venice-router repository metadata Docker Inc. Checked 2026-09-15.