Expo's Fingerprint Runtime Version Changes When You Edit extra, Not Your JavaScript

An over-the-air update is JavaScript that calls into a native binary you cannot change. Treat the runtime version as the ABI version of that binary. Experiments with @expo/fingerprint 0.20.13 show which edits change the hash (extra, version, build numbers, native modules) and which do not (JavaScript, pure-JS dependencies), and a skip list that silently drops a default.

September 30, 2026 | 9 min

React Native's Built-In URL Does Not Resolve '../x'

A client library shared between a website and a React Native app usually fails on the boring parts of the Web platform, not on fetch. Reading React Native 0.87.1 and Expo 57 sources shows three layers of runtime, a URL class that returns ‘/b/c/d/../x’ where the web returns ‘/b/x’, and a fetch with no response stream unless Expo replaces it. A small client that checks what it needs, tested against four simulated runtimes.

September 26, 2026 | 10 min

APNs Stores One Pending Notification per App, So Treat Push as a Hint

Apple and Google both document what happens to a push when the device is offline, the app is killed or the sender is too chatty: messages are replaced, dropped, reordered or delayed. A table of those documented failure modes, and a small simulation showing that a client which pulls from a cursor converges where a client which applies push payloads does not.

September 19, 2026 | 9 min

A Step-Up Challenge Is a 401, and Your Client Needs a Loop Guard

RFC 9470 lets an API tell a client that its access token was obtained with too weak or too old a login. Reading the RFC section by section, then building a toy server and client, shows what the document specifies (a 401 challenge, two parameters) and the three things it leaves to you: concurrent challenges, loops, and caches.

September 15, 2026 | 10 min

After Backgrounding, a WebSocket Reporting OPEN Is Only a Claim

Apple’s and Android’s own documentation say a backgrounded app can be suspended, its network access deferred, and its existing connections closed. So when your app comes back, readyState === OPEN is only a memory of the last event, not a measurement. This post derives a small foreground routine (probe, rebuild, catch up) from those documented rules, runs it against a frozen-process stand-in on Linux, and is explicit about what no device was used to check.

September 12, 2026 | 15 min