Short answer
The QGIS Graphical Modeler turns a sequence of manual algorithm runs into a single saved tool (.model3) that anyone can re-run with one dialog, in batch, or from a script. It replaces an undocumented click-path — which no one can audit or reproduce — with an explicit graph of inputs, algorithms and outputs. If you run the same chain of steps more than twice, or need to prove how a result was produced, build a model.
Why a model beats a click-path
When you process terrain by hand — fill the DEM, compute slope, reclassify, polygonise, clip to AOI — the only record is the Processing History log, and the only person who can repeat it reliably is you, that week. A model captures the logic: which algorithms, in what order, with which parameters wired to which inputs. Six months later it produces the identical result from new data, and a reviewer can read the graph instead of trusting your memory. This is the difference between an exploratory session and a workflow.
Open it from Processing ▸ Graphical Modeler (or Processing Toolbox ▸ the Create New Model button).
Anatomy of a model
A model has three kinds of node:
- Inputs — the parameters the user supplies: Vector Layer, Raster Layer, Number, Field (tied to a layer input), Extent, Distance, Boolean, Enum. Each input you add appears as a field in the run dialog.
- Algorithms — any Processing algorithm (native QGIS, GDAL, GRASS, SAGA). You drop them in and fill parameters either from a fixed value, from a model input, or from a previous algorithm's output.
- Outputs — the results you want kept. An algorithm output with no name is a temporary intermediate; give it an output name and it becomes a final deliverable exposed in the dialog.
Wiring an algorithm's output into the next algorithm's input is what makes the chain. Intermediate layers you do not name stay in memory and are discarded, keeping the project clean.
Worked example: a terrain-to-steep-zones model
Suppose you repeatedly need polygons of "steep, high-elevation" terrain from raw DEMs. The model:
- Input: Raster Layer
DEM; Numberslope_threshold(default 30); Numberelev_threshold(default 1500); Vector LayerAOI. - Fill sinks (
gdal:fillnodataorgrass:r.fill.dir) onDEM→ filled DEM (unnamed, intermediate). - Slope (
qgis:slopeorgdal:slope) on the filled DEM → slope raster. - Raster calculator (
gdal:rastercalculator) combining slope and DEM with an expression that yields 1 whereslope >= slope_threshold AND dem >= elev_threshold, else 0. Wire the two thresholds from the Number inputs. - Polygonize (
gdal:polygonize) the binary raster → polygons. - Extract by attribute keep value = 1; then Clip (
qgis:clip) byAOI. - Output: name the clip result
Steep_Zones.
Save as steep_zones.model3. Now any analyst runs it on a new DEM by picking the raster and an AOI and adjusting two numbers — no rebuilding, no forgotten step. The thresholds being inputs, not hard-coded, is what makes one model serve every project.
Expressions inside models
Model parameters accept QGIS expressions, evaluated at run time. You can build an output path from @project_folder, derive a buffer distance from another input, or set an algorithm parameter conditionally. For example a buffer distance could be @cell_size * 3, referencing a numeric model variable, so the model adapts to each DEM's resolution rather than using a fixed metre value. Expressions turn a static graph into one that responds to the data it is given.
Running over many datasets: batch mode
A model is most powerful applied to dozens of files. Right-click the saved model in the Toolbox and choose Execute as Batch Process. The batch dialog gives you a table — one row per input. Use the Autofill options to populate the layer column from a folder and to derive output filenames with a pattern (e.g. append the input name), then run the whole table unattended. This processes an entire tile set or a directory of survey areas through the identical workflow, which is exactly the reproducibility you cannot get from manual runs.
Headless execution: PyQGIS and qgis_process
Because a saved model registers itself as a Processing algorithm (model:steep_zones), it is callable programmatically:
import processing
processing.run("model:steep_zones", {
"DEM": "/data/dem_utm.tif",
"slope_threshold": 35,
"elev_threshold": 1800,
"AOI": "/data/aoi.gpkg|layername=area",
"Steep_Zones": "/out/steep.gpkg"
})
And from a shell or a scheduler, the standalone CLI runs it without opening the GUI:
qgis_process run model:steep_zones \
--DEM=/data/dem_utm.tif --slope_threshold=35 \
--elev_threshold=1800 --AOI=/data/aoi.gpkg \
--Steep_Zones=/out/steep.gpkg
This is how a model graduates from a desktop convenience to a step in an automated pipeline — nightly runs, server-side processing, CI checks on incoming data.
Common pitfalls and why they happen
- The model "works for me" but fails for a colleague. A parameter was hard-coded to a value or a path that only exists on your machine. Promote it to a model Input.
- Intermediate layers pile up and slow the run. You named outputs you did not need to keep. Leave intermediates unnamed so they stay temporary and are discarded.
- CRS mismatch errors mid-chain. Inputs in different CRSs reach an algorithm that assumes a common one. Add an explicit Reproject layer (
qgis:reprojectlayer) step early so the model normalises CRS rather than relying on the data being consistent. - Field input shows no fields. A Field input must be tied to a specific Vector Layer input; if that link is missing, the dropdown is empty.
- GRASS/SAGA step missing on another machine. Those providers must be installed and enabled. Prefer native QGIS or GDAL algorithms in shared models, or document the provider requirement.
- Batch outputs overwrite each other. The output pattern was static. Use an autofill expression that incorporates the input name so each row writes a distinct file.
QA and validation
- Run the model once interactively and compare its output to the manual result you trust before relying on batch mode.
- Keep the
.model3under version control with the project; it is plain enough to diff and is the canonical record of the workflow. - Add a final validation step inside the model where practical (e.g. Check validity on output geometry) so each run self-checks.
- Document each input's meaning in the model's Help editor — it appears in the run dialog and saves the next analyst from guessing units and defaults.
Bathyl perspective
We build a model the moment a process is going to repeat, because a model is simultaneously the tool, the documentation and the audit trail. Inputs are exposed rather than hard-coded, CRS is normalised inside the graph, and the .model3 ships with the project so the same result can be regenerated by a client or a colleague — interactively, in batch, or from a scheduler — without re-deriving the logic.
Related reading
- QGIS Field Calculator for GIS Cleanup
- QGIS Joins for Spatial Project Data
- QGIS Hillshade Workflow
- GIS and spatial analysis