---
title: "Use Freeze to Cache Expensive Notebooks"
description: "Avoid re-executing costly computations (MCMC, deep learning, simulations) on every docs build using Quarto's freeze feature."
tags: [Build, Deployment, CI\/CD]
---

# Use Freeze to Cache Expensive Notebooks

Great Docs enables `freeze: auto` by default, which means executable code cells are only
re-executed when their source `.qmd` file changes. This recipe explains how freeze works in
practice and how to manage the cache for expensive notebooks.

## How It Works

Great Docs uses Quarto's `freeze` mechanism to cache execution outputs in a `_freeze/` directory:

1. **First build**: all executable cells run and their outputs are cached
2. **Subsequent builds**: only pages whose `.qmd` source has changed are re-executed
3. **Cache round-trip**: Great Docs automatically restores `_freeze/` into the build directory
   before rendering, and copies the updated cache back to the project root after rendering

No configuration is needed — this works out of the box.

## Managing Expensive Pages

For pages with especially expensive computations (MCMC sampling, large simulations, GPU workloads),
you may want finer control. Use `freeze: true` in the page's frontmatter to lock it completely:

```{.yaml filename="user_guide/benchmarks.qmd"}
---
title: "Benchmarks"
freeze: true
---
```

With `freeze: true`, the page is *never* re-executed during a project render, even if its source
changes. The only way to update its outputs is an explicit `great-docs freeze`.

## Updating the Freeze Cache

When you change a frozen page's source code or input data, use the `great-docs freeze` command to re-execute it and update the cache:

```{.bash filename="Terminal"}
great-docs freeze user_guide/benchmarks.qmd
```

This command:

1. Renders the specified page inside the build directory (always executing code)
2. Copies the updated `_freeze/` entries back to your project root
3. Tells you exactly what to commit

You can freeze multiple pages at once:

```{.bash filename="Terminal"}
great-docs freeze user_guide/benchmarks.qmd user_guide/mcmc-demo.qmd
```

Or specify a custom persistence directory:

```{.bash filename="Terminal"}
great-docs freeze user_guide/benchmarks.qmd --freeze-dir docs/_freeze
```

The command prints a ready-to-use `git add` + `git commit` hint when it finishes.

## CI Workflow

The `great-docs setup-github-pages` command generates a workflow with built-in freeze caching using
`actions/cache`. The cache key includes both your dependency lockfile and `.qmd` content hashes:

```{.yaml filename=".github/workflows/docs.yml"}
- name: Restore freeze cache
  uses: actions/cache@v4
  with:
    path: _freeze/
    key: freeze-${{ hashFiles('**/uv.lock', ...) }}-${{ hashFiles('**/*.qmd') }}
    restore-keys: |
      freeze-${{ hashFiles('**/uv.lock', ...) }}-
      freeze-

- name: Build docs
  run: great-docs build
```

This ensures that dependency updates (new package releases, bugfixes) automatically invalidate the
cache, while documentation-only changes get fast partial cache hits. GitHub Actions caches are
branch-scoped, so PR branches benefit from `main`'s cache but never pollute it.

## Advanced: Additional Pre-render Scripts

If you need custom scripts to run before rendering (e.g., data generation), add them via `pre_render`. Great Docs automatically runs the freeze restore *before* your scripts so you don't need to include it yourself:

```{.yaml filename="great-docs.yml"}
freeze: auto
pre_render:
  - scripts/generate-data.py
```

Scripts run in order after the freeze restore, and each must exist at the specified path relative to your project root.

## When to Re-execute

The freeze cache should be refreshed when:

- Input data changes (not just source code)
- Package API changes affect output
- You want to update rendered figures or tables

To re-execute specific pages:

```{.bash filename="Terminal"}
great-docs freeze user_guide/benchmarks.qmd
```

To force a full re-execution of all frozen pages, use `--clean`:

```{.bash filename="Terminal"}
great-docs freeze --clean user_guide/benchmarks.qmd user_guide/sampling.qmd
```

## Build Log

When freeze is configured, the build log reports it:

```
 Step 1  Prepare build directory ················· Ready
          Freeze mode: auto
```

This confirms that the freeze configuration is active and the cache restore will happen automatically.

## Per-Page Overrides

Since freeze is enabled project-wide by default, all executable pages are cached. To force a
specific page to always re-execute, add `freeze: false` to its frontmatter:

```{.yaml filename="a-page-that-must-always-execute.qmd"}
---
title: "Live Status"
freeze: false
---
```

This is useful for pages that pull live data or display current status information.

## Disabling Freeze

To disable freeze entirely and re-execute all pages on every build, set `freeze: false` in
`great-docs.yml`:

```{.yaml filename="great-docs.yml"}
freeze: false
```
