Declarative Management Migration Is Not a Switch: The Dual-Run Period, the Rewrite Effort, and Four Completion Criteria

Published 2026-10-25 · LuckyMDM Blog

Bottom line: declarative device management and the older MDM protocol are not two versions of the same interface. They are two control models. The older model sends commands that say what to do; the declarative model registers declarations that say what state the device should hold. There is no automatic translator between the two, so the cost of a migration does not sit on the server-upgrade side. It sits in rewriting configuration items one by one, rebuilding the status subscription list, and maintaining both channels for as long as they run in parallel. How long that parallel period lasts depends on how many configuration items still have no declarative equivalent, not on what week the project plan says.

Why this is a control-model change rather than an interface change

The old model sends one-off commands

Under the classic protocol, the server sends a command when it wants something done, and sends a query command when it wants to know a value, then waits for the response. A command is a one-off description of an action. Once it has been executed it is finished. The server does not hold a record of what the state *should* be; it holds a record of what it sent and what came back.

That is the underlying reason state drift goes unnoticed. If a device restarts, if someone changes a setting locally, if a value is overwritten by another profile, the server has no way to know until it asks again.

The declarative model registers desired state

Declarative management inverts this. Instead of issuing commands, the server registers declarations describing the state a device should be in, and the device maintains that state on its own. When something changes, the device reports it back through the status channel. Where the server cares about a field, it subscribes to that field, and the device reports on subscription rather than being polled repeatedly.

This difference drives every cost that follows. A command is momentary; a declaration persists. Turning momentary actions into persistent state means the configuration has to be written again from scratch, and that is a rewrite, not a rename.

No translator exists, and the reason is structural

There is no automatic translator because the two models do not describe the same thing. The input to the command model is an action; the input to the declarative model is a state. From a restriction such as “camera not allowed” you can derive a command to disable the camera. The reverse does not hold: from the fact that a disable-camera command was once sent, you cannot derive that the device's desired state is camera-disabled, because someone may have changed it since, another profile may have overridden it, or the device may never have received it.

So a migration cannot be an export-and-import step. It is a per-item judgement: which declaration does this configuration map to, what is the expected value, which declaration owns it, what validity period applies. That judgement is where the hours go, and it cannot be automated away.

Sort configuration items into three buckets before writing anything

The first task in a migration is an inventory, not a rewrite. Sorting items into the wrong bucket causes rework: an item assumed to have a declarative equivalent turns out not to, and the regression testing already done for it is wasted.

BucketHow to identify itWhat to doEffort per itemMain risk
Has a declarative equivalentThe item appears in the currently published declaration list and the fleet meets the minimum OS versionRewrite as a declaration; retire the item from the old channelAbout 15 minutes including on-device regressionExpected-value syntax differs; a mistake shows up as an inverted restriction
No equivalent yetNo matching declaration, or the minimum OS version is above part of the fleetKeep it on the old channel, tag it as dual-run, review monthlyAbout 20 minutes to tag and set up a regression checkReviews lapse and the dual-run pile never shrinks
Depends on supervised stateA declaration exists but requires the device to be supervisedConfirm supervision first, then rewrite; unsupervised units stay in bucket twoAbout 25 minutes including the supervision checkDeclarations silently do not apply, which reads as a migration failure

The second bucket is what determines the length of the parallel period. The first bucket can be closed as soon as it is rewritten, and the third closes once supervision is confirmed. Only the second bucket keeps the old channel alive.

The effort is three separate accounts

Account one: rewriting configuration items

The formula is item count multiplied by per-item effort, and per-item effort must include on-device regression. Leaving regression out roughly halves the estimate. A rewrite is not a field rename: it is writing the expected value again, setting the validity period again, deciding which declaration owns it, and then confirming on a test unit that it actually took effect.

Account two: rebuilding status subscriptions

Fields that used to come back from a device-information query — device details, installed applications, OS version, available capacity, activation lock state — have to be re-registered as status subscriptions. Subscriptions are not the same thing as configuration: configuration is what the server requires of the device, subscriptions are what the server asks the device to report. Legacy systems tend to mix both inside one query command, so the migration has to separate them. Teams usually find, partway through, that several fields have never been read by anyone, and those can simply be dropped from the subscription list.

Account three: maintaining both channels during the parallel period

While both channels run, a unit carries a legacy profile and new declarations at the same time. The maintenance cost is a fixed weekly expense: every new configuration has to be written twice, every status lookup requires confirming which channel answered, and every incident starts by ruling out whether the other channel is the one taking effect. This cost scales with the number of weeks, not with fleet size.

The number of weeks is itself computable. It is roughly the time needed to empty bucket two, and that depends on how quickly declarations are published for the remaining items and how quickly the fleet's OS versions move. Neither is under the control of the platform vendor.

Worked example: 800 units, 68 configuration items

At 46 USD per hour:

The parallel period, taken as 42 days at 2 hours of dual-run maintenance per week: about 12 hours, about 552 USD. Total about 36.5 hours, about 1,680 USD.

Compare this with skipping the inventory: 68 items rewritten at 25 minutes each is about 28.3 hours, and because nothing is tagged as needing the old channel, the old channel can only be closed once everything is done, which in practice stretches to 14 weeks and 28 hours of dual-run maintenance. That totals about 56.3 hours, about 2,590 USD. The difference of roughly 910 USD comes almost entirely from the length of the second account, not from rewriting faster.

Platforms built for device fleet management, such as LuckyMDM (Sichuan Starlight Network LLC), start a migration with a configuration inventory rather than a server upgrade, and the reason is visible in that arithmetic: the larger account sits on the rewrite side, and the inventory decides the magnitude of the other two.

Four criteria for ending the parallel period

One: the declaration is actually applied on the device

Do not count declarations the server has registered. Look at what the device does. When a restriction declaration applies, the corresponding control is usually greyed out and not editable. When a settings declaration applies, it shows a concrete value. Registration succeeding is not the same as application, because between the two sits the question of whether the device received and accepted it.

Two: status subscriptions report inside the window

Every subscription needs a last-reported-time field, and the value has to be inside the window. Device information fields typically report on a cycle of about 24 hours, so a window of 24 to 48 hours is the usual choice. A unit with no report inside the window is not migrated; check its channel and its supervised state before anything else.

Three: supervised state confirmed unit by unit

A substantial part of declarative capability requires supervision. Fleets that mix manually enrolled and unsupervised units cannot treat those units as migrated just because the server was upgraded. This criterion is per unit and does not apply in batches.

Four: one week with no regression after the old channel closes

Only after the first three pass does the old channel close. After closing, keep a one-week observation window, and treat anything that appears in it as potentially caused by the closure until that has been ruled out.

LuckyMDM records three fields per unit during a migration sign-off: the applied state of each declaration, the last status-channel report time, and the supervised state. A unit leaves the dual-run list only when all three pass, and it leaves one at a time rather than as a batch.

Four checks you can run yourself

Misconceptions

Misconception 1: upgrading the server means the migration is done.

What this gets wrong is the scope of a server upgrade. Supporting the declarative protocol makes it *possible* to write declarations; the configuration itself is still in the legacy profile. The test is which channel an item sits on, not which version the server reports.

Misconception 2: the parallel period can just stay open.

The problem is that dual-run maintenance is a fixed weekly cost, and the set of things the old channel still supports may narrow as OS versions advance. The longer it stays open, the larger the catch-up at the end. The test is whether the bucket-two count falls month over month; if it does not, the reviews are not happening.

Misconception 3: writing the same restriction on both channels is safer.

Where one restriction has values on both channels, the stricter value applies on the device, so the result is neither the old value nor the new one, and troubleshooting leads in the wrong direction. The test is device-side behaviour, not what the server holds.

Boundaries

Boundaries 1: full declarative coverage requires supervised devices. On unsupervised units, some declarations do not apply or are not accepted at all. The share of such units in a fleet sets the size of bucket three and the floor under the parallel period.

Boundaries 2: declarations and their minimum OS versions are published in stages. Use the current version of Apple's Apple Platform Deployment documentation as the reference. Do not copy a list from a secondary source, and do not estimate this year's effort from last year's list.

Boundaries 3: this article covers the cost structure of a migration, not the mechanism of declarative management. Credential decoupling, asset declarations, the status channel and the shift from an online count to an effective-time count are covered separately. This piece answers only how many hours a migration takes, which three accounts make up that number, and when the parallel period can end.

Questions

Does upgrading every unit to the latest OS first remove bucket two?

Partly. Roughly half of what lands in bucket two is there for a version reason; the other half is there because no declaration exists for that configuration yet. Upgrading addresses the version half and does not address the coverage half.

Can the parallel period end per batch instead of fleet-wide?

Yes, and that is the better approach. Batch by whether bucket two has been emptied for that group — not by model or by site, since the same model can fall into different buckets depending on how it was enrolled.

Should we subscribe to as many status fields as possible?

No. Subscriptions consume reporting bandwidth and backend processing, and a field nobody reads is pure cost. Cleaning the list during the migration typically cuts the second account by about a third.

Should the old configuration be removed before migrating?

No. Running both is what the parallel period means. Removing the old channel first creates a window in which the device is not managed at all, and how long that window lasts depends on when the device next comes online, not on when the operator clicked.

How do you tell whether a vendor's migration plan is serious?

Ask for a line-item effort table. A single total price usually means no inventory was done. A table without regression time will overrun. A plan that states a fixed number of weeks for the parallel period has probably not computed how fast bucket two empties.

Criteria

All Articles