POROROCA OTA
Paywall experiments without an app-review cycle
The problem: your paywall is the most review-blocked screen you own
The paywall is often the single highest-leverage screen in a subscription app, and also the one you can least afford to leave broken while waiting on a review queue. A wording change, a price display tweak, or a layout variant you want to test all carry the same release overhead as a major feature.
The workflow in four steps
1. Validate the paywall document you've authored before signing anything — this is where a typo'd token name or an unsupported node type gets caught, before it ever reaches a signature.
swift run pororoca validate .pororoca/documents --platform ios2. Export a signed, immutable bundle with a descriptive, unique update ID. Because update IDs are immutable and unique within the app, encoding the date and purpose in the ID (as below) makes it easy to match a live paywall variant back to the exact export that produced it.
swift run pororoca export .pororoca/documents \
--output .pororoca/update --update-id checkout-copy-2026-09-04-1 \
--private-key .pororoca/keys/private.key3. Publish the variant to a 10% cohort so most users stay on the known-good paywall while you watch the new one. The private key never leaves this step — the manifest that reaches the control plane is already signed by the time it's published.
POROROCA_API_TOKEN=pororoca_live_... swift run pororoca publish .pororoca/update \
--server https://pororoca-ota.fly.dev --app your-app-slug \
--channel production --rollout 10 \
--public-key .pororoca/keys/public.key4. Read `applied` telemetry in the dashboard to confirm the cohort actually rendered the new paywall — not just that it downloaded — then widen deliberately or roll back in one command if it underperforms.
status → publish 10% → observe → 25% → observe → 50% → observe → 100%Because rollout is deterministic by install ID, the same 10% of installs stays in the experiment as you observe it — nobody bounces between variants between launches, so a conversion difference you see in the dashboard reflects the same group of real installs across the whole test, not a reshuffled sample each time someone reopens the app.
Limits and the trial
Not yet available: team members and RBAC, usage-based limits, automated alerts, cross-platform expression parity between iOS and Android, and a hosted MCP transport.
On Android, storage is host-managed and the renderer surface is smaller than SwiftUI's, with no full modifier parity yet — worth knowing before you build a paywall variant that leans on iOS-only presentation, since the same document may need a simpler Android counterpart rather than a byte-for-byte port.
There is one Pro plan, card-required 21-day trial, billed in BRL or USD.