DEV Community

George Fean
George Fean

Posted on • Originally published at bundledrop.app

Patch Delivery and Full-Bundle Reliability in React Native OTA

Most OTA releases do not replace most of an application.

A production update might fix one conditional, adjust a request handler, or change a small group of bundled assets.

Yet with a full-bundle-only delivery model, every eligible device still downloads the complete JavaScript and asset payload.

That model is easy to reason about. It is also often wasteful.

Patch delivery solves that efficiency problem by transferring a representation of what changed instead of sending the entire release again.

But patches introduce another question:

What happens when the device cannot safely use the patch?

That is where OTA delivery becomes more interesting than simply calculating the smallest possible download.

A production system needs to optimize network transfer without making that optimization a requirement for reaching a valid release. That is the principle behind Bundle Drop’s hybrid approach: a patch can be the smaller route to a release, while the complete verified bundle remains available as the dependable route. (Bundle Drop)

Why patch delivery is useful

Imagine a large React Native application where a release changes only a few lines of JavaScript.

The generated production bundle still contains the rest of the application module graph, dependencies, framework code, and other unchanged content.

If the update system always sends complete bundles, the amount of data transferred is tied more closely to the size of the application than to the size of the change.

That matters because mobile networks are not uniform.

Users can be on metered connections, high-latency networks, unstable Wi-Fi, or background execution windows that disappear before a large download completes.

A smaller transfer generally spends less time exposed to those conditions and consumes less user bandwidth. (Bundle Drop)

The advantage compounds when a team ships frequently.

A sequence of small fixes does not need to mean repeatedly transferring the majority of the same JavaScript bundle to every device.

When a client has the correct starting state, a patch can make the transfer cost look much more like the release itself.

The patch has a dependency that a full bundle does not

A complete release bundle is self-contained from the client’s perspective.

If the platform and runtime compatibility rules match, the device can validate the artifact without reconstructing it from a previously installed OTA state.

A patch is different.

It describes a transition from an expected source state to a target state.

That means the source matters.

This sounds simple until you think about a real production fleet.

Some users skipped an earlier update.

Some installed the application recently and only have the bundle embedded in the App Store or Play Store binary.

Some were offline during a rollout.

Some received an earlier release and then recovered from it.

Others may have been in different rollout or targeting cohorts.

Production devices rarely form one perfect linear chain of versions. (Bundle Drop)

If a patch only works from version B to version C, a device currently running version A needs another route.

That should not automatically become an application error.

It can simply mean the optimized route is not appropriate for that device.

Treat patching as an optimization, not a release prerequisite

There are two obvious extremes.

The first is to always send complete bundles.

That gives every eligible device a self-contained artifact and keeps the delivery model simple.

The downside is repeated over-transfer.

The second extreme is to make patches mandatory.

That minimizes transfer size when the expected source state exists, but every patch prerequisite becomes part of deployment correctness.

Now you have to think about missing source versions, multiple patch paths, reconstruction failures, and devices whose local state does not match the expected chain.

A better model is to separate the destination from the transport.

The release is the complete verified result.

The patch is one possible way of getting there.

If the patch can safely produce that result, use it.

If it cannot, fetch the complete release instead. (Bundle Drop)

That gives the system an important invariant:

Every successful delivery path converges on the same verified release.

Release selection and transport are separate problems

Another useful distinction is between deciding which release a device should receive and deciding how that release should be transferred.

A device might first be evaluated against:

channel, platform, runtime compatibility, rollout percentage, targeting rules, and release state.

Only after the system selects an eligible release does patch availability matter.

Two devices can therefore be eligible for the same release but receive it differently.

One may already have a suitable source bundle and use an optimized patch.

Another may need the complete bundle.

Both should converge on the same target release.

Bundle Drop’s current upload documentation reflects that separation: uploads become versioned OTA bundles, patch optimization is prepared afterward, and eligible installations can use the full bundle while patch work is still being prepared. If patching is not efficient, the system deliberately uses the full bundle instead. (Bundle Drop)

Verification matters more than transfer size

A patch being small does not make it safe.

A successful HTTP response does not make it safe either.

The useful boundary is whether the intended complete target exists locally and has passed the validation required before staging.

A patch can download correctly and still fail to reconstruct the expected result.

A transfer can be interrupted.

Local data can be incomplete.

The device can run out of storage.

The application can be terminated midway through work.

Those are ordinary failure modes in mobile software.

The system should have a binary outcome:

the complete intended release is present and verified, or the current working bundle remains active.

There should not be a halfway state where partially reconstructed content becomes executable. (Bundle Drop)

This is also why transport logic should ideally stay below the application-facing API.

Product code should be able to ask for an update and receive a staged release without branching into separate business logic for “patch mode” and “full bundle mode.”

The transport is an implementation decision.

The release state is the application concern.

Full-bundle fallback does not mean ignoring errors

Fallback is not magic recovery.

If the device has no usable connection, lacks storage, or cannot validate the complete artifact either, the update still cannot be staged.

The correct behavior is to keep running the existing verified bundle and try again later according to the application’s update policy.

The purpose of the full bundle is narrower:

a device should not be stranded just because the optimized patch route is unavailable.

That distinction matters.

Transport fallback handles a delivery-path problem.

It does not fix a bad release.

If the target JavaScript itself is faulty, that becomes a rollback or recovery problem instead. The canonical Bundle Drop resource explicitly treats transport reliability and release correctness as separate concerns. (Bundle Drop)

Progressive rollouts make mixed device states normal

Percentage rollouts intentionally create different device states.

During a staged rollout, some installations have the candidate release while others still run the previous one.

Targeted release rules can create additional valid branches.

Server-side rollbacks can change future release selection.

Device-side recovery can move an installation back to an earlier verified bundle.

In other words, the fleet becomes heterogeneous by design.

That makes a delivery model that assumes every device is always exactly one release behind increasingly fragile.

Patch optimization can still work well in that environment, but only when it is allowed to be conditional.

Devices that have the expected starting state use the smaller route.

Devices with different histories use the complete bundle.

The rollout system can then focus on release health instead of maintaining one perfectly uniform transport chain. (Bundle Drop)

Why this matters operationally

It is tempting to evaluate an OTA system by the smallest patch it can produce.

That is not a very useful production metric on its own.

A better set of questions is:

Can every compatible and eligible installation reach the release?

What happens when the optimized path cannot be used?

Does the current working bundle remain active after a failed delivery?

Do patch and full-bundle paths converge on the same staged result?

Are old and unusual device histories tested before broad rollout?

Those questions are less exciting than “our update was only 30 KB,” but they are much closer to the real job of release engineering. The source article makes the same point: predictable reachability and safe activation matter more than a perfect efficiency ratio. (Bundle Drop)

Optimize both, force neither

Patch delivery and full-bundle delivery are sometimes treated like opposing architectures.

They do not have to be.

A smaller transfer is useful because most releases change only part of an application.

A complete release artifact is useful because production devices do not share one clean history.

The two solve different problems.

Patches optimize transport.

Full bundles preserve an independent route to the release.

Verification decides whether the result can be staged.

That is the model Bundle Drop currently uses for React Native and Expo OTA delivery: the public SDK describes hybrid transport as maintaining full-bundle integrity while supported devices download patch-sized changes. (GitHub)

The important idea is broader than any one platform:

Bandwidth optimization should not become a new condition for deployment correctness.

The original technical resource for this article is:

https://bundledrop.app/resources/patch-delivery-full-bundle-reliability

Top comments (0)