Optimize flow & paywall fetching in Kotlin Multiplatform SDK
A reliable flow or paywall fetch on Kotlin Multiplatform does three things: renders fast, returns the audience-targeted variation, and falls back gracefully when the network is slow. The rules below cover the timing, caching, and fallback patterns to get there.
The rules assume Adapty.activate() and Adapty.identify() have already resolved. See Call order in Kotlin Multiplatform SDK.
Rules and pitfalls
| Do this | Don’t do this | Why |
|---|---|---|
| Fetch the placement you’re about to show. | Prefetch all placements concurrently on launch. | Bulk prefetch blocks the main thread and produces a black screen during the burst. |
Fetch getFlow after attribution has had a chance to resolve — for example, 1–2 seconds after activate or after setOnProfileUpdatedListener fires. | Call getFlow at app launch. | Attribution hasn’t landed yet. The flow resolves against the default audience and silently bypasses segments and ASA personalization. |
Set a loadTimeout and configure a fallback paywall for every placement. | Wait on getFlow indefinitely. | Without a timeout, users on poor connectivity see a blank screen until the network resolves — or close the app. |
See Fetch paywalls and products for the fetchPolicy and loadTimeout parameter reference, and Placements for picking the right placement.
Show first-screen media from the app bundle
A flow downloads its images and videos from Adapty. To show the first screen’s media instantly, serve it from the app bundle instead. This is a good way to reuse media you already ship, such as the visuals of an existing native onboarding.
- In the Flow & Paywall Builder, set a custom media ID on the image or video. The file you upload there stays as the fallback.
- Add the file to your app resources, in
commonMain/composeResources/files/. - When you create the flow view, pass the bundled file for that ID in
customAssets:
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
val bundledAssets: Map<String, AdaptyCustomAsset> = mapOf(
"welcome_video" to AdaptyCustomAsset.localVideoResource(
path = Res.getUri("files/videos/welcome.mp4")
),
)
AdaptyUI.createFlowView(
flow = flow,
customAssets = bundledAssets,
).onSuccess { view ->
view.present()
}.onError { error ->
// handle the error
}
Bundled files add to your app’s download size, so bundle only the media users see first.
Media you don’t bundle still appears right away: the flow’s layout includes a small low-resolution copy of each image, including a video’s still frame, and shows it until the full file loads.
For the full customAssets reference, see Customize assets.
Tune for poor connectivity
For markets with consistently poor connectivity (rural areas, transit, regions affected by routing):
- Set
fetchPolicy = AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoadon every fetch except the very first. - Configure a fallback paywall for every placement in the Adapty dashboard.
- Set
loadTimeoutto 3–5 seconds and accept the fallback when the timeout fires. - Don’t gate flow display on
Adapty.getProfile(). CallgetFlowindependently so a slow profile doesn’t block the UI.