Dry-run jobs
A dry-run job runs your workload through IBM Quantum® Compute Service without using any QPU time. Use a dry-run job to do the following before you commit to a real run:
- **Get the usage that the job would incur on the real QPU.
- Validate the job. Quantum Compute checks the job's parameters, the same way it does for a real job.
- Get the circuit timing schedule, if you request it, to debug the job before you run it for real.
Unlike dry-run jobs, local testing (fake backends and Qiskit Aer) runs on your own machine and therefore cannot provide usage numbers, service-side validation, or service timing information. To compare the two approaches, see Mock devices compared to fake backends.
qiskit-ibm-runtimev0.51.0 or later is required for dry-run jobs.- Dry-run jobs are available in all regions, and are only available on the Flex, Premium, and On-Prem plans. They are not available on the Open or Pay-As-You-Go plans.
How it works
To run a dry-run job, pass dry_run=True to the primitive's run() method:
backend = service.backend("ibm_phoenix")
isa_circuit = pm.run(circuit) # transpiled for ibm_phoenix
sampler = Sampler(mode=backend)
job = sampler.run([isa_circuit], dry_run=True)
job.result() # wait for completion
print(job.usage())dry_run is an argument of the run() method (the default is False), not a runtime option. It is available to all primitives.
A dry-run job has the following characteristics:
- It runs in IBM Quantum Compute Service in the cloud, not on your machine.
- It uses the calibration data from the real QPU, not just a snapshot.
- Its results keep the expected schema and follow the expected shape of results from the real QPU, but contain randomized mock data. They are not actual or simulated measurement results, so do not use them to check physical correctness.
- Processing happens on the server, so the job might not finish immediately.
Circuit size, shots, and other limits are the same as for any job of that program.
dry_run=True also works when the backend is already a mock device.
Read the usage
The usage of a completed dry-run job is the usage the same job would incur on the real QPU, except in rare situations where calibration data changes significantly after the dry-run job and before the job on a real QPU.
job.usage()returns the usage in seconds.job.metrics()["usage"]returns the same data together with the usage status.
Dry-run usage is not charged, does not consume your plan allocation, and does not count against any limits.
Do not use job.usage_estimation on a dry-run job. Use job.usage().
job.usage() returns 0 until the usage calculation is final, so wait for the job to finish before you read it.
Circuit timing schedule
To request the circuit timing schedule, use the same option as for a real job. For full details, see Visualize circuit timing.
Limitations
- Job and batch modes only. Dry-run jobs can only run in job mode and batch mode.
- Flex, Premium, and On-Prem plans only. Dry-run jobs are not available on the Open or Pay-As-You-Go plans.
Mock devices
Mock devices are the implementation behind dry-run jobs. Dry-run jobs hide mock devices by default, but you encounter them in these cases:
- Instances configured to access only mock devices. Example: if you use
service.backend("ibm_phoenix")to submit a dry-run job onibm_phoenix, but your instance doesn't have access toibm_phoenix, you will get aQiskitBackendNotFoundError. Instead, select the mock device directly withservice.backend("mock_phoenix"). - Compute resources. Mock devices are hidden by default on the Compute resources page. The table on the page has a filter option to include them, but only the Flex, Premium, and On-Prem plans have access to mock devices.
- Workloads table. Jobs from mock devices are hidden by default on the Workloads page. The table has a filter option (the funnel icon) to display them.
- Python API.
service.backends()andservice.jobs()exclude mock devices unless you call them withinclude_mocks=True.IBMBackend.is_mockindicates whether a backend is a mock device.service.least_busy()never returns a mock device.
Mock devices compared to fake backends
The names are similar, but a mock device and a fake backend are different things. A fake backend is a local object in your Python environment. A mock device is a cloud resource in IBM Quantum Compute Service.
Column 1 | Mock device (for example mock_phoenix) | Fake backend (for example FakeManilaV2) |
|---|---|---|
| What it is | A device in IBM Quantum Compute Service | A Python class in qiskit_ibm_runtime.fake_provider |
| Where it runs | Cloud, in the service | Locally, on your machine |
| How you get it | service.backend("mock_phoenix"), or automatically with run(..., dry_run=True) | from qiskit_ibm_runtime.fake_provider import ... |
| Account and instance | Specific plans only (Flex, Premium, or On-Prem) | All instances and plans |
| Calibration | Live, matches the real device at any time | Fixed snapshot shipped with the installed package |
| Results | Randomized data with the expected schema. Not a simulation | Noisy simulation that uses the snapshot's noise model |
| Physically meaningful results | No. Never use them to check correctness | Approximately, within the limits of the noise model |
| Usage reported | Yes | None |
| Charged or counted against plan allocation or limits | No | No |
| Job validation | Done by the service, same as a real job | Limited to what the client checks |
| Timing schedule | Available on request | Not available |
| Execution modes | Job and batch mode only. Sessions are blocked | Session syntax accepted but ignored (local mode has no real sessions or batches) |
| Completion | Asynchronous, on the server | Runs locally and returns when finished |
| Shown in platform interface and API lists | Hidden by default (Compute resources, Workloads table, backends(), jobs()). Opt in to show | Never, because nothing is sent to the service |
How to choose
- To find out how much usage the job will consume, or whether the service will accept it, use a dry-run job.
- To find out what the output might look like, or to work offline, use a fake backend or Aer.
- To do both, iterate on circuits and results with a fake backend, then dry-run as the last check before the real QPU.
Common points of confusion
- A mock device is not a simulator. Its output is random, so sampling a Bell circuit on
mock_phoenixdoes not return a Bell distribution. If you want realistic noisy output, use a fake backend. - A fake backend is not the live device. Its calibration is a snapshot and might be out of date. A mock device tracks the real calibration, so transpiled circuits and timing match what the QPU sees today.
- Neither runs on real hardware. Neither consumes QPU time, but only a dry-run job goes through the service.
usage_estimationis not the dry-run estimate. For a dry-run job,job.usage()returns the seconds of usage your job would be charged on a real QPU.
Use cases
Students and courses
An administrator restricts an instance to mock devices only, using the QPU customization toggle when creating or editing the instance. Students then validate their payloads end-to-end without consuming real QPU time or RUs. Because the instance has access only to mock devices, students select the backend by its mock name:
backend = service.backend("mock_phoenix")
sampler = Sampler(mode=backend)
job = sampler.run([isa_circuit], dry_run=True)Project planning
A team about to start a project dry-runs representative jobs to see the RUs the project needs, before choosing a plan or allocation:
backend = service.backend("ibm_phoenix")
sampler = Sampler(mode=backend)
job = sampler.run([isa_circuit], dry_run=True)
job.result()
print(job.usage()) Final check before running on a real QPU
Validate parameters and inspect the timing schedule with dry_run=True, then drop the argument and run on the real QPU. Nothing else in your code changes:
sampler = Sampler(mode=backend)
# Pre-flight check
job = sampler.run([isa_circuit], dry_run=True)
job.result()
# Real run - same code, without dry_run
job = sampler.run([isa_circuit])Next steps
- Test programs on your own machine with Local testing mode.
- Learn how workload usage is measured.
- Visualize the circuit timing schedule.
- Understand resource units and the available plans.