> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inkwell.finance/llms.txt
> Use this file to discover all available pages before exploring further.

# Why CKKS fails at scale

> What the 257 s H100 parity failure actually means, the absolute noise floor in CKKS bootstrap chains, and why programmable-bootstrap is the correctness-preserving path.

> **CONFIDENTIAL & PROPRIETARY © 2026 Inkwell Finance, Inc. All Rights Reserved.**
>
> This document is for informational purposes only and does not constitute legal, tax, or investment advice, nor an offer to sell or a solicitation to buy any security or other financial instrument. Any examples, structures, or flows described here are design intent only and may change.

The Dagon matching graph is a tâtonnement bisection over an
encrypted order book. A bisection *has* to preserve correctness —
every step is a compare-and-narrow against the encrypted mid-price
estimate, and a decryption error of one tick anywhere in the chain
turns the clearing price into noise. Whichever FHE scheme runs this
graph must preserve the shadow-plaintext answer to within
sub-tick tolerance.

CKKS at the bootstrap chain depth this implies does not. This page
explains why, and what we do about it.

## What the 257 s number measures, and what it does not

We ran the high-precision tier of the production matching circuit
on an NVIDIA H100 SXM via a CUDA-backed CKKS library. The wall-clock
was **257 s**. That number is a faithful measurement of graph
throughput on that scheme-hardware combination, and it is
reproducible from a committed run log.

What it is not: a measurement of a correctly-clearing match.
Decryption after the bisection chain exceeds tolerance against the
plaintext shadow. The match compute finished; the match *answer* is
wrong.

This is why the benchmark matrix tags the cell **`⚠ measured, parity
FAILED`** and the rule in the [methodology](/dagon/performance/methodology)
document says *never cite 257 s without the failure mode inline*.

## The structural reason: CKKS's absolute noise floor

CKKS encrypts approximations. Every operation on a ciphertext adds
noise; every bootstrap operation cleans the accumulated noise back
down to a floor. That floor is not zero. Published CKKS bootstraps
add on the order of 5 × 10⁻³ of absolute noise per invocation, no
matter how much precision you start with.

Our bisection compares encrypted midpoints. As the chain progresses,
each iteration halves the bracket — by the time the chain is deep
enough to resolve to a sub-tick clearing price, accumulated
per-bootstrap noise exceeds the bisection's granularity. The deeper
the chain, the wider the gap between noise and signal becomes.

We did not invent this constraint. It is CKKS-fundamental: every
bootstrap invocation writes a noise floor that the downstream
operations inherit. Halving per-op noise doesn't close the gap.
Deeper rings don't close the gap. Cleverer scale-matching doesn't
close the gap. The scheme was built to approximate real-valued
computation at moderate depth; it does not preserve 17 rounds of
binary-search decisions.

What we tried before settling on this conclusion:

* **Rescaling strategy tuning.** Per-op rescale, delayed rescale,
  batched rescale. None close the error gap.
* **Scale matching across bootstrap boundaries.** Helped a few
  iterations, made later iterations worse.
* **Looser multiplicative-depth variants.** Pushes the failure a
  few steps further down the chain but doesn't avoid it.
* **Reduced-precision tier with shorter bisection chain.** Lighter
  in ops; still exceeds the noise floor at the required precision.

## Why programmable-bootstrap is the correctness-preserving path

Programmable-bootstrap FHE schemes work differently. Each
homomorphic primitive invokes one bootstrap cycle under the hood and
returns a refreshed ciphertext. There is no "chain depth" to manage.
The match at the end of the chain decrypts to the correct answer
because every intermediate step decrypts correctly.

This is the structural reason Dagon's production scheme is
programmable-bootstrap. It is not a performance argument — the
7.77 s headline is the performance argument — it is a correctness
argument. CKKS cannot clear the production matching circuit without
a chain-depth breakthrough that isn't on any published roadmap.

## What we cite, and how

The 257 s H100 CKKS number is a load-bearing data point in the
narrative — it's the concrete exhibit for "CKKS at scale has a
correctness problem that performance alone can't solve." It is
**always cited with the parity-failure qualifier**.

The 7.77 s TFHE-rs H100 N=32 number is the headline. Every output
was decrypted and compared to the plaintext expected value before
the number was cited.

Important scope note: the TFHE-rs benchmark runs a different
circuit shape than the CKKS 257 s number. The 7.77 s figure is the
measured floor for the TFHE primitive set on this workload — a
correctness-preserving anchor for the broader claim that
programmable-bootstrap is the right substrate.

## The one-line version

**Programmable-bootstrap preserves correctness at the chain depth
Dagon needs. Leveled CKKS does not.**

Every CKKS number on the benchmark page and the scaling dashboard is
tagged to flag that distinction. Every TFHE-rs number is
correctness-verified before it gets a citation.

## Related

<CardGroup cols={2}>
  <Card title="Benchmarks" icon="gauge" href="/dagon/performance/benchmarks">
    The headline scheme × hardware figures with correctness tags.
  </Card>

  <Card title="Methodology" icon="list-check" href="/dagon/performance/methodology">
    The four status tags and the rules for citing each.
  </Card>

  <Card title="Why FHE, not ZK" icon="eye-slash" href="/dagon/faq/why-fhe-not-zk">
    The broader architectural argument for FHE in the matching
    critical path.
  </Card>
</CardGroup>
