A progress bar at 100% can precede a failed verification or activation of the new level. The download may be complete while decompression, verification or activation has failed. A dependable content-delivery system tracks those stages separately and keeps the previous usable content intact until replacement is ready.
Additional levels, voice packs and high-resolution textures can reduce the initial installation burden. They also introduce dependencies on storage, connectivity, operating-system scheduling and content versions. The design must explain what the player can do when any of those dependencies is unavailable.
Describe content with a versioned manifest
A manifest identifies the packages a particular app build can use. For a custom content system, record a package identifier, content version, size, integrity information, dependencies and supported client capabilities. Separate the catalogue from a temporary download address so an expired URL does not change the identity of the content.
Use immutable package versions. Replacing bytes at an existing address while keeping the same version makes cache behaviour unpredictable and can invalidate a partial download. If content changes, publish a new version and manifest reference.
Manifest item | Reason to include it | Failure it helps diagnose |
Package ID and version | Selects an exact content release | A client loading a stale cached level |
Compressed and expanded sizes | Supports storage planning | Enough room to download but not unpack |
Hash and trusted metadata | Checks the expected bytes | A damaged or substituted package |
Dependencies | Orders required packages | A level missing its shared material library |
Client compatibility | Prevents unsupported content activation | An older engine unable to read a new format |
Choose a platform delivery mode deliberately
Google Play Asset Delivery supports install-time, fast-follow and on-demand asset packs. Install-time packs arrive with installation; fast-follow delivery starts automatically after installation; on-demand packs are requested during app use. Asset packs contain assets rather than executable code.
Google also warns that the app cannot assume the files or locations of fast-follow and on-demand packs remain unchanged between sessions. Query their current availability through the integration. After an app update, previously downloaded packs can be invalidated while updates are applied, so the new binary needs an “update in progress” state.
On iOS, a custom file-transfer implementation can use a background URLSession for appropriate downloads. The system manages scheduling, and transfers can continue while the app is suspended. Recreating the session with the same identifier is part of handling supported system relaunch scenarios. This does not guarantee that every download starts immediately or survives every kind of termination.
A custom CDN and platform-managed delivery have different responsibilities. Decide which layer owns retries, storage locations, patching and lifecycle events. Adding a second independent downloader around a managed pack can create duplicated transfers and conflicting cleanup.
Budget peak storage, not only final content size
Consider a hypothetical update where the old package occupies 300 MB, the new compressed download is 120 MB and the replacement expands to 360 MB. If all three must coexist, package-related peak storage reaches 780 MB before temporary patch files, metadata and unrelated app data.
If the old 300 MB already exists, this example needs at least 480 MB of additional space for the compressed and expanded replacements alone. It is not a universal platform formula: an actual patcher may use different staging and copying strategies. Measure its peak usage on a real device.
Check storage before starting and handle exhaustion during transfer or expansion. Another application can consume space after the first check. Keep recoverable player saves outside disposable content cleanup, and never use a broad delete operation that removes both caches and progress.
Make resumable downloads refer to the same bytes
A partial transfer is useful only if the remaining bytes belong to the same representation. When using HTTP range requests, validate the response and relevant validators. A server that ignores a range and returns a complete body must not have that body appended blindly to an existing partial file.
Compare the expected package version and integrity data when resuming. If the content changed, discard the incompatible partial package or restart safely. If a signed download URL expires, obtain another authorised URL for the same package instead of treating the old link as an account failure.
Persist enough transfer state to recover after process termination. Handle duplicate completion events and a completed file whose final bookkeeping was interrupted. A transfer record can identify the package, bytes received, staging path and validation state without storing unnecessary user information.
Verify, unpack and activate as separate steps
Download to a staging location that gameplay does not read.
Confirm the expected package size and integrity information.
Extract using limits on expanded size, file count and allowed paths.
Check dependencies and compatibility with the installed client.
Switch the active content reference only after validation succeeds.
Remove obsolete packages according to a recoverable cleanup policy.
A file hash detects a mismatch against a trusted expected value. It does not establish authenticity if an attacker can replace both the package and its unsigned manifest. Protect delivery metadata with an appropriate trust mechanism, and use supported cryptographic libraries rather than inventing a signature format.
Archive extraction is another boundary. Reject paths that escape the intended directory and enforce bounds against unexpectedly large expansion. A corrupted package must fail validation without modifying the active installation.
Show progress for the actual stage
“Downloading 80 MB of 120 MB” measures received payload. “Preparing level” describes local work after transfer. Keep those states visible instead of leaving a completed percentage on screen while the phone decompresses data.
For an illustrative 120 MB decimal package on a sustained 12 megabit-per-second connection, the ideal payload transfer takes 80 seconds: 120 multiplied by eight, divided by 12. That excludes overhead, pauses, verification and expansion. Use observed throughput to update an estimate, and avoid a countdown that assumes the connection will remain constant.
Offer cancellation where the design supports it and explain whether partial data is retained. Respect the player's network choices for large optional transfers. If a download is required for a selected mode, identify that dependency before entering an otherwise unusable match or level.
Coordinate patches with the content catalogue
A delta patch depends on an exact base package. Applying a patch intended for version 5 to version 4 can produce unusable content even if the patch file downloaded correctly. Verify the base identity before patching and validate the finished result afterward.
If patching fails, fall back to a complete package only when storage, permissions and the product's data-use policy allow it. Repeating the same failing patch forever wastes bandwidth. Keep enough diagnostic information to distinguish a bad base, missing space, unsupported format and damaged transfer.
Avoid activating content from two catalogue versions
A level can depend on a shared shader pack and a sound bank. Downloading each package successfully does not prove that their versions belong together. Resolve a compatible dependency set from one catalogue snapshot, and activate that set as a unit where the content system supports it.
During a live event, an older cached catalogue may refer to packages the server has already removed. Retain packages for the supported catalogue window or provide a tested refresh path. Content cleanup should follow actual client compatibility, not merely the latest release's needs. Record the catalogue version with failures so support can distinguish a missing dependency from a damaged download.
Test the handover into gameplay
Stop the process halfway through transfer, extraction and activation.
Remove an optional package, then request the level that needs it.
Expire a download URL during a resumable transfer.
Launch an updated binary before its managed assets are ready.
Load an old manifest from cache and verify compatibility checks.
Exhaust storage after download but before extraction completes.
Measure success as ready-to-play content, not just a successful HTTP response. Record transfer failures, validation failures, expansion failures and activation failures separately. That breakdown tells the team whether to investigate the network, package pipeline, storage budget or game client.