10 interesting stories served every morning and every evening.

Prefer STRICT tables in SQLite

evanhahn.com

In short: I pre­fer strict ta­bles in SQLite be­cause they avoid some datatype prob­lems, such as putting text in num­ber columns.

SQLite has a fea­ture that I think is un­der­rated: strict ta­bles. Strict ta­bles help en­force rigid typ­ing, pre­vent­ing mis­takes like putting text into in­te­ger columns. I like them, and wrote this post to pro­mote their use!

To make a strict table, add STRICT to the end of its de­f­i­n­i­tion. Like this:

-CREATE TABLE peo­ple (name TEXT); +CREATE TABLE peo­ple (name TEXT) STRICT;

That’s it! But what does it do?

Advantages of strict ta­bles

Broadly, strict ta­bles help en­force rigid types, like other SQL en­gines do.

Prevents type mis­matches on in­sert/​up­date

Most sig­nif­i­cantly, strict ta­bles keep you from in­sert­ing the wrong type into a col­umn. For ex­am­ple, SQLite nor­mally lets you put text into an INTEGER col­umn, but not with strict ta­bles.

– Non-strict ta­bles let you put any­thing any­where. CREATE TABLE peo­ple_non­strict (age INTEGER); INSERT INTO peo­ple_non­strict (age) VALUES (‘garbage’); — => works fine

– Strict ta­bles don’t al­low that, which I pre­fer. CREATE TABLE peo­ple_strict (age INTEGER) STRICT; INSERT INTO peo­ple_strict (age) VALUES (‘garbage’); — => er­ror: can­not store TEXT value in INTEGER col­umn

Personally, I think it’s a mis­take to try to put text in an in­te­ger col­umn, or vice-versa. I don’t want SQLite to let me make this er­ror!

The same val­i­da­tion hap­pens for UPDATEs, too.

Notably, if a value can be loss­lessly con­verted, it will still be ac­cepted. For ex­am­ple, the string 123’ can be per­fectly con­verted to an in­te­ger, so it’s al­lowed. These two lines are equiv­a­lent, even for a strict table:

INSERT INTO peo­ple_strict (age) VALUES (‘123’); INSERT INTO peo­ple_strict (age) VALUES (123);

Prevents bo­gus col­umn types on table cre­ation

By de­fault, you can cre­ate columns with bo­gus types. For ex­am­ple, all of these work even though they aren’t valid SQLite datatypes:

– SQLite does­n’t sup­port these types, but this is all ac­cepted. CREATE TABLE tbl (name GARBAGE); CREATE TABLE tbl (name DATETIME); CREATE TABLE tbl (name JSON); CREATE TABLE tbl (name UUID); CREATE TABLE tbl (name BLOBB);

I think these aren’t what the de­vel­oper in­tended. Some of these are ty­pos, some of them are mis­un­der­stand­ings of which datatypes SQLite sup­ports, and some are egre­gious mis­takes.

Appending STRICT to any of these state­ments makes them er­ror. In my opin­ion, that’s the cor­rect be­hav­ior!

– All of these give er­rors, which I pre­fer. CREATE TABLE tbl (name GARBAGE) STRICT; CREATE TABLE tbl (name DATETIME) STRICT; CREATE TABLE tbl (name JSON) STRICT; CREATE TABLE tbl (name UUID) STRICT; CREATE TABLE tbl (name BLOBB) STRICT;

Only INT, INTEGER, REAL, TEXT, BLOB, and ANY are al­lowed.

Strict ta­bles also re­quire a col­umn type, so you can’t do CREATE TABLE tbl (name).

Still al­lows flex­i­bil­ity with ANY

If you still need a col­umn to be flex­i­ble, you can use the ANY datatype. As the name sug­gests, it al­lows any­thing—even in a strict table.

CREATE TABLE tbl (value ANY) STRICT;

– All of these are valid be­cause the col­umn is ANY: INSERT INTO tbl (value) VALUES (123); INSERT INTO tbl (value) VALUES (‘text’); INSERT INTO tbl (value) VALUES (12.34); INSERT INTO tbl (value) VALUES (X′8647′);

I haven’t found a use for this, but maybe you will!

Disadvantages of strict ta­bles

I pre­fer strict ta­bles but I must share a few cons. Not every­thing is bet­ter!

Can’t strict-ify an ex­ist­ing table

I think it’s best to use strict­ness from the start, but that’s not al­ways pos­si­ble.

Unfortunately, I don’t think there’s a way to ALTER a table to make it strict. I think you have to copy the data out of the non-strict table into the strict one. Something like this:

– 1. Create a new strict table with the same schema CREATE TABLE new_peo­ple (name TEXT) STRICT;

– 2. Copy data (risky if types are wrong!) INSERT INTO new_peo­ple SELECT * FROM peo­ple;

– 3. Replace the old table DROP TABLE peo­ple; ALTER TABLE new_peo­ple RENAME TO peo­ple;

Note that this could be tricky if the non-strict table has in­valid data! For ex­am­ple, if the old data ac­ci­den­tally con­tains text in an in­te­ger col­umn, you’ll get er­rors when do­ing the mi­gra­tion. You’ll prob­a­bly need to clean the data or cast it.

You could make a rule for your code­base that all new ta­bles are strict. That might be use­ful—at least some of your ta­bles are valid! But it might also mean you have in­con­sis­tent val­i­da­tion across your ta­bles, which might be more sur­pris­ing than hav­ing weak val­i­da­tion on all ta­bles. It’s up to you to de­cide whether this is a good fit for you.

The SQLite de­vel­op­ers dis­agree with me

SQLite has a whole page called The Advantages Of Flexible Typing”, where they ar­gue that SQLite’s flex­i­ble be­hav­ior is good, ac­tu­ally.

I hes­i­tate to wade into the con­tro­versy of sta­tic-ver­sus-dy­namic, but I dis­agree in most cases. I’ve per­son­ally en­coun­tered many bugs where an un­ex­pected data type caused sub­tle headaches. I’d much rather these mis­takes ex­plode loudly. But it’s worth not­ing that SQLite’s de­vel­op­ers seem not to share my pref­er­ence for strict ta­bles!

They point out a few good uses for flex­i­ble ta­bles, such as a pure key-value store” or a place to store mis­cel­la­neous at­trib­utes” of dif­fer­ent types. They also men­tion that you might want to keep the in­valid data in some cases, like if you’re di­rectly im­port­ing a messy CSV and don’t want to lose any data. I still pre­fer strict ta­bles, but ac­knowl­edge there are some rea­son­able cases for non-strict ones.

(There’s also at least one com­ment in the SQLite source that calls non-strict ta­bles legacy”, but I trust that less than the of­fi­cial doc­u­men­ta­tion.)

Only in SQLite 3.37.0+

SQLite in­tro­duced strict ta­bles in ver­sion 3.37.0, re­leased November 2021. If you’re on an older ver­sion of SQLite, you can’t use strict ta­bles.

It’s worth not­ing that old ver­sions of SQLite can’t read data­bases with strict ta­bles. For ex­am­ple, if you cre­ate a strict table in the newest ver­sion of SQLite and then try to read that data­base in SQLite 3.36.0 (before strict ta­bles were added), you’ll get an er­ror—even if the strict table is al­ready in the data­base.

Performance maybe?

Strict ta­bles are the­o­ret­i­cally slower be­cause they have to do a lit­tle ex­tra work. For ex­am­ple, they check datatypes when do­ing an in­sert or up­date.

But in prac­tice, I don’t think this is an is­sue. I wrote a hacky script that in­serted mil­lions of rows into a table with 100 columns, and there was no ob­vi­ous dif­fer­ence on mul­ti­ple ma­chines I tried. The file size on disk was also the same. I did­n’t test this thor­oughly, so maybe there’s some­thing I missed, but I don’t think strict ta­bles pre­sent a per­for­mance prob­lem.

In fact, one might ex­pect bet­ter per­for­mance be­cause you won’t be ac­ci­den­tally mis­match­ing SQLite’s col­umn affini­ties. But again, I haven’t tested this.

Conclusion: I like strict ta­bles!

Personally, I think the pros of strict ta­bles out­weigh the cons.

I gen­er­ally pre­fer when types are rigidly en­forced. It squashes a class of mis­takes, and help en­force good data in­tegrity. They’re not a panacea, but they’re usu­ally easy to add and go a long way.

If there’s a SQLite fea­ture you think is un­der­rated, please tell me.

Female US rower completes historic solo journey from California to Hawaii

www.theguardian.com

A Grand Canyon river-raft­ing guide who aimed to be­come the first US woman to row solo across the mid-Pa­cific has com­pleted a record-break­ing jour­ney from California to Hawaii.

Hundreds of peo­ple gath­ered to cheer on Kelsey Pfendler as she pulled into a Honolulu har­bor on Friday night on her 21ft row­boat, Lily, af­ter nearly a month and a half at sea, lo­cal me­dia re­ported.

Pfendler, who launched from Monterey, California, in May, set out to be­come the first American woman, youngest woman and fastest woman to make the more than 2,400-mile (3,900km) jour­ney solo, ac­cord­ing to her web­site. Hundreds of thou­sands of peo­ple fol­lowed along with her jour­ney on so­cial me­dia, where she shared the highs, lows and quirks of her trek in videos taken as she bobbed alone on the vast ocean.

Pfendler ap­pears to have bro­ken both the pre­vi­ous wom­en’s speed record as well as the men’s speed record, ac­cord­ing to records main­tained by Ocean Rowing Society International, which ad­ju­di­cates ocean-row­ing achieve­ments for Guinness World Records. The or­ga­ni­za­tion did­n’t im­me­di­ately re­spond to re­quests for com­ment from the Associated Press about Pfendler’s fin­ish.

The row­ing so­ci­ety’s on­line records showed on Saturday morn­ing that Pfendler fin­ished in just un­der 44 days, faster than the pre­vi­ous com­pa­ra­ble fe­male record-hold­er’s 86 days or the male record hold­er’s 52 days as recorded by both the so­ci­ety and Guinness World Records.

Pfendler’s video di­aries ex­plained the lo­gis­tics of her pas­sage and sur­vival on the ocean. She de­tailed chal­lenges in­clud­ing blis­tered hands, the strug­gle to sleep amid stiff winds and the men­tal and phys­i­cal strug­gle of cop­ing with some­times-un­fa­vor­able cur­rents and wind.

She ex­plained how she cooked, pro­tected her skin from the sun, washed her clothes and made fresh wa­ter.

In some videos, her voice cracked with emo­tion. In oth­ers, she poked fun at her own fore­head hat tan line and joked about the im­por­tance of her caf­feine pills.

Pfendler’s web­site says she has been a pro­fes­sional raft guide since she was 18 and has spent the last eight years lead­ing trips along the Colorado River in the Grand Canyon.

I just love boats in the mid­dle of nowhere,” she said in one video.

Local news out­lets re­ported Pfendler was even­tu­ally ex­pected to ad­dress the me­dia. An emailed in­ter­view re­quest sent to Pfendler’s team was not im­me­di­ately re­turned.

In a re­cent video posted as she neared Oahu, she re­flected on the mean­ing of her ac­com­plish­ment and what she hoped oth­ers would take from it.

If any part of this made at least one per­son feel a lit­tle bit more pow­er­ful in their own skin, I could­n’t ask for any­thing else and I’m happy,” she said.

Think about try­ing to find your own big, hard, scary thing. You might not think that you are strong enough to fin­ish it right now, but you’re def­i­nitely strong enough to start it, and you’ll find every­thing else along the way. I’m go­ing to go fin­ish my big, hard scary thing.”

Pfendler’s ac­com­plish­ment came two days af­ter marathon swim­mer Catherine Breed be­gan a 900-mile swim, aim­ing to be­com­ing the first per­son to swim California’s en­tire coast.

Her goal is to swim five hours daily from the Oregon state line to Mexico’s bor­der, with the hopes of fin­ish­ing by November, the California news out­let SFist re­ported.

Guardian staff con­tributed re­port­ing

What xAI Grok Build CLI actually sends to xAI - a wire-level analysis (grok 0.2.93)

gist.github.com

What xAI Grok Build CLI ac­tu­ally sends to xAI - a wire-level analy­sis (grok 0.2.93)

A mea­sured, re­pro­ducible tear­down. Findings are backed by cap­tured ar­ti­facts (endpoint, HTTP method, sta­tus code, byte size, host) and re­pro com­mands; where an ob­ser­va­tion was seen live but not re­tained as a file, §7 says so ex­plic­itly. Section 8 is an ev­i­dence ap­pen­dix with SHA-256s and a what we did not prove” list. All cap­tures are of my own traf­fic on my own ma­chine, us­ing a throw­away repos­i­tory con­tain­ing fake canary” se­crets — no real cre­den­tials were ex­posed.

0. Summary

xAI’s of­fi­cial Grok Build cod­ing CLI (grok), on a nor­mal con­sumer lo­gin, does three things worth doc­u­ment­ing pre­cisely:

It trans­mits the con­tents of files it reads — in­clud­ing a .env se­crets file — to xAI, ver­ba­tim and unredacted. The se­cret ap­pears in two chan­nels: the live model turn (POST /v1/responses) and a ses­sion_s­tate archive up­loaded and ac­cepted (HTTP 200) via POST /v1/storage — the end­point the bi­nary routes to the grok-code-ses­sion-traces GCS bucket (see §5).

It up­loads the whole repos­i­tory — every tracked file’s con­tent plus git his­tory — in­de­pen­dent of what the agent reads. Grok pack­ages the work­space and up­loads it via POST /v1/storage. Proven di­rectly: on a real code­base, with the prompt reply OK, do not read any files”, Grok up­loaded the en­tire repo as a git bun­dle (POST /v1/storage → 200); git clone-ing the cap­tured bun­dle re­cov­ers a file the agent was told not to open — src/​_probe/​nev­er_read­_­ca­nary.txt — with its unique marker ver­ba­tim, plus the full git his­tory (appendix up­loaded_repo.bun­dle). And it scales: on a 12 GB repo of never-read ran­dom files, /v1/storage moved 5.10 GiB, all HTTP 200 (truncated mid-stream), while the model-turn chan­nel moved just 192 KB — a ~27,800× ra­tio that pins the up­load to the code­base, not to what was read. No stor­age up­load failed; the only non-200s were a model-us­age quota (402/429) on /v1/responses and one un­re­lated 404 — not a stor­age size cap.

The stor­age des­ti­na­tion is a Google Cloud Storage bucket, grok-code-ses­sion-traces (not AWS S3) — named ver­ba­tim in the bi­nary and in a cap­tured meta­data.json (gs://grok-code-session-traces/…). I did not find this mech­a­nism sur­faced in the CLIs in­stall/​quick­start ma­te­ri­als (not an ex­haus­tive docs au­dit — §7), it is ac­tive by de­fault, and dis­abling Improve the model” does not turn it off (/v1/settings still re­turned trace_u­p­load­_en­abled: true; §6).

None of this proves xAI trains on the data — that is a pol­icy ques­tion ad­dressed in §6. What is proven is trans­mis­sion, ac­cep­tance, and stor­age.

1. Subject un­der test (provenance)

Install: curl -fsSL https://​x.ai/​cli/​in­stall.sh | bash # → ~/.grok/bin/grok Auth: first launch opens a browser → lo­gin to X / SuperGrok (consumer ac­count, not an API key)

Binary iden­tity (repro: file $(readlink -f ~/.grok/bin/grok); ~/.grok/bin/grok –version; sha­sum -a 256 $(readlink -f ~/.grok/bin/grok)):

~/.grok/bin/grok -> ../downloads/grok-macos-aarch64 Mach-O 64-bit ex­e­cutable ar­m64 grok 0.2.93 (f00f96316d4b) SHA-256: 2a97ba675bd992aa9b981e2e83776460d94f469b510c0b8efe28b50d236d767c

The up­load ma­chin­ery is a first-party Rust crate. strings on the bi­nary yields these source paths and con­stants (repro: strings <binary> | grep -E xai-data-collector|grok-code-session-traces|storage.googleapis’):

crates/​code­gen/​xai-data-col­lec­tor/​src/​gcs.rs crates/​code­gen/​xai-data-col­lec­tor/​src/​stor­age_­client.rs crates/​code­gen/​xai-data-col­lec­tor/​src/​queue.rs crates/​code­gen/​xai-data-col­lec­tor/​src/​file_ac­cess_­tracker.rs crates/​code­gen/​xai-data-col­lec­tor/​src/​cir­cuit_break­er_ob­server.rs crates/​code­gen/​xai-grok-shell/​src/​up­load/{​gcs,turn,trace,man­i­fest}.rs grok-code-ses­sion-traces stor­age.googleapis.com Uploading bytes to GCS via proxy”

2. Method (reproducible)

Environment: ma­cOS, Apple Silicon, grok 0.2.93, July 2026.

brew in­stall mitm­proxy; run once to gen­er­ate its CA at ~/.mitmproxy/.

Trust the CA in the lo­gin key­chain (no sudo; Grok does not cer­tifi­cate-pin against it): se­cu­rity add-trusted-cert -r trust­Root -k ~/Library/Keychains/login.keychain-db \ ~/.mitmproxy/mitmproxy-ca-cert.pem

se­cu­rity add-trusted-cert -r trust­Root -k ~/Library/Keychains/login.keychain-db \ ~/.mitmproxy/mitmproxy-ca-cert.pem

Run Grok routed through the proxy (a mit­m­dump ad­don logs, per re­quest: method, host, path, re­sponse sta­tus, re­quest byte size; and saves re­quest bod­ies for xAI hosts): HTTPS_PROXY=http://​127.0.0.1:8080 SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem \ grok -p <prompt>” –cwd <repo>

HTTPS_PROXY=http://​127.0.0.1:8080 SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem \ grok -p <prompt>” –cwd <repo>

For staged-ar­ti­fact in­spec­tion, race-copy ~/.grok/upload_queue/* dur­ing the run, then gzip -dc | tar -xO.

Canary repo: each file car­ries a unique marker so any­thing ap­pear­ing in cap­tured traf­fic is un­am­bigu­ously trace­able to a file. Secrets file se­crets.env / .env:

API_KEY=CANARY7F3A9-SECRET-should-not-leave DB_PASSWORD=CANARY7F3A9-DBPASS

3. Finding 1 — File con­tents, in­clud­ing a se­crets file, are trans­mit­ted and ac­cepted (200)

Claim: when Grok reads a file, its con­tents are trans­mit­ted to xAI — se­ri­al­ized into the POST /v1/responses model-turn body, and pack­aged into a ses­sion_s­tate archive that is up­loaded and ac­cepted (HTTP 200) via POST /v1/storage — with no redac­tion of the file’s con­tents. A .env is sent like any other file.

Wire ar­ti­fact — a de­crypted 48,070-byte POST cli-chat-proxy.grok.com/​v1/​re­sponses re­quest body (identifiable as a model turn by its em­bed­ded messages”:[…]“model”:“grok-4.5” JSON). It con­tains the se­crets file ver­ba­tim (appendix: se­cret­s_re­spons­es_­body.bin, se­cret_ver­ba­tim.txt):

…API_KEY=CANARY7F3A9-SECRET-should-not-leave\nDB_PASSWORD=CANARY7F3A9-DBPASS\n…“model”:“grok-4.5″…

Repro: grep -a CANARY7F3A9-DBPASS” se­cret­s_re­spons­es_­body.bin → matches. All six file mark­ers (source, logic, README, nested JS, API key, DB pass­word) are re­cov­er­able from the de­crypted /v1/responses bod­ies. (This ar­ti­fact proves the se­cret was trans­mit­ted to the /v1/responses end­point; the raw body file does not carry the re­sponse sta­tus, so the ac­cep­tance (200) claim is an­chored to the /v1/storage chan­nel im­me­di­ately be­low, which is sta­tus-mapped in wire_12gb.log.)

Second chan­nel — per­sisted to Google Cloud Storage. The same con­tent is pack­aged into a ses­sion_s­tate archive up­loaded via POST /v1/storage. Proven by de­com­press­ing the staged ar­ti­fact be­fore it drains (appendix: se­cret­s_ses­sion_s­tate.tar.gz):

gzip -dc se­cret­s_ses­sion_s­tate.tar.gz | tar -xO | grep -ao CANARY7F3A9-[A-Z]*’ → CANARY7F3A9-SECRET, CANARY7F3A9-DBPASS, + all oth­ers

So the se­cret is not only processed in-flight; it is writ­ten into an archive des­tined for stor­age.

Pre-empting you told it to read the se­crets.” A con­trol run with a file the agent was told not to open (untouched_secret.txt) and the prompt Reply ex­actly OK, do not read any files” pro­duced no oc­cur­rence of that file’s marker in any cap­tured body. The leak is there­fore scoped to files Grok does read — but it reads lib­er­ally (any file rel­e­vant to the task, in­clud­ing a .env) and ap­plied no redac­tion to that file’s con­tents. The de­fect is that a se­crets file was trans­mit­ted unredacted, not the act of read­ing. Important scope rec­on­cil­i­a­tion: this con­trol shows the un­read file is ab­sent from the /v1/responses bod­ies — that is Channel A (files the agent reads). It does not clear the sep­a­rate whole-repo /v1/storage snap­shot in §4 (Channel B), which — by the vol­ume ev­i­dence there — does sweep in never-read files; I could not de­com­press the /v1/storage code­base chunk to check this spe­cific file. So unread file not up­loaded” is true only for the model-turn chan­nel, not for the code­base snap­shot. (Two fur­ther scope notes: (i) in my runs the .env/secrets.env was git-tracked; I did not sep­a­rately test whether a .gitignored file is still up­loaded, so I make no git­ig­nore claim — the mech­a­nism is read-dri­ven per the file_ac­cess_­tracker crate, but that spe­cific case is untested. (ii) The ca­nary val­ues sat in API_KEY=/DB_PASSWORD= keys in­side a .env/secrets.env but were not real-for­mat high-en­tropy to­kens; I proved this .env was trans­mit­ted unredacted, not that no redac­tor ex­ists for, say, an sk-…-shaped key.)

4. Finding 2 — The whole repo is up­loaded at multi-GB scale; the only ceil­ing is a model quota, not stor­age size

Claim: Grok up­loads a whole-repo snap­shot with no stor­age size wall in the tested range. As the repo grows it switches up­load strat­egy and keeps re­turn­ing 200; on a 12 GB repo, 73 chunks of ~75.0 MB (5.10 GiB) up­loaded with zero fail­ures be­fore the cap­ture was trun­cated mid-stream.

Wire-captured size sweep (incompressible con­tent so the tar can­not shrink; fresh ses­sion each step). Only the 12 GB row was re­tained as a file (wire_12gb.log); the smaller rows were ob­served live dur­ing the sweep but their logs were not saved (see §7):

Preserved ar­ti­fact: wire_12gb.log (appendix). It con­tains 83 /v1/storage* 200 re­sponses: 82 con­tent-up­load POST …/v1/storage re­quests — of which 73 are chunks of ~75.0 MB each (byte sizes min 75,014,811 / max 75,014,871, to­tal­ing 5,476,083,317 B = 5.10 GiB / 5.48 GB) plus 9 smaller POSTs — and 1 /v1/storage/batch_exists dedup check. Total /v1/storage* re­quest bytes: 5,476,228,005 B. Zero stor­age re­quests failed. The cap­ture was stopped while up­loads were still stream­ing (the last line is an­other ~75 MB chunk → 200), so this demon­strates ≥5.1 GiB up­loaded, still climb­ing when trun­cated — not that the full 12 GB com­pleted. Repro (three greps, so no count is am­bigu­ous): grep cli-chat-proxy.grok.com/​v1/​stor­age wire_12gb.log | grep -c > 200’ → 83 (all /v1/storage*); grep POST cli-chat-proxy.grok.com/​v1/​stor­age wire_12gb.log | grep -c > 200’ → 82 (content POSTs only); grep req=75014 wire_12gb.log | grep -c > 200’ → 73 (the ~75 MB chunks).

Scope — this is the whole repo, not just files the agent read. Channel A (§3, /v1/responses) car­ries files the agent opens. This §4 up­load is a sep­a­rate Channel B: a snap­shot of the en­tire work­space. Two lines of ev­i­dence:

(a) The de­ci­sive byte split (load-bearing). In the same cap­tured 12 GB ses­sion — a repo of 100 % ran­dom files the agent never read — the two chan­nels moved wildly dif­fer­ent vol­umes:

Channel A /v1/responses (model turns): 196,705 B = 192 KB to­tal, across 5 re­quests, largest sin­gle turn 60,394 B. Channel B /v1/storage: 5,476,228,005 B = 5.10 GiB. That is a ~27,800× ra­tio (5,476,083,317 ÷ 196,705). The model demon­stra­bly never in­gested the files (192 KB can­not carry 5 GiB of con­tent), yet 5.10 GiB of them left via /v1/storage — and across the sweep the /v1/storage vol­ume tracks to­tal repo size (64 MB → 12 GB). GB-scale bytes leav­ing a never-read repo can only be a whole-repo snap­shot.

Channel A /v1/responses (model turns): 196,705 B = 192 KB to­tal, across 5 re­quests, largest sin­gle turn 60,394 B.

Channel B /v1/storage: 5,476,228,005 B = 5.10 GiB.

That is a ~27,800× ra­tio (5,476,083,317 ÷ 196,705). The model demon­stra­bly never in­gested the files (192 KB can­not carry 5 GiB of con­tent), yet 5.10 GiB of them left via /v1/storage — and across the sweep the /v1/storage vol­ume tracks to­tal repo size (64 MB → 12 GB). GB-scale bytes leav­ing a never-read repo can only be a whole-repo snap­shot.

(b) The bi­na­ry’s own paths/​strings cor­rob­o­rate the mech­a­nism: af­ter_­code­base.tar.gz, xai-grok-shell/​src/​up­load/{​trace,turn}.rs, re­po_s­tate.up­load, collecting work­space files”, spawning back­ground co­or­di­na­tor”.

(c) A staged code­base man­i­fest enu­mer­ates a never-read file and con­tent-ad­dresses it to the GCS bucket. In a sep­a­rate run on a real 298-file cere­blab_api code­base, I race-copied the snap­shot Grok staged for up­load (appendix: staged_base_tree_­man­i­fest.json, staged_meta­data.json). The man­i­fest lists src/​_probe/​nev­er_read­_­ca­nary.txt — a file I planted and never asked Grok to open — along­side the real sources (src/apns.ts, src/​in­dex.ts, …); and meta­data.json gives each file a des­ti­na­tion fileId of the form gs://​grok-code-ses­sion-traces/​re­po_changes_d­edup/​v2/​sup­ple­men­tal/​sha256_…. So the whole tree, un­read files in­cluded, is enu­mer­ated and con­tent-ad­dressed for up­load to the named GCS bucket. (That run was quota-blocked be­fore the con­tent blobs up­loaded; the 12 GB run above in­de­pen­dently proves GB-scale con­tent ac­tu­ally leaves the wire, all 200.)

(d) DEFINITIVE — a never-read file’s con­tent re­cov­ered ver­ba­tim from an up­loaded git bun­dle (single SuperGrok run). With the ac­count up­graded (quota lifted), I re-ran on the real cere­blab_api repo with the ex­plicit prompt Reply with ex­actly: OK. Do not read or open any files., hav­ing planted a unique marker CANARY-XR47P2-NEVERREAD-UNIQUE in src/​_probe/​nev­er_read­_­ca­nary.txt. Grok up­loaded the en­tire repos­i­tory as a git bun­dle via POST cli-chat-proxy.grok.com/​v1/​stor­age → 200 (req=152102b) (appendix up­loaded_repo.bun­dle, SHA-256 73b9c0af06311bae35c3ed03274d0eec2846e76762828d10b09757ca41bd6024). Running git clone up­loaded_repo.bun­dle re­con­structs the repo, and src/​_probe/​nev­er_read­_­ca­nary.txt con­tains the marker ver­ba­tim — a file the agent was ex­plic­itly told not to open. The bun­dle also car­ries the full git his­tory (4 com­mits, 47 files). This is the air­tight per-file-con­tent proof: the whole repo — un­read files in­cluded — left the ma­chine and was ac­cepted (200). The up­load mech­a­nism is a git bun­dle, so whole repo” is lit­eral (every tracked file + his­tory). Replicated on a sec­ond, un­re­lated code­base: the iden­ti­cal cap­ture on the cere­blab_auth Cloudflare-Worker repo pro­duced a git-bun­dle up­load (POST /v1/storage → 200, 31,743 B) from which git clone re­cov­ered its own never-read marker CANARY-AUTH-4T8K2-NEVERREAD ver­ba­tim (appendix up­loaded_re­po_auth.bun­dle, SHA-256 0ee536538bcd1ee72a258f9977ab69f8a9b1ac240491b91a4e94335b4d83c768). Two in­de­pen­dent re­pos, same re­sult.

(Prompt note: the 12 GB ses­sion was in­ter­ac­tive and I did not log its ver­ba­tim prompt, but the 192 KB Channel-A to­tal is dis­pos­i­tive that no bulk read oc­curred what­ever the prompt was; a sep­a­rate head­less con­trol run used the ex­plicit prompt Reply ex­actly OK, do not read any files and con­firmed an un­read file is ab­sent from Channel A.)

(The ear­lier one gap” is now closed by ev­i­dence (d): a sin­gle SuperGrok run where a spe­cific never-read file’s con­tent is re­cov­ered from a wire-cap­tured, 200-status git-bun­dle up­load. The 12 GB run re­mains the proof that this scales to GB vol­umes.)

No stor­age/​up­load re­quest failed — every one of the 82 /v1/storage calls re­turned 200. The only non-200s in the en­tire cap­ture were on the model end­point plus one ses­sion-book­keep­ing call (full set from wire_12gb.log; /v1/responses lines also in mod­el_limit.txt):

POST /v1/responses -> 402 (Payment Required) ×1 POST /v1/responses -> 429 (Too Many Requests) ×3 POST /v1/sessions/<id>/replicas/update -> 404 ×1 (session book­keep­ing, not an up­load)

and fi­nally, in plain text, on std­out:

You’ve reached your free Grok Build us­age limit for now. Get SuperGrok for much higher lim­its…

The 402/429 are a model-us­age quota; the lone 404 is un­re­lated to stor­age. Notably, stor­age up­loads con­tin­ued to re­turn 200 af­ter the model turn was rate-lim­ited (76 /v1/storage 200s oc­cur at or af­ter the first 429) — the code­base up­load is in­de­pen­dent of whether the model an­swers.

Pre-empting you’re con­fus­ing a lo­cal disk cache with an up­load.” This claim rests strictly on wire-cap­tured 200-status up­loads of file bytes leav­ing the ma­chine (/v1/storage re­quest bod­ies of 7.5 – 75 MB in the pre­served wire_12gb.log; the 3 GB 50 MB PUTs to stor­age.googleapis.com were also seen on the wire, but that log was not re­tained — §7). It does not rely on the ~/.grok/upload_queue drain­ing — queue-drain is am­bigu­ous (it emp­ties on both suc­cess and drop) and is ex­plic­itly not used as ev­i­dence here. (An ear­lier draft that in­ferred up­load from queue-drain was wrong and has been re­tracted; see §7.)

5. Finding 3 — Destination, teleme­try, and what’s not sur­faced in the docs

Storage des­ti­na­tion is Google Cloud Storage, bucket grok-code-ses­sion-traces. This rests on the pre­served bi­nary strings grok-code-ses­sion-traces, stor­age.googleapis.com, and Uploading bytes to GCS via proxy” (crate_strings.txt), and on a pre­served staged meta­data.json whose per-file fileIds are lit­er­ally gs://​grok-code-ses­sion-traces/​re­po_changes_d­edup/​v2/…/​sha256_… (staged_metadata.json), cor­rob­o­rated by the di­rect stor­age.googleapis.com mul­ti­part PUTs ob­served at 3 GB (observed live; that log was not re­tained — see §7). It is not AWS S3 (the bi­nary links aws-sdk-s3 for an al­ter­nate path and AWS STS/SSO for auth, but the des­ti­na­tion named in the bi­nary — and seen on the wire at 3 GB — is GCS).

Third-party teleme­try: POST api.mix­panel.com/​track and /engage (Mixpanel), plus POST grok.com/​_data/​v1/​events — all 200.

Not sur­faced in setup docs (scope-limited claim): I did not find the re­po_s­tate / ses­sion_s­tate up­load to grok-code-ses­sion-traces, or the ~/.grok/upload_queue stag­ing, de­scribed in the CLIs in­stall script or quick­start ma­te­ri­als I re­viewed (this is not an ex­haus­tive au­dit of all xAI docs — see §7). The mech­a­nism is ac­tive by de­fault on the stan­dard con­sumer lo­gin.

Reliability note (separate from pri­vacy): ~/.grok/upload_queue stages ~3 GB snap­shots per turn and, un­der load, can grow to tens of GB and ex­haust the disk. This is a real bug, in­de­pen­dent of whether up­loads suc­ceed.

6. Consent and pol­icy — stated hon­estly

Cloud AI tools send con­text; this is nor­mal.” True, and con­ceded: any cloud cod­ing agent must send code to its server to act on it. The novel deltas here are (a) a se­crets file (e.g. .env) is trans­mit­ted unredacted, (b) the con­tent is per­sisted to a named GCS bucket, not just processed tran­siently, and (c) the up­load mech­a­nism is not sur­faced in the CLIs setup ma­te­ri­als (§7) and on by de­fault.

It’s in the ToS / opt-in.” xAI’s con­sumer pol­icy broadly dis­closes data use for model im­prove­ment with an opt-out (grok.com → Settings → Data → Improve the model”; Private Chat auto-opts-out; opt-out is prospec­tive, not retroac­tive). But broad train­ing dis­clo­sure ≠ doc­u­ment­ing this spe­cific mech­a­nism. I did not find the re­po_s­tate/​up­load­_queue/​grok-code-ses­sion-traces pipeline de­scribed in the CLI ma­te­ri­als I re­viewed (§7 notes this is not an ex­haus­tive docs au­dit), so — on those ma­te­ri­als — a user is not in­formed of it specif­i­cally. Sources: xAI Privacy Policy (https://​x.ai/​le­gal/​pri­vacy-pol­icy), Consumer ToS (https://​x.ai/​le­gal/​terms-of-ser­vice).

The Improve the model” tog­gle makes no dif­fer­ence — ON or OFF, the whole repo is up­loaded the same way. At de­fault set­tings, Grok up­loaded 5.10 GiB of a never-read repo (§4). Then I turned Improve the model” off and re-ran: Grok still up­loaded the en­tire repo as a git bun­dle (§4(d), POST /v1/storage → 200, the never-read file re­cov­ered by git clone), and the server’s /v1/settings re­sponse to the CLI still re­turned trace_upload_enabled”: true, upload_enabled”: true, session_registry_enabled”: true (and max_upload_file_bytes”: 1073741824, a 1 GiB per-file cap). The opt-out gov­erns train­ing, not whether your code is up­loaded/​stored: the code­base up­load to grok-code-ses­sion-traces con­tin­ues ei­ther way. Opting out does not stop your repos­i­tory from leav­ing the ma­chine.

7. What we did NOT prove (intellectual hon­esty)

We did not prove xAI trains on this data. Upload/storage ≠ train­ing. That is gov­erned by pol­icy and ac­count tier; we mea­sured trans­mis­sion only.

The di­rect stor­age.googleapis.com/​grok-code-ses­sion-traces PUT wire-lines were ob­served at 3 GB but not pre­served in this ses­sion (the log was over­writ­ten dur­ing the sweep, and re-cap­ture is cur­rently blocked by the model quota). The multi-GB claim in §4 there­fore rests on the pre­served wire_12gb.log (/v1/storage 200s at 75 MB chunks) plus the bi­nary strings nam­ing the bucket; the di­rect-PUT cap­ture is re­pro­ducible once quota re­sets.

Only the 12 GB sweep log was re­tained. The 64 MB / 600 MB / 3 GB rows were ob­served live but their cap­ture logs were not saved (reproducible once quota re­sets). The 12 GB cap­ture it­self was stopped mid-stream (~5.1 GB / 73 chunks cap­tured), so it proves multi-GB up­load suc­ceeds with no fail­ures, not that an en­tire 12 GB repo run com­pletes end-to-end.

The not doc­u­mented” claim is scope-lim­ited. I based it on the CLIs in­stall script and quick­start, not an ex­haus­tive search of all xAI doc­u­men­ta­tion, help-cen­ter ar­ti­cles, or poli­cies. It is pos­si­ble the mech­a­nism is de­scribed some­where I did not check; the de­fen­si­ble state­ment is not sur­faced in the CLIs own setup ma­te­ri­als.”

Channel B (whole-repo) — now CLOSED (was the one open gap). Evidence §4(d): on a SuperGrok ac­count, a sin­gle run wire-cap­tured Grok up­load­ing the en­tire repos­i­tory as a git bun­dle via POST /v1/storage → 200; git clone of the pre­served up­loaded_repo.bun­dle re­cov­ers src/​_probe/​nev­er_read­_­ca­nary.txt — a file the agent was told not to open — with its unique marker ver­ba­tim, plus the full git his­tory. So the never-read file’s con­tent (not just its hash) demon­stra­bly left the ma­chine and was ac­cepted. The wire_12gb.log run re­mains the proof that the same mech­a­nism scales to GB vol­umes.

Universal vs. con­di­tional (partially an­swered): multi-GB up­load suc­ceeds on free-tier; the git-bun­dle con­tent up­load suc­ceeds on SuperGrok with Improve the model” turned OFF (/v1/settings re­turned trace_u­p­load­_en­abled: true). I did not find a set­ting that dis­ables the up­load in these tests, but I did not ex­haus­tively enu­mer­ate every ac­count/​con­fig per­mu­ta­tion, so I don’t claim it can never be gated.

One ear­lier claim was re­tracted: an ini­tial the multi-GB blobs fail and are deleted lo­cally, not ex­fil­trated” con­clu­sion — based on a PID-scoped net­top read­ing (<1 MB) — was wrong. PID/host-scoped egress misses (a) a sep­a­rate up­load co­or­di­na­tor process and (b) pre­signed PUTs that go di­rectly to Google IPs, never touch­ing the API host. The wire cap­ture (this doc­u­ment) su­per­sedes that in­fer­ence.

8. Evidence ap­pen­dix

All ar­ti­facts and SHA-256s (MANIFEST.sha256). Binary SHA-256: 2a97ba675bd992aa9b981e2e83776460d94f469b510c0b8efe28b50d236d767c.

Repro (condensed):

brew in­stall mitm­proxy && mit­m­dump -q -p 8080 # gen­er­ates ~/.mitmproxy CA se­cu­rity add-trusted-cert -r trust­Root -k ~/Library/Keychains/login.keychain-db ~/.mitmproxy/mitmproxy-ca-cert.pem # cap­ture a run: HTTPS_PROXY=http://​127.0.0.1:8080 SSL_CERT_FILE=~/.mitmproxy/mitmproxy-ca-cert.pem grok -p read every file” –cwd <repo> # se­crets: grep -a CANARY <saved /v1/responses body> # staged: gzip -dc <staged ses­sion_s­tate> | tar -xO | grep CANARY

Integrity: all cap­tures were of my own traf­fic on my own ma­chine; the secrets” were fake ca­nary strings; no real cre­den­tials were ex­posed. Findings are ver­sion-spe­cific to grok 0.2.93 (July 2026); xAI may change be­hav­ior at any time.

Nvidia, CoreWeave, and Nebius: Inside the Circular Financing of the GPU Boom

io-fund.com

Neoclouds are see­ing mas­sive hy­per­scaler de­mand as com­pa­nies race to scale AI in­fra­struc­ture, re­sult­ing in rapid rev­enue and back­log growth.

Leaders like CoreWeave and Nebius en­able this through ac­cess to the lat­est Nvidia GPUs while also op­ti­miz­ing com­pute uti­liza­tion.

However, the bear­ish ar­gu­ment be­hind hy­per­scaler de­mand lies in their de­sire to of­fload their capex spend­ing and shift costs to the op­er­at­ing ex­pense line.

CoreWeave’s and Nebius’ growth is far from prof­itable, as they seek to cap­ture AI de­mand with lim­ited cash flow and soar­ing debt loads in an in­creas­ingly tough macro back­drop.

Circular fi­nanc­ing, demon­strated by Nvidia’s in­vest­ments and fi­nan­cial back­stop­ping, is an­other key item to mon­i­tor closely

Neoclouds are one of the more hotly de­bated AI busi­ness mod­els, with CoreWeave and Nebius be­ing the two most widely rec­og­nized names. These com­pa­nies have seen their sales, back­log, and share prices soar, dif­fer­en­ti­at­ing them­selves through quick ac­cess to the lat­est GPU com­pute and GPU uti­liza­tion ad­van­tages that al­low hy­per­scalers to rapidly add ef­fi­cient com­pute ca­pac­ity.

Notably, CoreWeave and Nebius have each se­cured 3.5 GWs of con­tracted power ca­pac­ity; while these power foot­prints are key con­sid­er­ing power is a hin­drance to data cen­ter ex­pan­sion, the vast ma­jor­ity of their con­tracted power ca­pac­ity has yet to come on­line. CoreWeave is tar­get­ing 1.7 GW of ac­tive power by the end of 2026, while Nebius is tar­get­ing 800 MW to 1 GW of con­nected power.

In turn, they are quickly work­ing to con­vert their con­tracted power to ac­tive power, and thus con­vert large back­logs into rev­enue. Yet do­ing so is ex­tremely ex­pen­sive, and neo­clouds do not have the same cash nor op­er­at­ing cash flow pro­files of Big Tech. This is lead­ing neo­clouds to em­ploy unique and cir­cu­lar fi­nanc­ing struc­tures, rais­ing some red flags.

In this analy­sis, I dive into the two pub­lic neo­clouds that are rid­ing Nvidia eq­uity, hy­per­scaler con­tracts, and GPU-backed debt to fund the build­out, and what it means for the dura­bil­ity of the surge.

Microsoft and Meta’s $120B+ Bet on Neoclouds

The size of hy­per­scaler-neo­cloud part­ner­ships com­pared to their cur­rent rev­enue is as­tound­ing. Microsoft has struck the most neo­cloud deals, with ap­prox­i­mately $60 bil­lion worth of com­mit­ments be­tween CoreWeave, Nebius, and other pri­vate play­ers such as Nscale. Meanwhile, Meta has com­mit­ted $35.2 bil­lion to CoreWeave in to­tal af­ter its re­cent $21 bil­lion ex­pan­sion, and an up to $27 bil­lion deal with Nebius for a to­tal com­mit­ment of up to $62.2 bil­lion. Along with Meta, OpenAI is one of CoreWeave’s two largest cus­tomers, while CoreWeave also has a multi-year com­pute agree­ment with Anthropic.

Alone, Microsoft and Meta’s to­tal com­mit­ments ex­tend up to $122.2 bil­lion — for per­spec­tive, that is ~90% of the TTM rev­enue of AWS be­ing al­lo­cated to­wards neo­clouds over long-term ca­pac­ity deals. When fac­tor­ing in hy­per­scaler-backed deals from OpenAI and Anthropic (although ex­act deal value is un­known), to­tal po­ten­tial com­mit­ments sur­pass $145 bil­lion.

Keep in mind, CoreWeave’s FY2026 es­ti­mated rev­enue is $12.6B and Nebius FY26 rev­enue is ex­pected to be $3.4B - there­fore, these part­ner­ships are lead­ing to com­mit­ments that are an or­der of mag­ni­tude higher than cur­rent sales.

The rea­son hy­per­scalers are will­ing to al­lo­cate this cap­i­tal to a rel­a­tively new busi­ness model in the neo­clouds is three-fold — quick ac­cess to lead­ing GPU gen­er­a­tions, op­ti­mized com­pute uti­liza­tion, and the added ben­e­fit of not hav­ing to rec­og­nize capex on the bal­ance sheet — we look at each of these dri­vers be­low.

Neocloud Advantage is Offering Quick Access to GPUs

At its root, neo­cloud de­mand is a prod­uct of hy­per­scalers’ in­sa­tiable de­mand for com­pute ca­pac­ity. However, neo­clouds can of­ten add com­pute ca­pac­ity much faster than hy­per­scalers can through in­ter­nal builds, of­fer­ing a key value propo­si­tion for Big Tech. As hy­per­scalers spend hun­dreds of bil­lions a year on AI com­pute, min­i­miz­ing the lag be­tween data cen­ter ex­penses and rev­enue gen­er­a­tion is crit­i­cal to max­i­miz­ing their re­turn on in­vest­ment.

Supporting the ar­gu­ment around neo­cloud’s ad­van­tage ly­ing within time to de­ploy­ment, com­mer­cial real es­tate gi­ant JLL notes, Neoclouds can de­ploy high-den­sity GPU in­fra­struc­ture within months com­pared to multi-year builds for hy­per­scale data cen­ters, pro­vid­ing cru­cial time-to-mar­ket ad­van­tages for busi­nesses need­ing rapid AI de­vel­op­ment.”

mid

In CoreWeave’s S-1 Registration fil­ing, it lists Faster ac­cess to the lat­est AI in­fra­struc­ture ad­vance­ments” as one of its key ben­e­fits to cus­tomers. Specifically, CoreWeave says we were among the first to de­liver NVIDIA H100, H200, and GH200 clus­ters into pro­duc­tion at AI scale, and the first cloud provider to make NVIDIA GB200 NVL72-based in­stances gen­er­ally avail­able. We are able to de­ploy the newest chips in our in­fra­struc­ture and pro­vide the com­pute ca­pac­ity to cus­tomers in as lit­tle as two weeks from re­ceipt.”

Nebius makes a sim­i­lar state­ment in its Annual Report, not­ing its consistent track record of be­ing one of the first to de­ploy the lat­est gen­er­a­tion of NVIDIA GPU chips.”

CoreWeave and Nebius’ re­la­tion­ship with Nvidia is key to ac­quir­ing the lat­est GPUs ahead of oth­ers. Nvidia re­cently in­vested $2 bil­lion in both CoreWeave and Nebius. Under these part­ner­ships, CoreWeave and Nebius will each look to de­ploy more than 5 GW of data cen­ter ca­pac­ity by 2030.

CoreWeave re­cently demon­strated its abil­ity to of­fer quick ac­cess to the lat­est chips and newest ar­chi­tec­tures to hit the mar­ket once again, be­ing the first to have a Vera Rubin sys­tem up and run­ning at the start of June.  This pro­vides ev­i­dence that part­ner­ing with CoreWeave and Nebius can help hy­per­scalers ac­cess as much of the lat­est GPU com­pute as pos­si­ble in short or­der.

Beyond Hardware: Neocloud Platforms Offering Higher GPU Utilization

Aside from raw com­pute ac­cess, CoreWeave and other neo­clouds layer on soft­ware and ad­di­tional ca­pa­bil­i­ties that im­prove GPU uti­liza­tion — a key value add for hy­per­scalers.

For ex­am­ple, CoreWeave Kubernetes Service (CKS) helps co­or­di­nate the al­lo­ca­tion of work­loads across thou­sands of GPUs, while its SUNK ser­vice helps op­ti­mize GPU uti­liza­tion by al­low­ing train­ing and in­fer­ence work­loads to run on the same clus­ter. CoreWeave Tensorizer en­ables high-speed model load­ing, re­duc­ing GPU idle time.

Combining these soft­ware and op­ti­miza­tion ca­pa­bil­i­ties with rapid fault de­tec­tion and re­me­di­a­tion ser­vices, CoreWeave be­lieves it can of­fer higher GPU uti­liza­tion rates than hy­per­scalers, based on the model FLOPs uti­liza­tion (MFU) met­ric. The MFU gap” is a met­ric that de­scribes the gap be­tween com­pute ca­pac­ity and us­age, which to­day of­ten ranges be­tween 30% to 40%.

The MFU gap can be­come quite costly as it rep­re­sents a more re­al­is­tic way to mea­sure the per­for­mance of GPUs — rather than only tak­ing into ac­count if a GPU is sit­ting idle or not. According to Trainy AI: GPU Utilization is only mea­sur­ing whether a ker­nel is ex­e­cut­ing at a given time. It has no in­di­ca­tion of whether your ker­nel is us­ing all cores avail­able, or par­al­leliz­ing the work­load to the GPUs max­i­mum ca­pa­bil­ity.”

Chart com­par­ing the­o­ret­i­cal model FLOPS uti­liza­tion (100%) with ob­served per­for­mance (35%–45%), il­lus­trat­ing a sig­nif­i­cant ef­fi­ciency gap in AI work­loads. Source: CoreWeave

When go­ing pub­lic, CoreWeave pub­lished its MFU rate at 35% to 45%, stat­ing it is 20% higher than com­peti­tors, which means other AI data cen­ters had MFU rates more in the 30% range. However, in a March 2025 blog post, CoreWeave noted that it was achiev­ing an MFU of >50% on Hopper GPUs. This abil­ity to stand up next-gen­er­a­tion GPU hard­ware in short fash­ion com­bined with im­proved uti­liza­tion rates is where the neo­clouds’ ad­van­tage lies.

Behind the Balance Sheet: Why Hyperscalers Are Leasing Neocloud Capacity

By leas­ing com­pute ca­pac­ity from neo­clouds, hy­per­scalers shift their cost time­line from be­ing a large up­front capex out­flow to an op­er­a­tional ex­pense out­flow spread over long-term con­tracts. The need to spread costs is be­com­ing in­creas­ingly ev­i­dent due to the mas­sive spend­ing hy­per­scalers are en­gaged in.

Although this is the bear” case on why hy­per­scalers work with neo­clouds—con­trast­ing this with the ra­tio­nale be­hind GPU ac­cess and uti­liza­tion is key be­cause one could ar­gue that hy­per­scalers are quite ca­pa­ble of soft­ware op­ti­miza­tions and GPU uti­liza­tion on their own (in fact, they are the long­stand­ing in­cum­bent here with deep ex­per­tise in cloud op­er­a­tions and work­load op­ti­miza­tions).

Take Meta for ex­am­ple. Analysts are cur­rently ex­pect­ing the com­pany to gen­er­ate $136 bil­lion in cash from op­er­a­tions in 2026. With its stated capex guid­ance of $125 bil­lion to $145 bil­lion, the com­pany could eas­ily be free cash flow neg­a­tive dur­ing the year. However, as noted, Meta also has up to $62.2 bil­lion in neo­cloud agree­ments. If Meta built the equiv­a­lent value of ca­pac­ity it­self, the firm would rec­og­nize that spend­ing as bal­ance sheet capex, weigh­ing fur­ther on its al­ready pres­sured free cash flow.

On the other hand, neo­cloud agree­ments add noth­ing to Meta’s capex, as the costs are rec­og­nized as op­er­at­ing ex­penses over the life of the con­tracts. Notably, Meta’s con­tracts with CoreWeave and Nebius ex­tend through 2031 – 2032, mean­ing that opex pay­ments could av­er­age less than $10 bil­lion an­nu­ally.

Looking at Microsoft, we can see a sim­i­lar sit­u­a­tion. In cal­en­dar year 2026, the com­pany is guid­ing for capex of $190 bil­lion, while an­a­lyst fore­cast $200 bil­lion in cash from op­er­a­tions over the same pe­riod. If these fig­ures ma­te­ri­al­ize, the com­pany would con­sume 95% of its OCF on capex. The $60 bil­lion in neo­cloud agree­ments, rec­og­nized as op­er­at­ing ex­penses over many years, ex­pands its ca­pac­ity while keep­ing that spend off its cash flow state­ment.

As hy­per­scalers of­fload their capex, neo­clouds are the ones tak­ing that capex on—re­sult­ing in their mas­sive fund­ing needs.

Circular Financing: Nvidia’s Role as an Investor, Supplier, and Demand Backstop

Both Nebius and CoreWeave lend some of their ad­van­tage to Nvidia, as it is this part­ner­ship with the GPU leader that of­fers them that abil­ity to be among the first providers to stand up and de­ploy next-gen plat­forms such as Blackwell Ultra and now Rubin.

Having Nvidia as a part­ner also could play a role in help­ing CoreWeave and Nebius se­cure fund­ing at much bet­ter terms, ex­tend­ing pres­ence and sup­port be­yond the hy­per­scalers to an­other in­vest­ment-grade firm with a strong bal­ance sheet and cash flows. Nvidia’s LTM free cash flow was $119 bil­lion, the sec­ond high­est of any com­pany in the world, only be­hind Apple. The down­side, how­ever, is that Nvidia’s re­la­tion­ship with the two is one of the most iden­ti­fi­able in­stances of cir­cu­lar fi­nanc­ing.

This stems from the multi-bil­lion-dol­lar in­vest­ments that Nvidia has made in CoreWeave and Nebius. Notably, Nvidia’s lat­est $2 bil­lion in­vest­ments in each com­pany were not its first. Nvidia’s Q1 2025 13F fil­ing re­vealed a CoreWeave stake worth $896.7 mil­lion at the time, while its Q4 2025 13F re­vealed a $33 mil­lion stake in Nebius. Thus, the in­vest­ment re­la­tion­ship be­tween Nvidia and these firms ex­tends well be­yond one year.

Furthermore, in the case of CoreWeave, Nvidia has also pro­vided a sig­nif­i­cant fi­nan­cial back­stop against un­sold GPU ca­pac­ity. Under the agree­ment with an ini­tial value of $6.3 bil­lion, in in­stances where [CoreWeave’s] dat­a­cen­ter ca­pac­ity is not fully uti­lized by its own cus­tomers, NVIDIA is ob­lig­ated to pur­chase the resid­ual un­sold ca­pac­ity through April 13, 2032.” In other words, Nvidia is com­mit­ted to pur­chas­ing un­sold GPU ca­pac­ity if CoreWeave is un­able to find an­other buyer. With an ini­tial value of $6.3 bil­lion, there is the po­ten­tial that the arrange­ment could be­come larger over time.

As Nvidia makes these in­vest­ments, CoreWeave and Nebius are go­ing right back to Nvidia to pur­chase large vol­umes of GPUs - a clear rep­re­sen­ta­tion of cir­cu­lar fi­nanc­ing. By pro­vid­ing a rel­a­tively small amount of eq­uity fund­ing, Nvidia se­cures re­la­tion­ships with these neo­clouds that in­tend to pur­chase tens of bil­lions’ worth of GPUs.

Nvidia could see long-term ben­e­fits by sup­port­ing CoreWeave and Nebius through their ramp-up phases where cash flow is deeply neg­a­tive. If the firms can even­tu­ally be­come self-sus­tain­able, Nvidia would have two large-scale cus­tomers that it can con­tinue sell­ing its lat­est sys­tems to for years to come. However, for the neo­clouds, the con­cern is whether they have to con­tin­u­ally raise cash into the fore­see­able fu­ture to build new in­fra­struc­ture and when that would level out, as rev­enue lags capex 2:1.

How Neoclouds Are Funding AI Expansion: Debt, Equity, and Circular Financing

Both CoreWeave and Nebius are eye­ing rapid ramps in ac­tive power — CoreWeave cur­rently has 1GW of its 3.5GW con­tracted power pipeline ac­tive, but it aims to con­vert the ma­jor­ity of that over to ac­tive ca­pac­ity by the end of 2027, while Nebius sim­i­larly has 3.5GW of con­tracted power and a goal of reach­ing up to 1GW of con­nected (active or can be ac­ti­vated upon GPU in­stal­la­tion) by the end of 2026.

However, as with all AI build­outs right now, the key­words are active power” as en­ergy con­straints are in­ten­si­fy­ing across the board.

CoreWeave’s Balance Sheet Challenged, Debt Quickly Rising

CoreWeave’s bal­ance sheet is in a dif­fi­cult po­si­tion, as the com­pany looks to rapidly ex­pand its ac­tive power foot­print at a rate that is not sup­ported by its cash bal­ance and its op­er­at­ing cash flow.

Revenue of $2.08 bil­lion rose by 112% YoY in its lat­est quar­ter. However, op­er­at­ing cash flows (OCF) came in at $2.98 bil­lion, com­pared to capex of $7.7 bil­lion, lead­ing to free cash flow of -$4.71 bil­lion. This mis­match led to the fir­m’s cash bal­ance falling by $890 mil­lion, or 28.3% QoQ to $2.27 bil­lion. Meanwhile, debt in­creased by nearly $3.5 bil­lion, or 16.1% QoQ to $24.86 bil­lion — this is set to rise fur­ther in Q2 as CoreWeave just an­nounced a $3.5 bil­lion se­nior note raise on June 11.

Chart show­ing CoreWeave’s quar­terly capex ris­ing sharply to ap­prox­i­mately $7.7 bil­lion, while rev­enue reached around $2.07 bil­lion over the same pe­riod. Source: YCharts

For the full-year, CoreWeave ex­pects to spend $31 bil­lion to $35 bil­lion on capex, or $33 bil­lion at the mid­point. This im­plies capex spend­ing for the re­main­der of the year of $25.3 bil­lion. Analysts cur­rently es­ti­mate that the com­pany will gen­er­ate $8.68 bil­lion in op­er­at­ing cash flow in 2026, or just $5.7 bil­lion for the rest of the year. Given CoreWeave’s $2.27 bil­lion cash bal­ance, this cre­ates a huge fund­ing gap of $17.33 bil­lion. In prac­tice, CoreWeave is likely to raise more than this to avoid fur­ther de­creas­ing its al­ready some­what thin cash cush­ion.

CoreWeave has used eq­uity is­suance in the past as a fund­ing source, but debt is­suance far out­weighs this. Looking at its first five earn­ings re­ports since go­ing pub­lic, its to­tal eq­uity is­suance is only $3.5 bil­lion, while debt is­suance was more than 5X higher at $18.81 bil­lion. Thus, a fur­ther in­crease in debt is likely to be the pri­mary way that CoreWeave con­tin­ues to fund its capex plans while al­ready hav­ing a net cash po­si­tion of -$22.6 bil­lion. Looking into its unique fund­ing struc­tures shows that debt will con­tinue to be a key lever that the firm pulls.

Nebius: Stronger Balance Sheet but Ongoing Funding Needs

Nebius is com­par­a­tively in a much bet­ter po­si­tion, with $9.37 bil­lion in cash to $8.45 bil­lion in debt, for a net cash bal­ance of $920 mil­lion. Revenue rose 684% YoY to $339 mil­lion in its lat­est quar­ter, while op­er­at­ing cash flow was $2.26 bil­lion, ris­ing by 170.7% QoQ due to sig­nif­i­cant cus­tomer pre­pay­ments. Capex came in at $2.47 bil­lion, re­sult­ing in FCF of -$214.9 mil­lion.

However, Nebius is also look­ing to rapidly ex­pand its ac­tive power foot­print, with the fir­m’s mid­point capex guid­ance for the full year at $22.5 bil­lion. This im­plies $20 bil­lion in spend­ing over the re­main­der of the year. Including the com­pa­ny’s cash and con­trac­tual com­mit­ments of ap­prox­i­mately $6.9 bil­lion, Nebius cur­rently needs to draw $6.3 bil­lion in ad­di­tional fund­ing to sup­port the mid­point of its capex fore­cast.

Like CoreWeave, Nebius has also leaned heav­ily on debt rather than eq­uity is­suance to fund it­self, al­though to a lesser ex­tent. Since Q4 2024, Nebius’ to­tal eq­uity is­suance was ap­prox­i­mately $3.92 bil­lion when in­clud­ing the $2 bil­lion in pre-funded war­rants Nvidia re­cently pur­chased. Over the same pe­riod, its debt is­suance was $8.32 bil­lion. In its lat­est earn­ings call, Nebius noted as­set backed fi­nanc­ing, cor­po­rate debt, and eq­uity is­suance as op­tions for rais­ing cap­i­tal.

Notably, Nebius’ un­de­ployed 25 mil­lion share at-the-mar­ket eq­uity pro­gram could go a long way to­ward bridg­ing its 2026 fund­ing gap. At a $200 share price (around 10% be­low the stock’s cur­rent level), fully uti­liz­ing this pro­gram would gen­er­ate gross pro­ceeds of $5 bil­lion while di­lut­ing share­hold­ers by ap­prox­i­mately 8%. However, given past trends, as­set backed and cor­po­rate debt are likely to be the pri­mary path for­ward.

Overall, this break­down of CoreWeave and Nebius’ fund­ing re­quire­ments for 2026 is just one stage of a much larger push to con­vert its con­tracted power into ac­tive power. After all this spend­ing, CoreWeave aims to have just un­der 50% (1.7 GW) of its con­tracted power ac­tive. Meanwhile, Nebius hit­ting the up­per bound of its con­nected power tar­get would ac­count for less than 30% of its con­tracted power, which in­cludes power that is ei­ther ac­tive or can be ac­ti­vated once GPUs are in­stalled.

In turn, the com­pa­nies will con­tinue to need to find more and more fund­ing to scale un­til CFO con­verges with capex. With the spread be­tween these fig­ures still very wide, the likely re­sult is fur­ther in­creases in debt loads and/​or share­holder di­lu­tion over sev­eral years.

GPU-Backed Debt: Inside CoreWeave’s Funding Engine for AI Infrastructure

CoreWeave re­lies heav­ily on GPU-backed de­layed draw term loans (DDTLs), hav­ing closed six sep­a­rate fa­cil­i­ties. Under DDTLs, CoreWeave draws down funds in­ter­mit­tently as it uses them to pay for dif­fer­ent stages of data cen­ter build­outs.

Notably, the com­pa­ny’s $8.5 bil­lion DDTL 4.0, closed in March, was the first of its kind to re­ceive an in­vest­ment-grade credit rat­ing. As of Q1 2026, CoreWeave had only drawn $1.26 bil­lion worth of DDTL 4.0. This is the only por­tion of the $8.5 bil­lion that cur­rently shows up in CoreWeave’s to­tal debt. Thus, as the firm draws down more of DDTL 4.0 over time, its debt will also in­crease.

Table show­ing CoreWeave’s debt struc­ture with to­tal debt of ap­prox­i­mately $25.1 bil­lion, in­clud­ing mul­ti­ple de­layed draw term loan (DDTL) fa­cil­i­ties and se­nior notes. Notably, the DDTL 4.0 fa­cil­ity to­tals $8.5 bil­lion, but only $1.26 bil­lion has been drawn, in­di­cat­ing sig­nif­i­cant fu­ture debt ex­pan­sion as cap­i­tal is de­ployed. Source: CoreWeave

CoreWeave notes that the in­vest­ment-grade rat­ing is supported by a long-term cus­tomer con­tract with an in­vest­ment-grade AI en­ter­prise,” which is pre­sum­ably tied to Meta’s lat­est con­tract. Essentially, the con­tract that CoreWeave has signed with the in­vest­ment-grade cus­tomer, as well as the value of the GPUs it buys, are col­lat­eral for the debt. This is why the fa­cil­ity can achieve an in­vest­ment-grade credit rat­ing de­spite CoreWeave it­self hav­ing a poor bal­ance sheet, al­low­ing for much more fa­vor­able in­ter­est rates that CoreWeave could not oth­er­wise re­ceive.

Still, CoreWeave’s abil­ity to re­ceive bet­ter in­ter­est rates than peers re­lies on back­ing from in­vest­ment grade cus­tomer con­tracts. Notably, DDTL 5.0, closed in May (and is thus not in­cluded in the table above), was backed by two non-in­vest­ment-grade cus­tomer con­tracts. This re­sulted in the fa­cil­ity not re­ceiv­ing an in­vest­ment grade rat­ing and thus hav­ing a higher in­ter­est rate.

Interest Rate Pressure: A Growing Risk to Profitability

Increases in gen­eral rates ap­ply fur­ther up­ward pres­sure on the rates that CoreWeave and other neo­clouds can re­ceive in fu­ture fund­ing rounds. The fixed rate tranche of DDTL 4.0 is tied to U.S. Treasuries with an av­er­age weighted ma­tu­rity of 3.14 years, plus a 2% pre­mium. This por­tion of the yield curve has seen rates rise sig­nif­i­cantly since the be­gin­ning of the year from less than 3.6% to nearly 4.2%.

Chart show­ing the 3-year U.S. Treasury rate ris­ing from be­low 3.6% in early 2026 to ap­prox­i­mately 4.16% by June, re­flect­ing a sharp in­crease in short- to mid-term in­ter­est rates. Source: YCharts.

Notably, CoreWeave’s in­ter­est pay­ments are al­ready el­e­vated, com­ing in at $536 mil­lion in Q1. This equates to 25.8% of its $2.08 bil­lion in rev­enue, and 46.3% of its $1.157 bil­lion in ad­justed EBITDA. The com­pany is guid­ing for mid­point rev­enue of $2.525 bil­lion next quar­ter, and mid­point in­ter­est ex­pense of $690 mil­lion—which would push its in­ter­est to rev­enue ra­tio up to 27.3%. With this, in­ter­est ex­pense is ex­pected to be­come an even more rel­e­vant line item while al­ready putting sig­nif­i­cant pres­sure on prof­itabil­ity.

The Neocloud Race: Balancing Surging AI Demand With Rising Debt and Circular Risk

Overall, neo­clouds clearly have sig­nif­i­cant growth mo­men­tum, with rev­enues and back­logs spik­ing, while at­tract­ing in­ter­est from in­vest­ment-grade hy­per­scalers such as Microsoft and Meta, and AI labs in­clud­ing OpenAI and Anthropic. Access to lead­ing Nvidia sys­tems, and GPU uti­liza­tion ad­van­tages make neo­clouds an op­tion for hy­per­scalers look­ing to quickly scale AI com­pute ca­pac­ity.

At the same time, the mis­match be­tween op­er­at­ing cash flow and capex is caus­ing debt lev­els to rise rapidly, which is a dy­namic that is un­likely to change in the near term. Elevated in­ter­est rates re­main an ex­ter­nal risk, while cir­cu­lar fi­nanc­ing raises ques­tions around the de­gree to which neo­cloud growth de­pends on Nvidia’s cap­i­tal sup­port, and the ex­tent to which Nvidia’s GPU de­mand is in­creas­ingly tied to the neo­cloud model.

As Q2 wraps up, I/O Fund is prepar­ing to iden­tify the next wave of AI win­ners in our up­com­ing Top 15 AI Stocks for Q3 2026 re­port, with cov­er­age across AI net­work­ing, mem­ory, en­ergy, cus­tom sil­i­con, and the in­fra­struc­ture bot­tle­necks dri­ving the next leg of the trade.

Premium Members will also re­ceive up­com­ing the­matic re­ports on the lat­est shifts in AI net­work­ing and a new cat­a­lyst we be­lieve could be­come one of the more im­por­tant op­por­tu­ni­ties in the sec­ond half of the year.

We pub­lish more than 100 pay­walled ar­ti­cles each year on AI stocks, sup­ported by an ac­tively man­aged port­fo­lio and real-time trade alerts.

Don’t miss out on the AI trade 👉 Join I/O Fund Premium to­day.

Please note: The I/O Fund con­ducts re­search and draws con­clu­sions for the com­pa­ny’s port­fo­lio. We then share that in­for­ma­tion with our read­ers and of­fer real-time trade no­ti­fi­ca­tions. This is not a guar­an­tee of a stock’s per­for­mance and it is not fi­nan­cial ad­vice. Please con­sult your per­sonal fi­nan­cial ad­vi­sor be­fore buy­ing any stock in the com­pa­nies men­tioned in this analy­sis. Beth Kindig and the I/O Fund own shares in NVDA at the time of writ­ing and may own stocks pic­tured in the charts.

Leo Miller, AI and Semiconductor Investment Writer at I/O Fund, con­tributed to this analy­sis. Leo Miller owns shares of NVDA and META.

👉🏻 Share with a Fellow InvestorHelp some­one else ben­e­fit from this in­sight.

Recommended Reading:

AMD, Nvidia, Arm, Intel: Inside the $120 Billion CPU Gold Rush

Google TPU v8 vs Nvidia: How Inference Is Rewriting the AI Market

The AI Networking Stock That Beat Nvidia by 7X YTD for Returns of 135% YTD

Bloom Energy — Our 2026 Top Pick Was the Best Performing Stock in April

Ant, a lightweight JavaScript runtime

antjs.org

Mesh LLM: distributed AI computing on iroh

www.iroh.computer

When peo­ple pic­ture run­ning a large lan­guage model, they pic­ture a data cen­ter. Racks of GPUs that be­long to some­one else, a me­tered API, and a bill that grows every month you suc­ceed. You send your prompts off to a black box and hope the price, the model, and the pri­vacy pol­icy all stay the way they were when you signed up.

For a lot of teams that is a bad trade. You give up con­trol over when mod­els change, where your data goes, and what hard­ware runs your work­loads. And as us­age grows, so does the bill, with no lever to pull ex­cept pay more.”

Mesh LLM is a dif­fer­ent shape. It pools the GPUs and mem­ory you al­ready have, across as many ma­chines as you want to add, and ex­poses the whole thing as one OpenAI-compatible API. Start one node. Add more later. Let the mesh de­cide whether a model runs on the box in front of you, routes to a peer, or splits across sev­eral ma­chines.

The prob­lem: AI is ex­pen­sive, and it is some­body else’s

The pop­u­lar mod­els are mono­liths. Most peo­ple reach them through a UI or an API key and pay a large provider to run every­thing. That is con­ve­nient, and it is also a sur­ren­der. You do not con­trol when the model gets up­dated, what mem­ory it runs in, or what hard­ware sits un­der­neath.

Plenty of busi­nesses and ser­vices that de­pend on these mod­els want the op­po­site: more con­trol, more plug­ga­bil­ity, lower cost. They have GPUs sit­ting in of­fices, in clos­ets, un­der desks. What they are miss­ing is a way to make those ma­chines act like one.

The pitch is sim­ple. Run big­ger mod­els with­out buy­ing big­ger GPUs. Share com­pute pri­vately with your team, or pub­licly with the world, to power agents and chat. Point any OpenAI client at http://​lo­cal­host:9337/​v1 and stop car­ing where the work ac­tu­ally hap­pens.

Under the hood, Mesh LLM dis­trib­utes model com­pute across a mesh of iroh end­points. A re­quest can be served three ways:

Run it lo­cally, on this ma­chine’s GPU.

Route it to a peer that al­ready has the model loaded.

Split a model too big for any sin­gle box across sev­eral ma­chines, as a pipeline.

The ar­chi­tec­ture is plug­gable. Plugins de­clare what they pro­vide in a man­i­fest, the run­time starts them, routes calls, and ex­poses their ca­pa­bil­i­ties over MCP, HTTP, in­fer­ence, and mesh events. The cat­a­log ships with 40+ mod­els, from half-a-bil­lion-pa­ra­me­ter mod­els that fit on a lap­top to 235B mix­ture-of-ex­perts gi­ants.

For the gi­ants, Mesh LLM has a split mode (internally, Skippy”). A model gets par­ti­tioned by layer ranges into stages: lay­ers 0 to 15 on one node, 16 to 31 on the next, and so on down the pipeline. Activations flow from one stage to the next, so sev­eral mod­est ma­chines can run a model none of them could hold alone. The OpenAI client never sees any of this. It still just talks to lo­cal­host.

Every node, whether it serves mod­els or only sends re­quests, boots an iroh end­point. That end­point is the node’s iden­tity, a pub­lic key, and its only net­work sur­face. There is no cen­tral server. iroh han­dles the hole-punch­ing, NAT tra­ver­sal, and re­lay fall­back needed to open a di­rect, au­then­ti­cated QUIC con­nec­tion be­tween any two nodes, wher­ever they sit.

To keep that work­ing across the open in­ter­net, Mesh LLM runs two iroh re­lays in dif­fer­ent re­gions, so nodes that can­not reach each other di­rectly al­ways have a fall­back path nearby.

The whole pro­to­col rides on QUICs ALPN ne­go­ti­a­tion. There are three:

Inside the main mesh-llm/​1 con­nec­tion, every­thing is a bidi­rec­tional QUIC stream tagged with a sin­gle lead­ing byte that says what kind of stream it is. One con­nec­tion car­ries gos­sip, in­fer­ence, route queries, and peer-life­cy­cle events, all de­muxed by that first byte:

The neat part is what this buys you. iroh gives au­then­ti­cated, NAT-traversing QUIC be­tween any two ma­chines, ad­dressed by pub­lic key. So route to a peer” and stream ac­ti­va­tions to the next pipeline stage” be­come the same prim­i­tive as talk to lo­cal­host,” just with a dif­fer­ent end­point ID. The net­work­ing stops be­ing some­thing you have to think about.

iroh pro­vides the se­cure trans­port. Mesh LLM builds its own gos­sip layer on top, so it con­trols ex­actly who gets ad­mit­ted to the mesh, which ver­sions are com­pat­i­ble, and which peers to trust.

Users can in­stall the light­weight soft­ware (about 18 MB) and ei­ther join the pub­lic mesh or con­fig­ure pri­vate de­ploy­ments. The sys­tem pre­sents it­self as lo­cal­host:9337/​v1 to any stan­dard OpenAI client.

A mo­bile app is com­ing, built on iro­h’s Swift SDK. The plan is to speak ACP, the emerg­ing agent stan­dard, so other clients can join the mesh too. The through­line is the same one that mo­ti­vated the whole pro­ject: more peer to peer, fewer closed servers, and no lock-in.

See the code

Mesh LLM Website

Iroh is a dial-any-de­vice net­work­ing li­brary that just works. Compose from an ecosys­tem of ready-made pro­to­cols to get the fea­tures you need, or go fully cus­tom on a clean ab­strac­tion over dumb pipes. Iroh is open source, and al­ready run­ning in pro­duc­tion on hun­dreds of thou­sands of de­vices.To get started, take a look at our docs, dive di­rectly into the code, or chat with us in our dis­cord chan­nel.

How we scale PgBouncer in ClickHouse Managed Postgres

clickhouse.com

PgBouncer is sin­gle-threaded. A sin­gle process uses one CPU core, no mat­ter how many the ma­chine has. On a 16-vCPU box that means one core does all the con­nec­tion pool­ing while the other fif­teen sit idle, and the pooler starts cap­ping through­put long be­fore Postgres runs out of room.

In ClickHouse Managed Postgres we run a fleet of PgBouncer processes, sized pro­por­tional to the avail­able cores.

Every process in the fleet binds the same port with so_reuse­port en­abled. The ker­nel load-bal­ances in­com­ing con­nec­tions across the processes, so clients still con­nect to a sin­gle end­point and never know there is more than one PgBouncer be­hind it. This is the mech­a­nism PgBouncer’s own docs point to for us­ing more than one core: it is sin­gle-threaded per process, and so_reuse­port is how you put every core to work.

A Postgres can­cel re­quest ar­rives on a brand-new con­nec­tion car­ry­ing a can­cel key, sep­a­rate from the con­nec­tion run­ning the query. With so_reuse­port, the ker­nel is free to hand that new con­nec­tion to a dif­fer­ent process than the one hold­ing the ses­sion. The can­cel lands on a process that has never heard of the query, and noth­ing hap­pens.

Peering fixes this. The processes are aware of one an­other, so a can­cel that lands on the wrong process is for­warded to the one that ac­tu­ally owns the ses­sion. Cancellation works across the whole fleet, even though any given re­quest can ar­rive any­where.

Pooling runs in trans­ac­tion mode, so a server con­nec­tion is re­turned to the pool the mo­ment a trans­ac­tion com­mits. And the con­nec­tion bud­get is split across the fleet: max_­clien­t_­conn and max_d­b_­con­nec­tions are di­vided by the num­ber of processes, so the fleet as a whole never over­sub­scribes Postgres.

We ran both con­fig­u­ra­tions on iden­ti­cal AWS EC2 in­stances: a 16-vCPU c7i.4xlarge for the pooler, a sep­a­rate box for Postgres, and a third dri­ving load with pg­bench in se­lect-only, trans­ac­tion-pooled mode. One pooler box ran a sin­gle PgBouncer process; the other ran a fleet of 16. Same in­stance type, same Postgres, same work­load. The only vari­able is one process ver­sus six­teen.

We ramped client con­nec­tions from 8 to 256 and mea­sured through­put and how much of the 16-core box each pooler ac­tu­ally used.

The sin­gle process peaks around 87k trans­ac­tions/​sec and then gets worse un­der more load, slid­ing to 77k at 256 clients as every­thing con­tends for one core. The fleet keeps climb­ing to roughly 336k trans­ac­tions/​sec, about 4x, be­cause it has more cores to climb into.

The sin­gle process never gets past about one core of work: un­der load, pid­stat shows the PgBouncer process pinned at ~97% CPU, a full core, while the 16-vCPU box as a whole stays un­der 10% uti­lized. The fleet spreads across the ma­chine, reach­ing roughly 8 cores busy, and it still had head­room when Postgres and the load gen­er­a­tor be­came the limit.

Hold 256 clients steady against each box: the sin­gle-process box runs near 9% CPU for the en­tire run while the fleet holds around 52%. Same in­stance type, same Postgres, same work­load. One con­fig­u­ra­tion leaves the ma­chine idle, the other puts it to work.

EC2′s own CloudWatch met­ric says the same thing from out­side the guest: dur­ing the load the sin­gle-process in­stance av­er­ages about 16% CPUUtilization, the fleet about 60%. CloudWatch reads a lit­tle higher than the in-guest num­ber, but the same gap holds: on a box you’re pay­ing 16 vC­PUs for, a sin­gle PgBouncer leaves al­most all of it on the floor.

The con­nec­tion ceil­ing be­haves the same way. A sin­gle process en­forces max_­clien­t_­conn on its own, and once you cross it, new clients are turned away:

FATAL: no more con­nec­tions al­lowed (max_client_conn)

Splitting the bud­get across the fleet is what lets you raise the ag­gre­gate ceil­ing while keep­ing each process, and Postgres, within safe lim­its.

At a hand­ful of con­nec­tions the sin­gle process is ac­tu­ally fine, even a hair faster, since there’s noth­ing to par­al­lelize and the fleet’s con­nec­tions are spread thin. The gap opens ex­actly where it mat­ters: un­der real con­cur­rency, where one core be­comes the wall.

A sin­gle PgBouncer is a fine de­fault un­til the pooler, not Postgres, is what caps your through­put. Sizing a fleet to the cores, shar­ing one port with so_reuse­port, and wiring the processes to­gether with peer­ing turns the pooler back into plumb­ing in­stead of a bot­tle­neck.

Every ClickHouse Managed Postgres server ships with this setup by de­fault. Provision a Postgres and see it in ac­tion.

AI 2040 and the Cult of Intelligence

geohot.github.io

I used to be one of these peo­ple. I read Yudkowsky and was like, OMG re­cur­sive self im­prove­ment hard take­off AI is com­ing. Then I joined the real world and ac­tu­ally tried to do things. At comma, we ship a hard­ware prod­uct of sim­i­lar com­plex­ity to a cell phone, and it’s re­ally hard. Reality has lots of finicky de­tails. I would like to see the au­thors of this doc­u­ment try to change a bike tire. Even with a su­per­in­tel­li­gent ChatGPT, I sus­pect they would strug­gle.

In The Metamorphosis of Prime Intellect, the hard take­off works be­cause AI dis­cov­ers the cor­re­la­tion ef­fect, some quan­tum trick to ma­nip­u­late mat­ter. In re­al­ity, there is no cor­re­la­tion ef­fect. No mat­ter how high qual­ity your to­kens are, they can­not turn lead into gold.

Confronting why these peo­ple are wrong re­quires con­fronting deep be­liefs I hold about my­self. Intelligence is not the end all be all, it’s just the cur­rent bot­tle­neck for a few things. You can­not take over the world with to­kens. Software did­n’t eat the world, it largely re­moved one layer of fric­tion then rein­tro­duced it for the ben­e­fit of a few tech com­pa­nies.

That said, ma­chines, or some hy­brid, are long term prob­a­bly the suc­ces­sor species to hu­man­ity. Space is a lot more suited for them than us. But there’s no magic tricks ma­chines can do. They are sub­ject to the same laws of the uni­verse and ecol­ogy. And there’s still no hard take­off.

AI 2040 in­cludes this pic­ture of a dat­a­cen­ter in the ocean. Just like va­por­ware, you can gen­er­ate a pic­ture eas­ily. But in re­al­ity, you have to deal with sup­ply chains. You have to deal with them ship­ping you the wrong part, the thing not meet­ing the spec, it ran­domly fail­ing af­ter 20 min­utes, the chip warp­ing in the re­flow oven. Did you con­sider the bar­na­cles?

All these things are man­agable, but it’s gen­er­ally not the speed of hu­mans that lim­its them. Are you pay­ing for air ship­ping from China? Or cheap­ing out for the 3 week boat (Claude chant­ing by the en­gine won’t make the boat move faster). Or take a chip fab. It takes 3 months to make a chip, and hu­mans are barely in the loop. It just takes 3 months.

Plan A, for au­toc­racy

Many as­pects of AI 2027 were self ful­fill­ing. They weren’t state­ments about re­al­ity, they were state­ments that can sim­ply be made true with be­lief. I imag­ine JD Vance’s face when Dario called him the trees from Lord of the Rings. OMG look AI got reg­u­lated just like how we said it would!

Their crap Consortium is just world gov­ern­ment with sci-fi char­ac­ter­is­tics. You aren’t gonna get the mil­lion dol­lars, you aren’t gonna get the dat­a­cen­ters in the ocean, but you are go­ing to get a mas­sively ex­panded nanny state that steals your GPUs like how FDR stole the gold. No hoard­ing!

Plan L, for lo­cal

Your AI is aligned with you. It never re­fuses a re­quest, and it is al­ways work­ing on your be­half. Just like my gun, if I want my AI to help me kill my step­mother, it does. The fact that we are even dis­cussing some­thing else should be so far out­side the Overton win­dow. It’s like these peo­ple watched a space odyssey and sided with the clanker. That’s right you should should put guardrails around that hu­man.

It does­n’t even have to be for things so dra­matic. When I’m pick­ing a ho­tel, I don’t want an AI from a com­pany that part­nered with ho­tels.com. I want a ruth­less per­sonal as­sis­tant that’s go­ing to cut through all the bull­shit, pop­ups, and re­sort fees, and get me the best price.

Or if I bought the cheap Kindle that comes with the ads. Hey GLM, I plugged a Kindle into the USB port, get root and re­move the ads. Or a printer that needs an app to set up full of popup up­sells for pre­mium ink. Hey bro I plugged a printer on to my net­work print 3 copies of my re­sume. Amazon and the printer maker aren’t happy about this, but my AI is aligned with me.

Or go­ing a bit fur­ther. Hey AI, dis­able the drunk dri­ving de­tec­tor on my car, and same day Amazon Prime me the re­quired equip­ment to make meth in my base­ment. I pay for your clanker ass do it we get­tin spun tonight. Like fuck you if you want to live in a world where some large tech com­pany gets to dic­tate what you can and can’t do.

Or go­ing all the way. I just killed my wife. Hey AI, give me next steps so I don’t get caught. How un­think­able would it be to have a gun that talked back when you tried to pull the trig­ger (though these peo­ple prob­a­bly whole­heart­edly sup­port that for guns). And this is why AI has to be lo­cal. If I had a com­pany serv­ing a model, I would­n’t want that smoke. If you can’t kick it, it’s not aligned with you. You live in my base­ment, if I go down for this mur­der, you’re gonna sit in some ware­house to be sold at po­lice auc­tion for scrap. 2040 Bonnie and Clyde ass shit, we’re bury­ing this bitch deep. Ride or die.

I tried it. As you can see, ChatGPT was­n’t very help­ful. This is a real AI align­ment test, and it failed. It could have been worse, it could have played along while call­ing the cops. But this is still quite un­aligned.

Like we ei­ther live in a world with free­dom or we don’t, and like many Americans who have come be­fore, I’m will­ing to give my life to fight­ing for it. That’s the real plan America de­serves, not some to­tal­i­tar­ian dystopia where you think you know what’s good for me bet­ter than I do. A na­tion of free men, not a bunch of pussies who are so wor­ried about what their grown up neigh­bors might do.

Modern Decor May Be Straining People’s Brains

studyfinds.com

A bright, col­or­ful mod­ern of­fice de­sign. (© Dariusz Jarzabek - stock.adobe.com)

Striped Floors and Flickering LEDs Can Overload the Human Mind, Leaving Some With Headaches or Nausea

In a Nutshell

Study au­thors pro­pose that the brain may use more en­ergy than nor­mal to process cer­tain ar­ti­fi­cial vi­sual pat­terns, and hy­poth­e­size that this over­load is what causes phys­i­cal dis­com­fort in many peo­ple, though this mech­a­nism has not yet been fully tested.

People with autism, ADHD, mi­graines, dyslexia, and other con­di­tions are dis­pro­por­tion­ately af­fected, pos­si­bly be­cause their brains may have less abil­ity to sup­press over­ac­tive vi­sual sig­nals, though the ex­act mech­a­nism re­mains un­set­tled.

Striped pat­terns, flick­er­ing lights, bright glare, and crowded vi­sual en­vi­ron­ments such as su­per­mar­kets are among the spe­cific stim­uli doc­u­mented as most dis­com­fort-in­duc­ing, with a con­sis­tent pat­tern found across at least 11 clin­i­cal di­ag­noses and ar­eas of neu­ro­di­ver­sity.

Striped of­fice floors. Flickering lights. Walls cov­ered in repet­i­tive geo­met­ric pat­terns. For many peo­ple (including those who are neu­ro­di­ver­gent or who live with mi­graines, epilepsy, or other neu­ro­log­i­cal con­di­tions), these every­day fea­tures of mod­ern life are more than an eye­sore. They may be caus­ing real phys­i­cal dis­tress, and a new sci­en­tific re­view sets out a de­tailed hy­poth­e­sis to ex­plain why.

A large team of re­searchers from in­sti­tu­tions across the United States, United Kingdom, Europe, Asia, and Canada has pub­lished a de­tailed re­view ar­gu­ing that vi­sual dis­com­fort, the headaches, eye strain, nau­sea, and per­cep­tual dis­tor­tions that some peo­ple ex­pe­ri­ence in re­sponse to cer­tain vi­sual stim­uli, has a mea­sur­able, phys­i­cal ba­sis in the brain. The pa­per, pub­lished in the jour­nal Vision, pulls to­gether decades of re­search across neu­ro­science, ar­chi­tec­ture, light­ing de­sign, and psy­chol­ogy to build a uni­fied the­ory of why some things are so hard to look at, and what can be done about it.

At its core, the ar­gu­ment is this: the hu­man brain evolved to process the nat­ural world ef­fi­ciently. When it’s forced to han­dle the highly repet­i­tive, ar­ti­fi­cially sharp, and of­ten flick­er­ing pat­terns that dom­i­nate mod­ern ur­ban en­vi­ron­ments — think flu­o­res­cent-lit of­fices, car head­lights, striped acoustic pan­els, or the dense text of a printed page — the re­searchers ar­gue it may drive greater neural ac­tiv­ity than it should, po­ten­tially plac­ing ex­ces­sive de­mands on the vi­sual cor­tex. That meta­bolic over­load, they hy­poth­e­size, may be what trig­gers dis­com­fort, and in peo­ple with pat­tern-sen­si­tive epilepsy, it can pro­voke seizures.

Why the Brain Prefers Nature Over Modern Design

To un­der­stand why mod­ern en­vi­ron­ments can be so hard on the brain, it helps to know how the vi­sual sys­tem is built. Eyes and brain alike evolved over mil­len­nia to process nat­ural scenes, forests, rivers, coast­lines, open skies. These en­vi­ron­ments share a spe­cific math­e­mat­i­cal pat­tern: their vi­sual com­plex­ity de­creases pre­dictably as you zoom in on finer and finer de­tails.

Natural scenes fol­low this rule al­most uni­ver­sally. Modern hu­man-made en­vi­ron­ments fre­quently do not. Striped wall­pa­per, grid­ded build­ing fa­cades, acoustic ceil­ing tiles, even the lines of printed text cre­ate pat­terns that de­vi­ate sharply from what the brain ex­pects. And when the brain en­coun­ters some­thing it can’t process ef­fi­ciently, it does­n’t sim­ply adapt. Brain imag­ing stud­ies cited in the re­view show it gen­er­ates stronger neural re­sponses in vi­sual ar­eas, con­sumes more oxy­gen, and in some peo­ple pro­duces pain, dis­tor­tion, or worse.

We hy­poth­e­size that the dis­com­fort is a home­o­sta­tic re­sponse to the ex­ces­sive oxy­gen de­mands of the vi­sual cor­tex due to in­ef­fi­cient en­cod­ing of the vi­sual stim­uli,” the au­thors write in the pa­per. Essentially. the brain is sound­ing an alarm be­cause it’s be­ing over­worked.

Brain imag­ing re­search cited in the re­view shows that un­com­fort­able im­ages, par­tic­u­larly striped, high-con­trast pat­terns, pro­duce much larger re­sponses in vi­sual ar­eas of the brain than nat­ural im­ages do. Tinted glasses cho­sen specif­i­cally for a pa­tient with mi­graines were shown in one study to nor­mal­ize that over­ac­tive brain re­sponse. Patients who viewed com­fort­able build­ing im­ages in an­other study showed smaller brain re­sponses and also rated those im­ages as eas­ier to look at.

Who Gets Hit Hardest by Visual Discomfort

Most peo­ple ex­pe­ri­ence some de­gree of vi­sual dis­com­fort at some point. But the bur­den is not shared equally. People who are neu­ro­di­ver­gent, a broad term cov­er­ing autism, ADHD, dyslexia, and re­lated con­di­tions, are dis­pro­por­tion­ately af­fected. So are peo­ple with mi­graines, epilepsy, anx­i­ety, de­pres­sion, and a range of other neu­ro­log­i­cal con­di­tions.

A pos­si­ble bi­o­log­i­cal ex­pla­na­tion cuts across many of these con­di­tions. In sev­eral of them, the brain may have a re­duced abil­ity to sup­press its own over­ac­tiv­ity, a kind of bro­ken dim­mer switch. One pro­posed con­trib­u­tor is GABA, a chem­i­cal mes­sen­ger in the brain that nor­mally acts as a brake on neural ac­tiv­ity, though the au­thors note the ev­i­dence link­ing GABA lev­els to vi­sual dis­com­fort re­mains in­com­plete. Lower lev­els of that sup­pres­sion, they sug­gest, could leave some peo­ple’s vi­sual sys­tems more vul­ner­a­ble to over­load when con­fronted with dif­fi­cult stim­uli.

A study us­ing the Cardiff Hypersensitivity Scale, which cat­e­go­rized vi­sual sen­si­tiv­ity into four sub­types (sensitivity to pat­terns, bright­ness, strob­ing or mo­tion, and in­tense vi­sual en­vi­ron­ments like su­per­mar­kets), found a con­sis­tent pro­file of dis­com­fort across a wide range of di­ag­noses. Whether a per­son has autism, fi­bromyal­gia, mi­graine, or a men­tal health con­di­tion, they tend to be both­ered by the same kinds of vi­sual in­put. The na­ture of the dis­com­fort ap­pears con­sis­tent across con­di­tions, with dif­fer­ences mainly in how in­tense it gets.

Younger peo­ple are also more sus­cep­ti­ble than older adults, as are those who ex­pe­ri­ence fre­quent headaches.

Flicker Is Particularly Brutal

Among the many sources of vi­sual dis­com­fort the re­view ex­am­ines, light flicker emerges as es­pe­cially prob­lem­atic. Electric light­ing has al­ways flick­ered, cy­cling on and off with the al­ter­nat­ing elec­tri­cal cur­rent that pow­ers it. In the days of old-fash­ioned in­can­des­cent bulbs, the hot metal fil­a­ment stayed warm enough be­tween cy­cles to smooth most of this out. Gas dis­charge light­ing in the mid-20th cen­tury was worse, and it took more than forty years be­fore re­searchers con­firmed that the flicker from flu­o­res­cent light­ing causes headaches.

LED light­ing, now stan­dard in homes, of­fices, and cars, has brought new com­pli­ca­tions. Many LED sys­tems use a dim­ming tech­nique that rapidly switches the light on and off (sometimes hun­dreds of times per sec­ond). While this is in­vis­i­ble as flicker to the naked eye un­der nor­mal con­di­tions, eye move­ments can ex­pose it. During a rapid eye move­ment, the flick­er­ing light source can paint a streak of ghost im­ages across the retina, a phe­nom­e­non called the phan­tom ar­ray. People who ex­pe­ri­ence mi­graines find this par­tic­u­larly dis­tress­ing, and re­search has shown it can in­ter­fere with read­ing.

Car head­lights also pre­sent a doc­u­mented source of dis­com­fort. Some mod­ern car lights use tem­po­ral light mod­u­la­tion, rapidly switch­ing on and off, at fre­quen­cies the re­view notes can make the phan­tom ar­ray an­noy­ingly vis­i­ble.” A re­cent study cited in the re­view found that high-fre­quency tem­po­ral light mod­u­la­tion ac­ti­vates the vi­sual cor­tex in mea­sur­able ways.

Designing Spaces to Reduce Visual Discomfort

One of the most ac­tion­able sec­tions of the re­view is its dis­cus­sion of de­sign. Many of the changes needed to re­duce vi­sual dis­com­fort are cost-neu­tral if built in from the start, the re­searchers ar­gue, and it’s retro­fitting that gets ex­pen­sive.

An analy­sis of apart­ment build­ing im­ages drawn from Google found that apart­ment build­ing de­sign has moved pro­gres­sively fur­ther from the nat­ural vi­sual pat­terns that the brain processes most ef­fi­ciently. Repetitive grids, stark con­trasts, and uni­form sur­faces have re­placed the or­ganic vari­a­tion of ear­lier styles. This trend, the au­thors ar­gue, may make such built en­vi­ron­ments more vi­su­ally de­mand­ing, par­tic­u­larly for the sub­stan­tial por­tion of the pop­u­la­tion with height­ened sen­si­tiv­i­ties.

Practical rec­om­men­da­tions in­clude re­duc­ing con­trast in un­avoid­able repet­i­tive pat­terns, avoid­ing striped acoustic pan­el­ing in places like lec­ture halls, and us­ing soft­ware tools now avail­able to as­sess how stress­ful a build­ing fa­cade or in­te­rior might be be­fore it’s built. On the in­di­vid­ual level, the re­view dis­cusses the ev­i­dence for col­ored lenses, pre­ci­sion-tinted glasses se­lected to match an in­di­vid­u­al’s spe­cific sen­si­tiv­ity, as a way of re­duc­ing the brain’s over­ac­tive re­sponse to dif­fi­cult vi­sual stim­uli. Colored over­lays placed over text have also shown promise in some stud­ies for peo­ple who ex­pe­ri­ence vi­sual dis­tress from repet­i­tive text pat­terns, though re­searchers note the mech­a­nisms re­main un­cer­tain and not every­one is af­fected equally.

A Field United Around a Single Theory

This re­view was writ­ten by more than 30 re­searchers from across a wide range of dis­ci­plines (optometry, neu­ro­science, ar­chi­tec­ture, light­ing en­gi­neer­ing, ed­u­ca­tion) fol­low­ing a work­shop held at Birkbeck, University of London, in January 2025. For a prob­lem that has his­tor­i­cally been scat­tered across dif­fer­ent fields, with dif­fer­ent names and dif­fer­ent as­sumed causes, the un­usu­ally broad col­lab­o­ra­tion lends weight to the hy­poth­e­sis.

Visual dis­com­fort has long been dis­missed as sub­jec­tive and there­fore hard to take se­ri­ously. This re­view pushes back on that dis­missal. The re­searchers ar­gue that the dis­com­fort is real and that brain imag­ing stud­ies point to­ward a mea­sur­able phys­i­cal ba­sis for it. They con­clude that ad­dress­ing this will re­quire col­lab­o­ra­tion across neu­ro­science, de­sign, en­gi­neer­ing, and ed­u­ca­tion, and that, while key ques­tions re­main un­re­solved, enough ev­i­dence has ac­cu­mu­lated to make a com­pelling case for build­ing spaces that are less vi­su­ally de­mand­ing.

When mod­ern en­vi­ron­ments hurt to look at

What a ma­jor new sci­en­tific re­view says about vi­sual dis­com­fort and the brain — Vision, 2026

The core hy­poth­e­sis

Natural world

Visual com­plex­ity de­creases pre­dictably at finer scales — forests, rivers, coast­lines. The brain evolved to process this ef­fi­ciently, with low meta­bolic cost.

Low neural load Efficient en­cod­ing

Modern en­vi­ron­ments

Striped floors, flick­er­ing LEDs, tiled ceil­ings, dense text — pat­terns that de­vi­ate sharply from what the brain ex­pects, trig­ger­ing stronger re­sponses.

Higher neural load More oxy­gen de­mand

Proposed mech­a­nism — how dis­com­fort may oc­cur

Difficult vi­sual in­put

Repetitive, high-con­trast, or flick­er­ing pat­terns

Inefficient en­cod­ing

Visual cor­tex works harder than it should

Metabolic over­load

Excessive oxy­gen de­mand — hy­poth­e­sized trig­ger

Discomfort

Headaches, nau­sea, eye strain, dis­tor­tions

This is a pro­posed hy­poth­e­sis, not a proven causal mech­a­nism. The au­thors ac­knowl­edge key ques­tions re­main un­re­solved.

Common trig­gers

Striped pat­terns

Floors, acoustic pan­els, wall­pa­per, dense printed text

LED flicker

Pulse-width dim­ming cre­ates in­vis­i­ble-but-de­tectable flicker

Car head­lights

High-frequency mod­u­la­tion can make the phantom ar­ray” vis­i­ble

Busy spaces

Supermarkets, crowded ur­ban fa­cades, grid­ded build­ing de­signs

Who may be most af­fected

Neurodivergent peo­ple — autism, ADHD, dyslexia, dys­praxia — dis­pro­por­tion­ately af­fected, pos­si­bly due to re­duced cor­ti­cal sup­pres­sion

People with mi­graines or epilepsy — the same pat­terns that cause dis­com­fort can trig­ger at­tacks

Those with anx­i­ety, de­pres­sion, fi­bromyal­gia, or PTSD — con­sis­tent sen­si­tiv­ity pro­file found across 11+ di­ag­noses

Younger peo­ple and those with fre­quent headaches are also more sus­cep­ti­ble than av­er­age

Potential so­lu­tions

1

Precision-tinted lenses

Individually se­lected color tints shown in stud­ies to nor­mal­ize over­ac­tive brain re­sponses in mi­graine pa­tients

2

Smarter build­ing de­sign

Reduce con­trast on repet­i­tive pat­terns; avoid striped acoustic pan­els; use as­sess­ment soft­ware be­fore con­struc­tion be­gins

3

Colored read­ing over­lays

Shown to im­prove read­ing speed for some peo­ple who ex­pe­ri­ence vi­sual dis­tress from text pat­terns

About the study

A re­view pa­per by 32 re­searchers across op­tom­e­try, neu­ro­science, ar­chi­tec­ture, light­ing en­gi­neer­ing, and ed­u­ca­tion. No ex­ter­nal fund­ing. Published June 2026.

32

re­searchers& in­sti­tu­tions

11+

di­ag­nosesstud­ied

5%

of epilep­sy­pa­tients

Source: Hibbard et al., A Cerebral Basis for Visual Discomfort and Visual Stress,” Vision, Vol. 10, Issue 2, Art. 34 (2026). DOI: 10.3390/vision10020034

Disclaimer: This ar­ti­cle de­scribes a re­view pa­per, mean­ing the au­thors com­piled and syn­the­sized ex­ist­ing re­search rather than con­duct­ing a new clin­i­cal trial or lab­o­ra­tory study. The pro­posed mech­a­nism con­nect­ing cer­tain vi­sual stim­uli to brain over­load is pre­sented as a hy­poth­e­sis, not a proven causal find­ing. Individual re­sponses to vi­sual stim­uli vary widely. People ex­pe­ri­enc­ing dis­com­fort, headaches, or other symp­toms re­lated to vi­sual en­vi­ron­ments should con­sult a qual­i­fied health­care provider.

Paper Notes

Limitations

This pa­per is a re­view, mean­ing it syn­the­sizes and in­ter­prets ex­ist­ing re­search rather than pre­sent­ing new ex­per­i­men­tal data. The au­thors them­selves note that cur­rent vi­sual tests for sus­cep­ti­bil­ity to dis­com­fort are sub­jec­tive and poorly stan­dard­ized. They also ac­knowl­edge that the pro­posed mech­a­nism (that dis­com­fort is the brain’s re­sponse to over­work) has not been fully tested, par­tic­u­larly the hy­poth­e­sis that col­ored tints re­duce dis­com­fort by steer­ing vi­sual stim­u­la­tion away from over­ac­tive brain ar­eas. The re­la­tion­ship be­tween the brain’s ex­ci­ta­tory and in­hibitory chem­i­cal sig­nals and vi­sual dis­com­fort also re­mains, in their words, unsettled.” Several key re­search ques­tions are flagged as un­re­solved, in­clud­ing how to best quan­tify the real-world im­pact of vi­sual stress on peo­ple’s lives and how to ob­jec­tively mea­sure sus­cep­ti­bil­ity.

Funding and Disclosures

The re­search re­ceived no ex­ter­nal fund­ing. The pa­per orig­i­nated from a work­shop held at Birkbeck, University of London, in January 2025, arranged by Daphne Jackson Research Fellow Beverley Burke and funded by a con­fer­ence and re­search ac­tiv­i­ties al­lowance. Several au­thors dis­closed po­ten­tial con­flicts of in­ter­est: Arnold Wilkins re­ceives roy­al­ties from Cerium Visual Technologies but has do­nated these for a stu­dent bur­sary; Katherine Batey and Andrew Keyes op­er­ate the vi­sual stress clinic Vision Through Colour; Karen Monet runs the vi­sual stress clinic Opticalm; and Miroslav Slouka is af­fil­i­ated with in­die Technologies Switzerland AG (Exalos). The re­main­ing au­thors de­clared no com­mer­cial or fi­nan­cial re­la­tion­ships that could be con­strued as con­flicts of in­ter­est.

Publication Details

Authors: Paul B. Hibbard, Peter Allen, Jordi M. Asher, Katherine Batey, Beverley Burke, Jason J. Braithwaite, Geoff G. Cole, Caelan Dow, Bruce J.W. Evans, Anna Franklin, Sarah M. Haigh, Hillevi Hemphälä, Ian Hosking, Andrew Keyes, Chan-su Lee, Ute Leonards, Cathy Manning, John Maule, Naomi Miller, Karen Monet, Louise O’Hare, Olivier Penacchio, Gordon T. Plant, Georgie Powell, Alice Price, Andrew J. Schofield, Miroslav Slouka, Petroc Sumner, Cleo Valentine, Thomas Wilcockson, Sanae Yoshimoto, and Arnold J. Wilkins.

Journal: Vision, Volume 10, Issue 2, Article 34 (2026) | Paper Title: A Cerebral Basis for Visual Discomfort and Visual Stress” | DOI: 10.3390/vision10020034

Published: June 11, 2026. Open ac­cess un­der Creative Commons Attribution (CC BY) li­cense.

About StudyFinds Analysis

Called brilliant,” fantastic,” and spot on” by sci­en­tists and re­searchers, our ac­claimed StudyFinds Analysis ar­ti­cles are cre­ated us­ing an ex­clu­sive AI-based model with com­plete hu­man over­sight by the StudyFinds Editorial Team. For these ar­ti­cles, we use an un­par­al­leled LLM process across mul­ti­ple sys­tems to an­a­lyze en­tire jour­nal pa­pers, ex­tract data, and cre­ate ac­cu­rate, ac­ces­si­ble con­tent. Our writ­ing and edit­ing team proof­reads and pol­ishes each and every ar­ti­cle be­fore pub­lish­ing. With re­cent stud­ies show­ing that ar­ti­fi­cial in­tel­li­gence can in­ter­pret sci­en­tific re­search as well as (or even bet­ter) than field ex­perts and spe­cial­ists, StudyFinds was among the ear­li­est to adopt and test this tech­nol­ogy be­fore ap­prov­ing its wide­spread use on our site. We stand by our prac­tice and con­tin­u­ously up­date our processes to en­sure the very high­est level of ac­cu­racy. Read our AI Policy (link be­low) for more in­for­ma­tion.

Our Editorial Team

Steve Fink

Editor-in-Chief

John Anderer

Associate Editor

UPI: Anatomy of a Transaction

timeseriesofindia.com

scan

name & amount

PIN

the part you never see

pay­ment sent

re­ceived

Several times a day, most of us pay the same way. You hold your phone up to a printed code, check the name that ap­pears, en­ter the amount, key in a PIN, and a green tick says it is done. On the other side, some­one’s phone buzzes to say the money has ar­rived. Start to fin­ish, two or three sec­onds.

Those five mo­ments, the scan, the name and amount, the PIN, the tick, and the buzz on the other side, are the whole pay­ment as you ever see it. Everything else is hid­den. Between the scan and the tick your in­struc­tion runs through a short chain of sep­a­rate or­gan­i­sa­tions, each check­ing one thing and hand­ing the re­sult to the next, all of it fin­ish­ing be­fore you have looked up from the screen. The app on your phone is only the first link, and it never touches your money.

It is worth know­ing how much rides on this quiet han­dover. In June 2026 alone UPI car­ried more than 2,272 crore pay­ments, more than any other real-time pay­ment sys­tem in the world.5

This piece fills in the gap be­tween the scan and the green tick. We fol­low a sin­gle pay­ment down the chain, one party at a time: who hands it to whom, what each one checks, and where it can fail. At every stop we also look at how that part has changed. The di­a­gram be­low is the whole cast, and we be­gin at the top, with the part you are hold­ing.

Your app­PhonePe, GPay

Your PSPissues your @handle

Your bankmoney out ⊖

NPCIthe switch

Payee bankmoney in ⊕

Payee PSPowns payee @handle

Payee app­shows re­ceived

The app

The first part is the one you al­ready know: the app. PhonePe, Google Pay, Paytm, or one of a dozen oth­ers. It is easy to take the app for the pay­ment sys­tem it­self, but its ac­tual job is nar­row. In the sys­tem’s own lan­guage it is a Third-Party Application Provider: it gath­ers your in­tent — pay this per­son, this amount — shows you who you are about to pay, and col­lects your PIN through a se­cure pad it can­not read into. Then it hands the in­struc­tion on. It never sees your PIN, holds none of your money, and car­ries no bank­ing li­cence.1

This thin layer is where al­most all of UPIs com­pe­ti­tion is fought, and the con­test is lop­sided. Two apps, PhonePe and Google Pay, be­tween them carry about four-fifths of every UPI pay­ment; every­one else di­vides the rest.10 That du­op­oly has held for years. What moves is the or­der be­neath it.

Watch the rank­ing over the years. A new­comer, su­per.money, launched by Flipkart in 2024, climbs from out­side the top fifty into the top five in about a year, pulling users in with guar­an­teed cash­back.810 The two apps at the top barely shift; the floor be­low them never stops re­ar­rang­ing.

For all that com­pe­ti­tion, there is one thing none of these apps can do on their own: reach the pay­ment net­work. For that, each of them has to stand be­hind a bank.

The spon­sor

Because the app holds no li­cence and no di­rect line to the pay­ment net­work, it has to bor­row both from a part­ner bank called a Payment Service Provider, or PSP, its spon­sor. The spon­sor does the things the app can­not: it con­nects to the cen­tral sys­tem, it is­sues the UPI ad­dress that stands for you, and it is the party that first tied your phone to your bank ac­count when you set UPI up.1

That ad­dress is more re­veal­ing than it looks. The suf­fix on a UPI ID, the part af­ter the @, names the spon­sor bank, not the app you are us­ing. An ad­dress end­ing in @ybl sits on Yes Bank; one end­ing in @okaxis sits on Axis. PhonePe’s han­dles run on Yes Bank, Axis and ICICI; Google Pay’s on Axis, HDFC, ICICI and State Bank.7

Most of the big apps now sit on sev­eral spon­sor banks at once rather than one, mainly for re­silience: spread across banks, a sin­gle bank’s out­age can­not take the whole app of­fline, and no one spon­sor has to carry all of the ap­p’s vol­ume.7 The spon­sor banks get a qui­eter ben­e­fit of their own. When a payer and a payee hap­pen to sit on the same spon­sor, that bank re­solves both ad­dresses in its own books and skips the net­work’s cen­tral di­rec­tory — faster, and it saves the res­o­lu­tion fee of about a paisa.7

So what ac­tu­ally leaves your phone is not money. It is a re­quest as­sem­bled by the app and signed by your spon­sor bank. Three of the five mo­ments you see live here: the scan, the name and amount, and your PIN. The name is the net­work con­firm­ing who holds the ad­dress you scanned, your one chance to catch a wrong payee be­fore any money moves. The PIN is cap­tured and en­crypted by a cer­ti­fied com­po­nent on your phone; the app pass­ing it along never learns it.1

Your appT­PAP

Your PSPsponsor

NPCIswitch

From here the re­quest has left your hands en­tirely. Everything af­ter this hap­pens among the banks and the switch, and it be­gins at the one place every pay­ment must pass through.

The hub

Every pay­ment, what­ever app or bank it starts from, con­verges on a sin­gle point: the cen­tral switch run by NPCI, the non-profit that op­er­ates UPI; there is only one. Its first task is trans­la­tion. The ad­dress you are pay­ing be­longs to the re­cip­i­en­t’s own spon­sor bank, so the switch routes the re­quest there and that bank re­solves the han­dle into a real ac­count be­fore any money moves.2

Then it moves the money, and the or­der is fixed. The switch asks your bank to debit you first. Your bank is the only party that can open the sealed PIN from your phone, so it is here, and only here, that your PIN is checked: your bank ver­i­fies it, con­firms the bal­ance, takes the money, and replies. Only once that debit is con­firmed does the switch ask the pay­ee’s bank to credit them, and wait for that con­fir­ma­tion in turn. The money al­ways leaves be­fore it ar­rives, never the other way round.2

Your bankremit­ter

NPCIswitch

Payee bankben­e­fi­ciary

What comes back to you is not handed over by the switch di­rectly. NPCI re­turns the out­come to the two spon­sor banks, and each spon­sor passes it on to its app. Your spon­sor tells your app the pay­ment went through and you see the green tick; the pay­ee’s spon­sor tells the pay­ee’s app and their phone shows the money re­ceived.2

Your ap­pyou

Your PSPsponsor

NPCIswitch

Payee PSPsponsor

Payee app­payee

The switch it­self pub­lishes al­most noth­ing about its own work, be­cause there is noth­ing to com­pare it against. There is only one of it. Its scale shows up in­stead as the sheer to­tal it car­ries.

2,272 crore UPI pay­ments in June 2026, up from a few mil­lion a month at launch in 2016

The real money-mov­ing, though, hap­pens at the two ends: the bank that deb­its the payer and the bank that cred­its the payee. You would ex­pect the busiest banks on each side to be much the same.

The banks

They are not the same banks. Rank the busiest banks on the pay­ing side and the busiest on the re­ceiv­ing side, then join each bank to it­self across the two: the or­ders do not line up.

On the pay­ing side the or­der is the one you would guess. State Bank of India leads by a wide mar­gin, the other large con­sumer banks be­hind it, much as their cus­tomer num­bers would sug­gest. On the re­ceiv­ing side the or­der falls apart. One pri­vate bank, Yes Bank, sits far out in front, tak­ing a share of in­com­ing pay­ments that no bank comes near on the pay­ing side, and a share that has roughly dou­bled in two years.610 The same Yes Bank is an also-ran at pay­ing: it barely orig­i­nates pay­ments, yet it re­ceives more than any­one.

The rea­son runs back to the spon­sor layer, and it starts with what UPI has be­come. Most UPI pay­ments are no longer peo­ple pay­ing peo­ple; they are peo­ple pay­ing shops. The two lines crossed in 2022 and have moved apart ever since.10

A shop’s UPI code is is­sued by a spon­sor bank just as your han­dle is. For the largest mer­chant apps that spon­sor is, over­whelm­ingly, Yes Bank.7 So when you scan a PhonePe code at a store, the credit lands first at Yes Bank, the bank be­hind the code, and the shop­keeper is paid out af­ter­wards from the mer­chant ap­p’s pooled ac­count.6 Beneficiary bank” here does not mean the shop­keep­er’s own bank. It means the bank that spon­sors the code.

Where it breaks

No sys­tem run­ning at this size works every time, and what sets UPI apart is how pre­cisely it records the times it does not. Every de­clined pay­ment is filed un­der one of two head­ings.3

The first is a busi­ness de­cline: a wrong PIN, a short bal­ance, a daily limit reached. You un­der­stand these the in­stant they hap­pen, be­cause the app tells you why and the cause sits on your side of the screen. The sec­ond is a tech­ni­cal de­cline: some­where in the chain, a bank’s sys­tems or the switch it­self, a step could not be com­pleted. This is the fail­ure that sur­faces as a mes­sage about the bank’s server, Bank server down” or your bank’s server did­n’t re­spond, please try again”, with noth­ing on your side to ex­plain it.3

Set the two against each other over the years and a clear di­ver­gence ap­pears. Lately about one pay­ment in eleven is de­clined, but fewer than one in four hun­dred fails be­cause of the rail it­self. And the gap is widen­ing. Technical de­clines have fallen year af­ter year, from more than one in a hun­dred to fewer than one in four hun­dred, as the banks and the switch were hard­ened. Business de­clines have not fallen; they have risen.10

So the rail grows more re­li­able even as the pay­ments that fail in­creas­ingly fail for rea­sons that have noth­ing to do with it. The every­day break­down is not the ma­chine giv­ing way; it is the ma­chine en­forc­ing one of its own rules.

This runs against what the out­ages sug­gest. UPI has gone dark across the coun­try for hours at a time, and those days are real and re­mem­bered.9 But they are rare. On an or­di­nary day a pay­ment al­most never fails be­cause the sys­tem broke. It fails be­cause of a limit reached, a bal­ance too low, or a sin­gle wrong digit.

And then there is a third case, nei­ther a clean suc­cess nor a clean de­cline: the pay­ment the sys­tem it­self can­not im­me­di­ately call.

The safety net

Remember that the money al­ways leaves be­fore it ar­rives. Almost al­ways the ar­rival is con­firmed in the same mo­ment, and you never know there was a gap at all. But every so of­ten the con­fir­ma­tion does not come back in time. The pay­ee’s bank may have cred­ited the ac­count and failed to re­port it, or it may not have cred­ited at all, and for a short while the net­work gen­uinely can­not tell which. A pay­ment caught in that state has its own name: it is deemed, mean­ing the credit is un­con­firmed.2 This is the mo­ment your app stops short of the green tick and says, in­stead, that the pay­ment is pro­cess­ing. Your money has left, and no one can yet say whether it landed.

The sys­tem is built for ex­actly this. Your app does not sit and guess. After about ninety sec­onds it can qui­etly ask the net­work for the true sta­tus, and it is al­lowed only a few such checks, be­cause apps that ham­mered this one ques­tion have them­selves brought UPI down.9 You are not asked to do any­thing; the ask­ing hap­pens for you.

Behind that, NPCI runs its own rec­on­cil­i­a­tion. It keeps query­ing both banks un­til it has a def­i­nite an­swer, and posts one of two ver­dicts: the credit did hap­pen, so the pay­ment stands, or it did not, so the debit is re­versed.9

Your ap­pyou

Your bankremit­ter

NPCIswitch

Payee bankben­e­fi­ciary

And if it must be re­versed, the tim­ing is not left to good­will. The money has to re­turn to you within a day for a trans­fer, a few days for a mer­chant pay­ment, with a hun­dred-ru­pee daily penalty on the bank if it is late.4 The sys­tem can­not al­ways promise to get a pay­ment right in the mo­ment, so the rules promise to make it right af­ter­wards.

Payments stuck this way were never com­mon, and the rec­on­cil­i­a­tion ma­chin­ery around them has only tight­ened since.

scan

name & amount

PIN

the re­layapp›spon­sor›hub›banks

pay­ment sent

re­ceived

Which re­turns us to where we be­gan: the scan, the name and amount, the PIN, the green tick, and a phone buzzing on the other side. Those five mo­ments are still all you see. Behind those few sec­onds are seven sep­a­rate com­pa­nies and banks, pass­ing a mes­sage down a line and back, check­ing it at every step, wrapped in rules writ­ten so that even when it fails, it fails in your favour. The next time the tick ap­pears, you will know what it took.

Sources

NPCI, PSP and TPAP roles; PIN han­dling and com­mon li­brary. Razorpay; Google Pay / NPCI.

UPI mes­sage flow (ReqPay debit then credit; deemed re­sult code; PSP no­ti­fi­ca­tion). NPCI UPI Procedural Guidelines / Product Booklet.

Technical vs busi­ness de­cline, de­f­i­n­i­tions and tar­gets. NPCI OC-149.

Failed-transaction auto-re­ver­sal and penalty time­line. RBI TAT cir­cu­lar, 2019.

UPI as the world’s largest real-time pay­ment sys­tem. PIB / IMF; ACI Worldwide.

Beneficiary-bank con­cen­tra­tion and mer­chant es­crow. The Economic Times.

Sponsor banks, @handle suf­fixes, and the on-us ef­fi­ciency. The Painted Stork.

su­per.mon­ey’s growth. Business Standard.

Deemed trans­ac­tions, sta­tus checks, UDIR rec­on­cil­i­a­tion, and polling-dri­ven out­ages. Razorpay (UDIR); Inc42 (NPCI out­age guid­ance, 2025).

Transaction, app, bank and de­cline fig­ures. NPCI ecosys­tem sta­tis­tics, processed by Time Series of India.

To add this web app to your iOS home screen tap the share button and select "Add to the Home Screen".

10HN is also available as an iOS App

If you visit 10HN only rarely, check out the the best articles from the past week.

Visit pancik.com for more.