A Brief for Evaluation Prep · 2026

Graph thinking
& primitives.

Why Jane Street builds in nodes, edges, and small composable parts — and what changes about your reasoning when you do the same.

Subject
Engineering ethos & mental model
Form
Browser course, 9 chapters
Voice
KnuthOusterhout-Karpathy
Reading time
≈ 35 minutes, denser if you sit with it
Chapter One

The standard frame.

Most engineers learn graphs as a data-structures topic and then largely forget them outside of leetcode. That is the frame we have to leave behind first.

Open any algorithms textbook and a graph is a pair G = (V, E): vertices and edges, possibly directed, possibly weighted. You learn traversals, you learn shortest paths, you learn flows. You learn that a function is a thing that takes inputs and returns outputs, and that this is roughly orthogonal to the graph chapter.

This is a perfectly good frame for a class of problems — routing, scheduling, network analysis, dependency resolution. It is incomplete as a way to build software. The textbook treats the graph as the object of study: something you are given, something you query. Jane Street treats the graph as the shape of the program itself. That is the move.

What the textbook leaves implicit

Every program is, secretly, a directed graph. The dependencies between values form edges; the values and intermediate computations form nodes; the functions are the rewriting rules that say how outputs are derived from inputs. In imperative code we hide this graph behind statements, mutation, and control flow. In functional code we expose it — and once exposed, we can reason about it, optimize it, and incrementalize it.

Mental shift Stop asking "what does this function do?" Start asking "what value does this expression denote, and what does it depend on?" Programs become graphs of denotations. Execution becomes graph evaluation.

Why this matters before we go further

The standard frame produces engineers who write code in lines, debug in stack traces, and reason locally. The elevated frame produces engineers who write code as expressions, debug by reading types, and reason about dependencies. Jane Street's entire stack — language, libraries, review culture, even the trading systems themselves — is organized around the second.

Chapter Two

Graph as computation.

The single biggest conceptual move at Jane Street is to model the running program as a self-adjusting computation graph. This is what their Incremental library is.

A trading system, a risk dashboard, a pricing engine — all of these are long-running computations over rapidly changing inputs. The naïve approach is to recompute everything when any input changes. The clever approach is to recompute only what depends on what actually moved. Doing this by hand is tedious and bug-prone. Doing it with the wrong abstraction is worse. Doing it with a computation graph is, it turns out, the cleanest thing in the world.

Self-adjusting computation, developed academically by Umut Acar and collaborators in the early 2000s, became Incremental at Jane Street under Yaron Minsky. The model is small enough to hold in your head:

The win is not theoretical. Incremental is the substrate for production pricing tools, real-time risk monitors, and the firm's UI framework. Their distributed platform Webs uses the same idea to scale incremental recomputation to billions of nodes and edges, sitting somewhere between a spreadsheet and a pure functional DSL.

Self adjusting computations are essentially graph-structured computations that can be updated efficiently when their inputs change. Yaron Minsky, Jane Street blog

What this changes about your mental model

Once you internalize the graph-as-computation frame, the question "how do I update X when Y changes?" stops being an algorithm problem and becomes a graph construction problem. You describe the relationships once, declaratively, and the runtime handles propagation. This is the same move React made for the DOM, but generalized to every value in your program — and grounded in a type system strong enough that you cannot lie about your dependencies.

(* sketch of an Incremental computation, OCaml-flavored *)
let price  = Incr.var 100.0
let qty    = Incr.var 50
let fee    = Incr.var 0.001

let notional = Incr.map2 price qty ~f:(fun p q -> p *. Float.of_int q)
let cost     = Incr.map2 notional fee ~f:(fun n f -> n *. (1. +. f))

(* Move only `fee`. Only `cost` refires. `notional` is untouched. *)
Incr.Var.set fee 0.002

Notice what isn't here: no event handlers, no observers, no manual cache invalidation, no dirty flags. The dependency graph is the program. That is the elevation.

Chapter Three

The primitive discipline.

The second half of the ethos: instead of one big abstraction that bundles every concern, build small, sharp primitives that compose on demand.

The instinct in mainstream software engineering is to reach for a framework. A framework gives you a Component, which has state, which renders, which handles events, which probably has a lifecycle, which may also be reactive — all of it welded into one shape. Jane Street's instinct runs in the opposite direction: separate these concerns into independently composable primitives, and let the engineer assemble exactly the abstraction they need at the call site.

Their UI library Bonsai makes the contrast explicit. Most frameworks "lump together state, incrementality, and rendering into a single abstraction, the UI component." Bonsai instead exposes state, incrementality, and rendering as primitives you compose à la carte. The same primitive that prevents a re-render of a panel can be the primitive that caches an expensive business calculation on a live data feed. The primitive does not know it is for a UI; it knows it is for incremental state.

AThe framework instinct

One abstraction bundles state, rendering, lifecycle, effects, and incrementality.

Composition is by inheritance or by living inside the framework's tree.

You learn the framework's mental model before you learn your problem.

The framework decides what you can express; you negotiate the rest with workarounds.

BThe primitive instinct

Each concern is a small, total, type-safe primitive.

Composition is by function application: combine primitives like Lego.

You learn small parts, and the whole assembles from honest interfaces.

Whatever you can describe as a value, you can build, because primitives don't reach into you.

Why this is a moral position, not just a stylistic one

A framework asks you to surrender vocabulary. It says: speak in my nouns — Component, Effect, Store, Route — and your problem will be representable. A primitive asks you to keep your vocabulary and only borrow verbs from a well-designed library. The composition belongs to you. This matters because, in a trading firm, the cost of a bad abstraction does not show up in developer convenience surveys; it shows up in the moments when the abstraction is wrong and you cannot reach under it.

Ousterhout, on this A deep module has a narrow interface and a substantial implementation behind it. Jane Street's primitives are deep in exactly this sense: small surface, real work inside. The framework instinct produces the opposite — shallow modules with wide interfaces, which Ousterhout would call a complexity disaster.
Chapter Four · Interactive

A self-adjusting computation.

Move the sliders. Watch only the affected nodes recompute. Compare this against "rerun the whole program on any change," which is what most code does by default.

The graph below evaluates a tiny pricing expression: cost = (price · qty) · (1 + fee). The leftmost nodes are inputs; everything else is derived. Each time you change a slider, the system highlights exactly the nodes that actually had to refire. Pure functions plus dependency tracking buy you this automatically.

Live · Incremental sketch last fire
price 100.0 qty 50 fee 0.001 notional 5000 1 + fee 1.001 cost 5005
nodes total6
fired last update
total fires0
avoided recomputes0

The savings counter is the entire economic argument: a real Jane Street computation has thousands or millions of nodes, and the fraction that fires on any single tick is typically tiny. The graph encodes the structure once; the runtime exploits it forever.

Chapter Five

The ideology, examined.

Now the question that this whole brief exists to answer: why do they choose this over the obvious alternatives? It is not aesthetics. There are four reasons, in descending order of how often you will hear them said aloud.

  1. Risk control through readability. A trading firm can be ended by a tight loop making the wrong decision at speed. The earliest Jane Street response to this was that the founders themselves read every line of code into production. To make that scalable, code had to be readable. OCaml's type system, pure functions, and algebraic data types make the shape of a program legible at a glance; mutable, framework-laden code is not legible at a glance. The choice is not philosophical, it is operational.
  2. Composability multiplies a small team. Their technology group is small by design. Small teams cannot afford to reinvent abstractions, and they cannot afford the maintenance tax of monolithic frameworks. Composable primitives mean that each engineer's good idea becomes a piece every other engineer can reuse without negotiation. The economics of a primitives library compound; the economics of a framework do not.
  3. Incremental recomputation is the natural model for real-time data. Markets do not stop. Inputs change constantly. A program that recomputes everything on every tick is wasteful; a program that hand-rolls change-propagation is brittle. A self-adjusting computation graph is the right data structure for the job, the way a hash map is the right data structure for a lookup. Once you have the right structure, the engineering becomes ordinary.
  4. Types are a cheaper form of verification than tests. A type that says "this function takes a price and returns a quantity" rules out an infinite number of bugs at compile time. A test merely confirms that one specific input behaves correctly. In a domain where the cost of a missed bug is catastrophic, the asymptotic advantage of types compounds. Functional languages with strong, expressive type systems are simply more efficient at producing correct code per engineer-hour.
A summary, in one sentence Jane Street builds in graphs and primitives because risk is asymmetric, teams are small, data is live, and types are cheap.

The reasons you will not usually hear them say

Two more, which are equally true: this style of engineering attracts a certain kind of mind — mathematically inclined, fluent in abstraction, comfortable with rigor — and that selection effect is itself part of the moat. And: building your own primitives means owning your dependencies, which means surviving the bit-rot of other people's libraries for the multi-decade timescale on which a trading firm actually operates.

Chapter Six

Their artifacts.

The libraries below are the public face of the ethos. Each is worth studying as an answer to the question "what does it look like to build this idea seriously?"

01

Incremental

A library for self-adjusting computations. Define values as nodes in a directed graph; change inputs; the runtime recomputes only the affected subgraph. The substrate everything else stands on.

Core · open source
02

Bonsai

Their declarative UI framework, built on Incremental. State, incrementality, and rendering as separate composable primitives instead of one fused Component abstraction. Compiles a description into a running computation.

UI · primitives à la carte
03

Webs

Distributed spreadsheet meets pure functional DSL. Billions of nodes and edges, incremental recomputation under the hood, strong types on top. Used for pricing, risk, and dynamic analysis across the firm.

Scale · internal
04

JSQL

SQL-flavored query language with a uniform interface over in-memory OCaml data and database tables. The in-memory engine sits on Incremental, so queries stay current as data changes. Composability all the way down.

Query · incremental engine
05

Async

A monadic concurrency library. Cooperative, deterministic, threaded through the type system. Concurrency as a value you compose, not a runtime you negotiate with.

Concurrency · monad
06

Core / Async kernel

An alternative to the OCaml standard library, designed for the firm's needs. Total functions, clean signatures, no surprise mutation. The vocabulary the rest of the stack speaks.

Stdlib · vocabulary
Chapter Seven

Thinking in this idiom.

If you walk in with the standard frame, you will write standard answers. The following is how to translate, in real time, from leetcode-shape thinking to the shape Jane Street rewards.

When a Jane Street interviewer hands you a problem, they are not just checking that you can produce a correct answer. They are checking whether the shape of your thinking matches the shape of their codebase. The cheapest way to communicate that match is to talk in terms of values, dependencies, types, and composition — not loops, mutations, and ad-hoc state machines.

Translation Table · standard ⟶ jane street

"I'd use a for-loop" → "I'd express this as a fold or a map over the input collection."

"I'd cache that with a flag" → "That dependency should be its own node; I'd let the graph cut off propagation when the upstream value is unchanged."

"I'd inherit from a base class" → "I'd factor the shared behavior as a primitive and compose it where needed."

"I'd check that at runtime" → "I can encode that invariant in the type."

"I'd add another field to the component" → "I'd lift state out of the component and let it be addressed by a primitive."

The five questions to ask yourself, aloud, during the problem

  1. What are the values, and what are the dependencies between them?
  2. What is the smallest type that makes illegal states unrepresentable?
  3. Which parts of this need to be recomputed on which kind of change?
  4. What primitive am I implicitly assuming, and can I name it?
  5. If this needed to run for a year without restarting, what would break?

None of these will sound out of place. All of them communicate the right thing: that you are not just coding, you are reasoning about a system as a structure of dependencies, with types as the dominant tool for ruling out classes of failure.

A small but real tip If you do not know OCaml well, write your interview code in something type-rich that you do know — TypeScript with strict mode, Haskell, Rust, or even Python with rigorous typing. Sloppy types in any language will read as a sloppy mind in a Jane Street room.

A worked reframing

Suppose the prompt is: "given a stream of trades and a stream of mark prices, maintain the current PnL." The standard answer is a loop over events with a mutable PnL variable. The Jane Street answer is: model the trade stream and the mark stream as inputs; PnL is a derived node whose value is a function of the current positions (themselves a fold over the trade stream) and the current marks. Now ask which inputs cause which downstream nodes to refire; that is your incremental update story. You have not yet written code — and you have already communicated the entire mental model.

Sources

Read the originals.

Everything in this brief is paraphrased from public Jane Street material. To deepen, go to the sources directly — they are written carefully and they reward rereading.

  1. Functional Programming at Jane Street — index of internal libraries and applied research. janestreet.com/functional-programming/
  2. Technology at Jane Street — broader strokes on the engineering culture. janestreet.com/technology/
  3. "Introducing Incremental" — Yaron Minsky's announcement of the library. blog.janestreet.com/introducing-incremental/
  4. "Seven Implementations of Incremental" — tech talk on the history of the library. janestreet.com/tech-talks/seven-implementations-of-incremental/
  5. "Self Adjusting DOM" series — the move from Incremental to UI. blog.janestreet.com/self-adjusting-dom/
  6. Bonsai documentation — primitives-à-la-carte UI framework. bonsai.red
  7. "OCaml for the Masses" — Minsky's CACM essay on why Jane Street chose OCaml. dl.acm.org/doi/fullHtml/10.1145/2018396.2018413
  8. "A Consistent Semantics of Self-Adjusting Computation" — Acar et al., the academic foundation. arxiv.org/pdf/1106.0478
  9. Signals and Threads podcast — long-form conversations with Jane Street engineers. signalsandthreads.com
  10. Real World OCaml — the closest thing to a canonical text for the firm's idiom. dev.realworldocaml.org