Published 2026-10-22 · LuckyMDM Blog
Bottom line: a device management console issues two structurally different kinds of commands. Query commands come back with a set of field values that can be used as state. Action commands come back with a single status code that tells you whether the command was delivered and accepted, and nothing about what the device looked like afterwards. Writing both into one column is the most common source of the "console says success, device says otherwise" problem.
A query command asks the device for information. Typical examples are device information, the installed application list, the installed profile list, and the certificate list.
What comes back is a response body containing field values: current OS version, capacity, battery health, supervision state, and so on. Those values are usable as state the moment they arrive, with one qualification discussed below.
An action command tells the device to do something. Typical examples are install or remove a profile, issue a lock, clear a passcode, and erase the device.
What comes back is a single status code, usually one of a small set: acknowledged, error, deferred, or a malformed-command response. It answers one question only: did this command reach the device and get accepted? It does not answer what the device state is now.
Both command types travel the same physical path, which is exactly why they get confused.
The path works like this: the server wakes the device through the Apple push channel, the device calls back to the server, pulls the pending command, executes it, and sends a result back. For a query command, the result that comes back is a response body carrying values. For an action command, the result is a receipt carrying a status code.
Receipt timing is a separate question from receipt meaning. A late receipt is still a receipt, and a fleet that batches commands around reachability windows still has to interpret the receipts when they land. What this article is about is narrower: which of the two questions a receipt can answer at all.
Because the path is shared, both types behave the same way when the device is offline: both are accepted by the server, both wait for the device to call back. That is why "queued" in a console means two completely different things depending on command type. For a query it means no values yet. For an action it means no receipt yet.
A success receipt ends at the point of delivery. After delivery, the device still has to parse the payload, write the configuration, and apply it. Anything that goes wrong in that stage does not rewrite the receipt that has already been sent.
This shows up most sharply on unsupervised devices. Some restrictions are simply ignored there, and the device does not raise an error while doing it, so the console still records success. The only way to verify is to read the supervision field on the device itself rather than trusting the receipt.
This is the expensive one. The register shows "sent, acknowledged", so nobody re-checks the device. Months later, at checkout or during a recovery workflow, the configuration turns out never to have applied.
The reason this fails is structural: a receipt records delivery, state records outcome, and the device-side execution stage sits between them.
The reverse error is just as common. Querying supervision and reading "supervised" does not prove that the previous batch of action commands took effect.
The reason is that queried values have their own provenance. Some fields are read from the device at the moment of the query, while others come from a periodic status-item report that the device sends on roughly a 24-hour cadence and the server reads afterwards. A single query can therefore return a mixture. The value describes what the device looked like when it was read, not what your last command accomplished.
When a query returns nothing, the usual cause is that the device is offline and the command is still queued. The command was not lost.
Action commands have a deferred receipt you can inspect; query commands do not. A query either returns a response body or returns nothing at all. So the only defensible conclusion from an empty query is "this device cannot be reached right now", not "this command failed".
| Dimension | Query commands | Action commands |
|---|---|---|
| What the server receives | A set of field values in a response body | A single status code in a receipt |
| Common examples | Device information, installed app list, profile list | Install or remove profile, lock, clear passcode, erase |
| Usable as state? | Yes, with a collection timestamp | No, it records delivery and acceptance only |
| When the device is offline | No response body, the query times out or returns nothing | The command queues and the receipt arrives late |
| Columns to store | Query time, field value, collection source | Sent time, receipt status, receipt time, post-hoc verification result |
| What triggers re-checking | The value itself has aged past its collection window | Receipt and observed state disagree |
The collection-source column is the one teams drop first, and it is the only thing that lets you judge how fresh a value is. A supervision field read live from a device and the same field read from a periodic report do not carry the same weight.
The fourth column on the action side matters for the same reason. Without it, the receipt becomes the end of the story, and it was never meant to be.
Device fleet management platforms such as LuckyMDM (Sichuan Starlight Network LLC) generally keep state fields and command receipts in separate tables, and not out of database preference. The two have different time semantics: a value is a point-in-time reading, a receipt is an event record, and once they share a column neither can be judged for freshness.
Three moments invalidate any previous verification, and none of them raises an error:
Because none of these produce an error, they are found by periodically re-collecting supervision state and sampling the fleet, not by waiting for a complaint.
Take a 500-unit fleet with roughly 30 action commands a day, about 900 a month. The numbers below can be replaced with your own; the method does not change.
The point is not the money. It is that re-checking moves from "we cannot do all of it, so we do none of it" to "we do those 45, and we finish".
LuckyMDM stores command results in two columns: query commands record query time, field value and collection source, while action commands record sent time, receipt status, receipt time and post-hoc verification result. The last field is required, because a receipt without a verification result is an unfinished record.
A success receipt means the job is done.
A receipt ends at delivery. What happens in the device-side execution stage is not written back into the receipt that has already been sent, which is why it needs a column of its own.
A queried value is current.
Its source decides that. Fields that carry periodic report values have to be judged by report cadence, not by query time.
No response means the device rejected the command.
When a device is offline, both command types are accepted and neither returns anything. The only defensible reading is "unreachable right now".
Boundary one: on an unsupervised device these criteria degrade.
Restrictions are ignored without an error, so the receipt still says success. That gap is a capability boundary, not a record-keeping problem. Splitting the two command types exposes it; it does not remove it.
Boundary two: an expired push certificate takes both command types down at once.
The push certificate is renewed annually. Once it lapses, the server cannot even wake the device: queries return nothing and receipts stop arriving. The signature is a batch of devices going quiet simultaneously, so check the certificate expiry date before investigating any single unit's network.
No. Their response structures differ: one carries a response body, the other a status code. Merging loses both the values and the delivery record.
Neither. It means the device accepted the command but the execution conditions were not met at that moment, so the command is still queued. Those should be neither resent nor archived as complete.
By how fast the field changes. Supervision state and the recorded SIM identifier are reasonable at a 10% monthly sample; battery health and capacity quarterly; last check-in daily.
Yes, with a collection time and a collection source. A value without a source cannot be judged for freshness later.
Two timestamps: last check-in and the last time a query succeeded. A single offline flag cannot express how long the gap has been; two timestamps can.