Caching strategy and reruns

library(nlmixr2targets)

What triggers a re-fit?

nlmixr2targets builds on targets, which caches every target keyed by a hash of its command, its dependencies, and its inputs. When you call tar_make(), only targets whose hash has changed (directly or transitively) are rebuilt.

For a single tar_nlmixr(name = <name>, ...) call, the five targets generated are:

Target Stores Hashed inputs
<name>_object_simple md5 string identifying the simplified ui in the indirect cache the captured object expression
<name>_covariates sorted names of the covariates the model reads <name>_object_simple
<name>_data_simple simplified data frame <name>_covariates, the captured data expression, the table$keep columns, and est/control (methods like est = "vae" also keep their covariate-search columns)
<name>_fit_simple fitted nlmixr2 object <name>_object_simple, <name>_data_simple, est, control
<name> final fit, with labels and metadata restored <name>_fit_simple, the captured object (re-read for labels), data

The single most important property of this layout is that <name>_fit_simple depends only on the structural content of the model. nlmixr_object_simplify() strips parameter labels and the model’s metadata environment before caching, so cosmetic edits to either do not invalidate the expensive estimation step.

The simplified data, in turn, depend on the model only through <name>_covariates. A model edit re-runs the cheap _covariates target, and when the covariate names come out the same, _data_simple is skipped rather than rebuilt.

Examples of common edits

# Adding a comment, changing a label, or editing meta:
#   only re-runs the cheap `_object_simple` and the final `<name>` target
#   (the relabel/meta-restore step). The expensive `_fit_simple` is reused.

# Changing initial values (`ini({...})`) or the model structure
# (`model({...})`) without changing which covariates it reads:
#   re-runs `_object_simple`, `_covariates`, `_fit_simple` and the final
#   target. `_covariates` returns the same names, so `_data_simple` is
#   skipped.

# Adding a covariate to the model, or removing one:
#   re-runs everything from `_object_simple` onward, including
#   `_data_simple`.

# Changing the values in a covariate column of the dataset:
#   re-runs `_data_simple` and `_fit_simple`. `_object_simple` and
#   `_covariates` are reused if the model didn't change.

# Editing a subject-constant column that the model does not use:
#   for most `est` methods nothing re-fits (`_data_simple` re-executes,
#   but its value is unchanged, so `_fit_simple` is reused). With
#   `est = "vae"` the automated covariate selection searches such
#   columns, so they are kept in `_data_simple` and the edit re-runs
#   `_fit_simple` too.

# Changing `est` or `control`:
#   re-runs the cheap `_data_simple` (they determine the columns kept
#   for method-specific covariate searches, e.g. `est = "vae"`) and the
#   `_fit_simple` and final targets. `_object_simple` is reused.

# Renaming a `tar_nlmixr_multimodel()` entry:
#   only re-runs the cheap combining target that collects the fits into a
#   named list. The name is the description that `_fit_simple` announces
#   when it runs, and it is deliberately excluded from that target's hash.

Inspecting and pruning the indirect cache

The simplified-model md5 cache lives under <tar_config_get("store")>/user/nlmixr2/. It is not removed by targets::tar_destroy(), so it can accumulate orphan files over time (e.g. after model iterations).

# Quick inventory: hashes, sizes, last-modified
nlmixr2targets_cache_status()
#>      hash size_bytes               mtime
#> 1 aaaaaa..       1234 2026-05-21 12:00:00
#> 2 bbbbbb..       1567 2026-05-21 13:30:00

# Find orphans (dry run by default)
nlmixr2targets_cache_prune()

# Delete them
nlmixr2targets_cache_prune(dry_run = FALSE)

nlmixr2targets_cache_prune() with no keep argument reads targets::tar_meta() from the current store, finds every built target whose name ends in _object_simple, and treats those hash values as reachable. Anything else in the cache directory is reported (and, with dry_run = FALSE, removed). Pass keep = character() to wipe the cache unconditionally.

tar_outdated() is a quick way to preview what would rerun

If you are about to edit a model and are unsure how invasive the change is, run

targets::tar_outdated()

after the edit but before tar_make(). The list of outdated targets is every target that may re-execute. tar_make() can still skip one whose upstream values turn out unchanged: after an edit that leaves the model’s covariates alone, _data_simple is listed but skipped. If _fit_simple is not in the list, the fit is reused; one or two entries usually means only the cheap relabel/restore step runs.