Twitch Ships Server-Side Eppo Keys in Its iOS App, Exposing Its Entire Product Roadmap
How a one-character configuration mistake turns feature flags into a competitive intelligence feed
The Twitch iOS application initializes the Eppo feature flagging SDK (now a Datadog product) using server-side SDK Keys instead of Client Tokens. This means every flag configuration is returned to the device in plaintext: flag names, variation values, allocation percentages, targeting rules, A/B test structures, and experiment status.
Two distinct SDK keys were observed in network traffic from the Twitch iOS app. Together they return over 260 production feature flags across Twitch's Production environment. Across a two-week observation window, 12 Twitch iOS users generated 208 flag configuration requests, confirming that these configurations are fetched automatically, repeatedly, and at scale by the app's normal operation.
The result is not a list of boolean toggles. It is a real-time, continuously updated window into Twitch's product strategy.
What leaked
Before the technical details, here is what these unobfuscated flags reveal. None of this has been publicly disclosed by Twitch or Amazon:
- Twitch is testing viewer-triggered ad breaks (
pause-ads-trigger), a 50/50 A/B test launched February 26, 2026. If viewers choose when to watch ads instead of being interrupted, it rewrites Twitch's entire relationship with its audience. - Amazon product listings are live inside Twitch streams for e.l.f. Cosmetics, Dove, Razer, Revlon, L'Oréal, NYX, Meta Quest, Bazooka, and others, with ASINs, campaign IDs, and per-brand measurement holdouts baked into the flag configuration.
- Turbo has a dedicated growth engineering team. Nine sequential placement tests, a nested experiment pitting "signup upsell" against "acquisition," a 30% targeted discount, and a custom chat color upsell. The ad-free tier is no longer an afterthought.
- A friendly fraud ML model is deployed to 90% of users, 2FA is being skipped for 99.98% of new creators, and the complete community gift sub pricing curve (discount tiers, quantity breakpoints, margin ratios) is readable in the JSON payload.
- An "Elevate Prime 2026" experiment with seven variants is fully configured but not yet launched. Five strategies to convert free viewers into Prime subscribers.
- A Twitch Rivals roster for a February 2026 event is hardcoded: tydollasign, funnymike, Im_Dontai, and 15 other handles.
All of this from two misconfigured SDK keys.
The misconfiguration
Eppo provides two types of credentials for SDK initialization: SDK Keys and Client Tokens. They are functionally identical with one critical difference: when a Client Token is used, the configuration payload is obfuscated. Flag names are hashed, variation values are encoded, and targeting rules are not human-readable.
Eppo's own documentation is explicit:
SDK keys and Client Tokens are the same functionality keys, except config always is obfuscated when Client Tokens are used. Therefore, the main application of the Client Tokens is SDK clients requesting configurations for clients such as browsers or mobile applications. Meanwhile, the primary application of the SDK keys is on server side.
And from the SDK introduction:
For client SDKs, this configuration is obfuscated to ensure that end users cannot reverse engineer what flags are active, or what targeting logic is in place.
Twitch's iOS application uses server-side keys. Two distinct keys were observed in network traffic:
Key 1: 3mv-BKCSZJDyZr...
Key 2: jfJjDAgpy-B7j5...
Key 1 returns 146 flags spanning web, mobile, and cross-platform features. Key 2 returns 132 flags, predominantly iOS-specific. Nine flags appear in both. Both return "format":"SERVER" in the response header, the explicit marker that the payload is unobfuscated:
{
"createdAt": "2026-02-27T08:45:24.609Z",
"format": "SERVER",
"environment": {
"name": "Production"
},
"flags": { ... }
}
Had Client Tokens been used, this field would read "format":"CLIENT" and every flag key, variation, and rule would be hashed. Instead, the entire configuration (flag names, experiment structures, targeting conditions, JSON payloads with ASINs and pricing tables) is returned as human-readable JSON.
The endpoint is hosted on Twitch's CDN (assets.twitch.tv), requires no authentication beyond the key itself, and is not rate-limited:
GET /eppo/api/flag-config/v1/config
?sdkName=ios-debug
&sdkVersion=4.0.1
&apiKey=[KEY]
Host: assets.twitch.tv
Once a key is observed in network traffic, it can be used to poll from any HTTP client indefinitely. Changes Twitch makes to their flag configuration are reflected within minutes.
What feature flags encode
In a mature experimentation platform like Eppo, each flag carries a flag name, a human-readable string like is_user_in_friendly_fraud_group or Elevate-Prime-2026. Variation values: the possible states, revealing whether something is a simple rollout or a multi-arm experiment. Allocation rules: who sees what at what percentage, distinguishing active A/B tests (50/50 with logging) from graduated features (100% treatment, no logging). Targeting conditions: user IDs, channel IDs, app versions, staff flags. JSON payloads: structured data including Amazon ASINs, pricing ratios, promotion schedules, and URL configurations.
When unobfuscated, the configuration file reads like an internal product strategy document.
Monetization: 30+ simultaneous experiments
Over 30 flags across both keys are dedicated to purchase flow optimization, the single largest cluster in the configuration. Twitch is not iterating on monetization. It is running a systematic sweep of every variable in the commerce stack.
The checkout page has a five-way A/B test (two-column-checkout) experimenting with "suggested payment method" placement: left vs. right, card opened vs. collapsed. Apple Pay on web is in a separate A/B test. Venmo is hidden for 90% of users with a 10% holdout still logging, either underperforming or carrying unfavorable processing economics. Xsolla banners are live. Even the landscape orientation of the iOS app is being tested for commerce layout: ios_com_landscape_ingress_v2 runs three variants ("buttons over," "prioritize gifting," and control) with logging.
Bits purchasing has its own conversion funnel. One-click checkout in the top nav (50/50 with logging). Repeat buyer promos (50/50 with logging). A more-buttons-more-bits flag that has already graduated to 100%. That experiment concluded and shipped. The internal logic is visible in the allocation: more surfaces for purchase entry points equals more spending, validated by data.
Gift subs are scaling. 200-unit and 1,000-unit bundles are enabled. A gift_badge_progression flag with four variants tests gamified tiers. A spender rewards experiment (Q3_2025_Spender_Rewards) tests 100 Bits vs. 250 Bits rewards against control, measuring exactly how much bonus currency changes purchasing behavior.
And then there is prominent-entry-hardcoding, which contains the complete community gift pricing ratio table in its JSON payload: discount tiers at 35% and 50%, quantity breakpoints at 5, 10, 25, 50, 100, and 150 gifts, and separate pricing curves for minimum, intermediate, and maximum tiers. This is internal commerce economics, the margin structure of community gift subs, served to every device.
Turbo: nine experiments to find every conversion surface
Twitch Turbo has historically received minimal product investment. The flag data shows a different reality for 2026.
turbo-february-experiments splits traffic 50/50 between "turbo-signup-upsell" and "turbo-acquisition," two different growth hypotheses tested head-to-head. Within the signup-upsell cohort, go-turbo-go runs a four-way test with three treatment variants against control. This is nested experimentation: one test feeds into another to decompose which strategy and which execution converts best.
On iOS, nine sequential experiments (ios_com_app_start_test_v1 through v9) each run six-way tests across "following", "profile", "home", "following_plus_profile", and "combined" placements, all with logging. Twitch has systematically tested every surface in the app for Turbo upsells. The winner is in the data: ios_com_turbo_ingress_v2 has graduated following_plus_profile to 100%. Following and Profile won. It shipped.
The incentive stack is also being tested. A 30% targeted discount (ios-turbo-discount-30) is staged. A custom chat color upsell (ios_com_turbo_custom_color_upsell) runs 50/50 with logging, testing whether vanity features drive Turbo conversions. An ios_com_turbo_signup_upsell runs a three-way test for app versions 27.9+.
Nine placement tests, a nested experiment, a discount, a vanity upsell, and a graduated winner. This is not casual A/B testing. This is a dedicated growth engineering program.
Amazon commerce: a general-purpose shopping layer
The sponsored_shopping_release flag is among the most complex in the configuration. It contains Amazon ASINs for over a dozen brands, mapped to campaign IDs, segmented by marketplace, and structured with measurement holdouts.
e.l.f. Cosmetics: three ASINs, US and Canada, one campaign ID. Dove Men+Care: one ASIN per market, three campaign IDs. Razer: nine ASINs, two campaigns, one at 100% (no holdout), one at 90/10. Revlon: six ASINs, two campaign windows. L'Oréal: nine ASINs. NYX: nine ASINs. Meta Quest: single ASIN (B0CD1JTBSC). Bissell: single ASIN. Bazooka: eight ASINs. Amazon Basics: nine ASINs, US and Canada.
Most brands run 90/10: 90% see the shopping experience, 10% holdout for measurement. The holdout structure is consistent across brands, a standardized commerce measurement framework. The targeting rules route specific advertising campaigns to specific product sets by marketplace.
The brand list tells the story. Razer and Meta Quest are gaming-adjacent. Everything else (cosmetics, haircare, household cleaning, candy, commodity electronics) is not. Twitch is not building a merch shelf. It is building a distribution channel for Amazon's advertising business across every consumer category.
Ads: from forced interruption to viewer choice
pause-ads-trigger launched February 26 as a 50/50 test with logging. Internal test device IDs (twitch-internal-test-request, twitch-internal-test-request-gdads) are whitelisted. If this is what the name implies, ad breaks triggered at viewer-initiated pause points rather than forced mid-rolls, it is the most significant change to Twitch's ad model since pre-rolls.
The measurement stack is being built alongside it. OM SDK viewability (omsdk_ad_measurement) runs a 50/50 test with logging. IAB compliance (omsdk_iab_compliance) is at 100%. A brand lift measurement system (brand_lift_v0) is configured but disabled, in development. An ads_sprig_trigger flag fires Sprig user sentiment surveys across 18 ad event types: preroll starts, midroll starts and ends, squeezeback starts and ends, parallel adplay, outstream verticals, lower thirds. Every format, surveyed.
On iOS, closed captions are coming to ads (ios_ads_cc_native, ios_ads_cc_pc). Async first feed ad requests are at 98% treatment with a 2% control holdout. A video ad countdown UI is being tested.
The direction is legible: make ads something viewers tolerate rather than endure, and make the tolerance measurable enough to justify premium CPMs.
Fraud, security, and the growth tradeoff
is_user_in_friendly_fraud_group allocates 90% to a friendly_fraud_model ML variant and 10% to control, with logging. "Friendly fraud" (chargebacks filed by the actual buyer) is a specific and expensive category for platforms selling virtual goods. The 90/10 split with active measurement means the model is deployed and its precision is being validated before full rollout.
pre-affiliate-2fa-skip routes 99.98% of users to skip two-factor authentication during creator onboarding. Logging is enabled on the 0.02% holdout. Twitch determined that mandatory 2FA was killing creator conversion and made a calculated tradeoff: security friction versus funnel velocity. The tiny holdout means they are still measuring whether it holds.
Age verification is staged. ios-user-age-verification has staff access enabled and a general population allocation at 0% traffic, configured and ready to flip. mobile_mandatory_email_verification is similarly staged for both iOS and Android. These are compliance features waiting for a regulatory trigger.
Protocol-level flags block javascript: and data: URLs in auth callbacks and restrict social auth postMessage origins. Active XSS mitigations in production.
Unreleased products
Elevate Prime 2026. Seven variations: control, "Subscribe Button Copy", "Support Panel Prime Elevation", "Banner/Chat Callout", "One-Click Prime Button", "DART Notification", and combined. Fully configured. Set to control. Not yet launched. This is Amazon's next push to convert Twitch's free audience into Prime subscribers, with five strategies ready to test.
Weekly Rewards. iOS-Weekly-Rewards, configured, set to false. Not yet live.
Theater Portal. An allowlist of 14 user IDs has been iterated through three development variants, with the latest deployed for app version 28.1+. Early access testing.
Watch Streaks. Enabled on iOS since version 26.3, with an extended "stories recovery" variant and a separate web visibility test at 50/50 with logging. Duolingo-style retention applied to viewing.
Broadcasting. BRB Mode, Dual Camera, and Skyline Chat are all configured but dormant. IRL Broadcasting v2 is at 99.99% treatment. Shipped. A speed control feature for VOD playback is rolling out on iOS 28.2+.
Creator Promotions. An unlock schedule references quarterly dates through February 2027 with a "3 promos per 24 hours" rate limit.
Internal identifiers
The flags expose operational details that were never intended for external consumption.
Xarth. ios_app_performance_monitoring reveals internal release track names: "Xarth Beta", "Xarth Enterprise", "Xarth Debug." Xarth is the internal codename for the Twitch iOS app.
Kasada. exclude-client-errors filters kasada-solver from user-agent strings in error monitoring. Twitch is aware of and filtering bot traffic from Kasada bot mitigation solvers.
Hardcoded user IDs. do-md-ael targets 13 user IDs and 3 channel IDs. farmland_promote_fungi_cisco targets 21 IDs. iOS-Theater-Portal-Allowlist exposes 14 user IDs across development variants. seal-sheep-bear targets 7. These are production identifiers, resolvable to real Twitch accounts.
A Twitch Rivals roster. twitch-rival-turbo-sda contains streamer handles: GlitterXplosion, WavePunk, KurtBenkert, funnymike, jakenbakeLIVE, MeesterKeem, MARI, Im_Dontai, sakurashymko, a2guapo, Silky, reemknocks, thesketchreal, Jaycinco, YonnaJay, Yugi2x, tydollasign, and twitchrivals.
"Decenber." expiring_gift_promotion_dates serves a variation keyed decenber-2025. A misspelling of "December" that persists in production. It is cosmetic, but it says everything about the assumption that these configurations would never be read outside the building.
The fix
Eppo provides Client Tokens for exactly this purpose. Generate Client Tokens in Eppo's dashboard, replace the SDK Keys in the iOS app, ship an update. The endpoint, SDK integration, and evaluation logic stay the same. Only the payload format changes: from human-readable to obfuscated.
Scope
Twitch reported 35 million average daily visitors in 2024. Every iOS installation that initializes the Eppo SDK fetches these configurations automatically. Over a two-week observation window, 12 Twitch iOS users were observed generating 208 flag configuration requests across both keys. The iOS-specific key (jfJjDAgpy-B7j5...) alone accounted for 198 events from 9 users, averaging over 20 config fetches per user. The cross-platform key (3mv-BKCSZJDyZr...) was observed from 5 users.
Once a key is observed in network traffic, it can be used to poll from any HTTP client. The createdAt timestamps confirm the configurations are regenerated with current data. Flags from both keys show modifications as recent as February 26–27, 2026.
Feature flags are the operational layer between product strategy and user experience. They encode what a company is building, who they are building it for, which hypotheses they are testing, and which bets they have already made. When the configuration that controls all of this is served unobfuscated to every mobile device, the flag infrastructure does not just manage the product. It documents it, publicly, in real time.