RORK LABJP
PLAY — Google Play's target API level 36 requirement took effect yesterday, August 31. From today, new apps and updates must target Android 16VISIBILITY — Apps still on API 35 stay listed but disappear for users on newer Android versions. No error is raised; new installs simply fade, which makes the change easy to missEXTENSION — If you missed the deadline, an extension through November 1, 2026 can be requested in Play Console — best filed alongside a concrete migration planAPPLE — On the Apple side, the event lands September 9 and iOS 27 is reported to ship September 14. Testing generated apps on iOS 27 hardware before release week is time well spentEXPO — Expo released expo-paste-input on August 28, a native module that brings image, GIF, and sticker paste to React Native TextInputEAS — EAS Observe reached general availability on August 20, putting crash and performance monitoring on the same EAS platform as builds and updatesPLAY — Google Play's target API level 36 requirement took effect yesterday, August 31. From today, new apps and updates must target Android 16VISIBILITY — Apps still on API 35 stay listed but disappear for users on newer Android versions. No error is raised; new installs simply fade, which makes the change easy to missEXTENSION — If you missed the deadline, an extension through November 1, 2026 can be requested in Play Console — best filed alongside a concrete migration planAPPLE — On the Apple side, the event lands September 9 and iOS 27 is reported to ship September 14. Testing generated apps on iOS 27 hardware before release week is time well spentEXPO — Expo released expo-paste-input on August 28, a native module that brings image, GIF, and sticker paste to React Native TextInputEAS — EAS Observe reached general availability on August 20, putting crash and performance monitoring on the same EAS platform as builds and updates
Articles/Dev Tools
Dev Tools/2026-04-01Advanced

Rork Max × tRPC × Cloudflare Workers: Three Boundaries Where a Green Type Check Still Returns a 500

A full tRPC and Cloudflare Workers edge API walkthrough, plus three boundaries that slip past the type checker: D1 column names versus your output schema, KV cache return shapes, and a rate limiter that measured 30.5 requests per minute against a stated limit of 60.

tRPCCloudflare Workers24type safetyedge APIRork Max232TypeScript8backend9D12

Premium Article

Setup and context: The Hidden Cost of Untyped APIs in Mobile Development

When you're building a Rork Max app and connecting it to a backend API, a subtle but serious risk lurks beneath the surface: type divergence. The backend evolves, a field gets renamed, a response shape changes — and your mobile app continues calling the old API until a user reports a crash. By then, the damage is done.

This problem isn't unique to beginners. Even experienced TypeScript developers working on REST APIs routinely deal with the friction of manually keeping frontend and backend types in sync. You write an interface on the client, a matching type or schema on the server, and then spend mental energy ensuring they stay aligned. Code generation tools like OpenAPI Codegen or GraphQL Code Generator help, but they introduce their own complexity: schema files, generation scripts, versioning challenges.

tRPC (TypeScript Remote Procedure Call) takes a fundamentally different approach. Instead of generating types from a schema, it shares the type definitions themselves between your server and client. When you define a procedure on the server, your React Native components automatically know its input and output types — no generation step, no schema file, no manual sync. If the server type changes, your client shows a compile-time error immediately.

Pair this with Cloudflare Workers, and you have a globally distributed, low-latency backend that costs virtually nothing for indie app scales and scales seamlessly as your user base grows. This guide covers everything: project architecture, router design, authentication, caching, advanced middleware patterns, and a full CI/CD pipeline with GitHub Actions. It's written for developers comfortable with TypeScript who have shipped apps with Rork Max.

What tRPC Guarantees, and What It Does Not

Before the implementation, here is the map I wish I had drawn first. Everything below the third row is a boundary you have to close by hand, and the first time I skipped one it cost me a production incident: a getProfile procedure that compiled cleanly, autocompleted perfectly in the editor, and returned INTERNAL_SERVER_ERROR on every single call.

BoundaryType guaranteeWhat happens when it breaks
Client ↔ router definitionYes (shared AppRouter type)The build fails. It never reaches production
Input ↔ Zod schemaYes (validated at runtime)BAD_REQUEST comes back. An expected failure
D1 column names ↔ output schemaNo.output() throws at runtime — every request 500s
KV return value ↔ declared typeNo (as T waves it through)A differently shaped value arrives wearing the right type
Environment secrets existingNoYou find out on the first request after deploy

Only the top two rows are covered by the compiler. The bottom three stay open unless you deliberately close them, and this guide flags each one as we reach it.

Understanding tRPC's Core Concepts

Procedures: The Building Blocks

In tRPC, everything revolves around procedures — server-side functions that your client calls directly. There are three types. A query is for reading data (equivalent to an HTTP GET). A mutation is for writing data (equivalent to a POST, PUT, or DELETE). A subscription is for real-time data streams over WebSocket, though we won't cover subscriptions in this guide since Cloudflare Workers has limited WebSocket support.

What makes procedures special is that they're defined with full TypeScript types, and those types are exported as a single AppRouter type that your client imports. No REST specification. No GraphQL schema. Just TypeScript.

Zod: Your First Line of Defense

tRPC uses Zod for input validation. Every procedure that accepts arguments must define a Zod schema for its input. This gives you two things at once: compile-time type safety (TypeScript infers types from Zod schemas) and runtime validation (malformed requests are rejected before they reach your business logic). For a mobile app where you control both client and server, you might wonder if runtime validation is really necessary. It is — because your API will eventually be called by users with older app versions, or potentially by third-party clients, and Zod protects you in all those cases.

The Router as a Contract

An appRouter in tRPC is essentially a typed API contract. When you export type AppRouter = typeof appRouter, you're exporting a structural description of every endpoint your backend exposes — its name, its input schema, and its output type. Your mobile app imports only this type (not any runtime code), which means you can keep your backend package out of your mobile bundle entirely.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
See exactly why putting SELECT * and .output() in the same procedure returns a 500 on every request, and get the mapper function that closes the gap
Read the measured numbers behind a rate limiter that admits 30.5 requests per minute when it claims 60, plus a fixed-window rewrite you can drop in
Learn why a KV cache wrapper hands back a D1Result wearing an array's face, and how waitUntil removes the write latency from every cache miss
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $15 for lifetime access
View Membership →

Related Articles

Dev Tools2026-04-02
Building a Production-Ready REST API with Rork, Hono.js & Cloudflare Workers — JWT Auth, D1, R2, and Rate Limiting
Build a production-grade REST API for your Rork app with Hono.js and Cloudflare Workers — JWT auth, D1 SQLite, R2 storage, and rate limiting, all from scratch.
Dev Tools2026-06-22
Serving Both Plain Rork and Rork Max From One Backend — Designing an API Response Contract That Never Breaks Old Binaries
When plain Rork (React Native / Expo) and Rork Max (native Swift) both call the same Cloudflare Workers backend, the whole design centers on not breaking old binaries you cannot force-update. Wrap responses in an envelope, evolve them additively, absorb client differences with capability flags, and retire old contracts safely — shown in code.
Dev Tools2026-07-19
When Rork Max's Two-Click Submit Stalls, Tell Which Layer Broke
Rork Max's one-click install and two-click submit fold the complexity of iOS shipping into four hidden layers. When the abstraction leaks and your submission stalls, this map helps you tell which layer failed and fix it yourself.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →