> For the complete documentation index, see [llms.txt](https://docs.strikelabs.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.strikelabs.app/protocol/architecture.md).

# Architecture

Strike is two systems with one deliberate boundary between them: an off-chain matching engine that owns the market, and an on-chain vault that owns the money. Everything fast happens off-chain; everything that moves dollars in or out crosses the boundary explicitly, signed by the party that step belongs to.

## The system

```mermaid
flowchart LR
    T[Trader]
    M[Makers]
    F[Spot price quorum]
    subgraph venue [The venue]
        E[Edge — rate limits]
        W[Workers — parse, verify signatures]
        ENG[Engine thread — match, ledger]
        D[(WAL + snapshots)]
    end
    subgraph op [Operator daemons]
        DW[Deposit watcher]
        PB[Payout batcher]
    end
    V[(Arbitrum vault)]
    T -->|REST /v1| E
    E -->|WebSocket push| T
    M -->|token-gated quote endpoints| E
    E --> W --> ENG --> D
    F --> ENG
    T -->|deposit USDC| V
    V --> DW -->|credit, token-gated| E
    PB -->|commitBatch| V
    V -->|claim, your gas| T
```

The venue itself never touches the chain: it holds no RPC connection and no key. Separate operator daemons watch the vault for deposits and commit payout batches to it, and they reach the venue's ledger only through token-gated endpoints that no trader calls. The venue's job is the market; the chain's job is the money; the daemons carry messages between them.

## The matching engine

The engine is native Rust — price-time priority, integer micros end to end, no floating point anywhere money moves — and it answers in roughly a millisecond.

One thread owns all trading state, and every mutation and read runs on it, so there is no lock: a race on an account's cash that mints or loses money is structurally impossible, because there is exactly one writer and it is single-threaded. The business logic cannot be sharded by symbol anyway — margin is portfolio-level, so an account's positions across every symbol back one another and there is no clean boundary to cut.

What keeps one thread fast is everything that is *not* matching or ledger work happening off it, in parallel across workers: request parsing and signature verification before a job is submitted, response serialisation and the WAL fsync after it returns. The business thread does only in-memory matching and ledger arithmetic, which a single core does in the low microseconds.

## A write, end to end

```mermaid
sequenceDiagram
    participant C as Client
    participant W as Worker
    participant E as Engine thread
    C->>W: POST /v1/order — signed envelope
    W->>W: parse, verify the signature
    W->>E: submit job
    E->>E: match, update the ledger, append the WAL row
    E-->>W: result, plus the WAL sync handle
    W->>W: fsync the WAL
    W-->>C: ack — your updated account, echoed back
```

Every write echoes your full account back in the response, so there is nothing to poll after trading. A rejected order is not an error envelope — it comes back `400` with the normal order shape, `status: "rejected"` and a human-readable reason; [Errors](/api-reference/errors.md) lists every one.

## Durability

Fills and account credits are appended to a write-ahead log by the engine thread and fsynced before the acknowledgement leaves the venue. If the venue told you it happened, it happened — a crash a millisecond later replays it.

Snapshots are periodic and deliberately boring: the state is copied under the writer's control, encoded and written to disk off it, and the file lands atomically. The WAL rotates at the same instant as the copy, so the retired log holds exactly the events the snapshot contains — a fill landing during the write goes to the fresh log and survives either way. On boot the engine loads the last snapshot, then replays any log a crash left behind, oldest first.

## The clock

The book never closes — no opening auction, no halt, no weekend, no holiday calendar — but the venue keeps time. One maintenance timer runs three jobs, in an order that matters: **settle** first, so expired contracts stop counting toward anyone's margin; then **roll** the listings, so a board that just lost its front expiry has a new one; then **liquidate**, judging accounts on the state the first two left behind rather than on positions that no longer exist. [Market structure](/protocol/market-structure.md) has the cutoffs, the margin formulas, and what settlement pays.

## Prices

Spot prices come from a quorum of feeds and settlement prints are taken as a median, so no single feed can move the print. When the sources disagree or go quiet, the oracle **refuses to settle** rather than guessing — the refusal semantics, and the tightly bounded hand-settle path behind them, are on the [market structure](/protocol/market-structure.md) page, including an honest account of how independent the current sources actually are.

## The money boundary

```mermaid
flowchart LR
    A[Your wallet] -->|1 — deposit USDC, you sign| V[(Vault)]
    V -.->|2 — watcher credits, after confirmations| B[Venue balance]
    B -->|3 — withdraw request, session key signs| R[Payout requested]
    R -->|4 — operator commits the batch| V
    V -->|5 — claim, you sign, your gas| A
```

Five steps, and the party that signs each one is different — that is the design. The venue credits and debits trading balances; the vault holds the actual dollars; payouts reach the chain in operator-committed batches and are then claimable by you alone. This boundary is where the custody model lives, and the custody model is the part of Strike you should read most skeptically: it is **not a trustless exit**, and the [custody page](/protocol/custody.md) states exactly who can move what, including the parts that are awkward.

## Market data

Reads are plain JSON over HTTP, most of them unauthenticated: the listing universe, per-expiry chains, books, and the public tape. A WebSocket pushes the same state on a short tick — server-push only, no subscription protocol — including private fill and order streams for the authenticated account. The [WebSocket feed](/api-reference/streaming.md) page documents every frame on the wire.

## Makers

Market makers quote through their own token-gated endpoints — a quote board and quote sessions — rather than through the public order endpoint. Those routes are classified in [the contract](/api-reference/openapi.md) with the reason each is excluded from the public reference: excluded is not secret. Strike publishes no pricing logic, and none ships in the venue.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.strikelabs.app/protocol/architecture.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
