diff --git a/examples.md b/examples.md
index 15da4e3..8ef0520 100644
--- a/examples.md
+++ b/examples.md
@@ -252,7 +252,7 @@ Esy allows you to export built dependencies and import pre-built dependencies.
     ...(Build job)...
 
     # Re-export dependencies if anything has changed or if it is the first time
-    - name: Setting dependency cache 
+    - name: Setting dependency cache
       run: |
         esy export-dependencies
       if: steps.restore-cache.outputs.cache-hit != 'true'
@@ -428,14 +428,214 @@ When dependencies are installed later in the workflow, we must specify the same
 
 ## Rust - Cargo
 
+### Simple end product build
+
+If `Cargo.lock` is checked into git, its hash can be used as a key
+to cache filesystem state suitable for the build. Use the `--locked` option
+with cargo build and test commands to ensure that the state cached at the
+post step corresponds to the contents of `Cargo.lock` that were hashed for
+the key.
+
 ```yaml
-- uses: actions/cache@v2
+- name: Cache cargo dependencies
+  uses: actions/cache@v2
   with:
     path: |
-      ~/.cargo/registry
-      ~/.cargo/git
-      target
-    key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+      ~/.cargo/registry/index
+      ~/.cargo/registry/cache
+      ~/.cargo/git/db
+    key: cargo-deps-${{ hashFiles('**/Cargo.lock') }}
+- name: Cache cargo build
+  uses: actions/cache@v2
+  with:
+    path: target
+    key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }}
+```
+
+### A separate job to fetch and cache the dependencies
+
+The files cached from `$CARGO_HOME` are platform-independent.
+If cargo build/test jobs are run on a matrix and `Cargo.lock` changes often,
+it might make sense to populate the cache with the matching state in one job,
+then reuse it in the matrix jobs.
+
+This example also uses a separate cache to avoid expensive syncs with the
+`crates.io-index` repository.
+
+```yaml
+jobs:
+  update-deps:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+
+      - id: cargo-deps
+        name: Cache cargo dependencies
+        uses: actions/cache@v2
+        with:
+          path: |
+            ~/.cargo/registry/index
+            ~/.cargo/registry/cache
+            ~/.cargo/git/db
+          key: cargo-deps-${{ hashFiles('**/Cargo.lock') }}
+
+      - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }}
+        id: ls-crates-io-index
+        name: Get head commit hash of crates.io registry index
+        shell: bash
+        run: |
+          commit=$(
+            git ls-remote --heads https://github.com/rust-lang/crates.io-index.git master |
+            cut -f 1
+          )
+          echo "::set-output name=head::$commit"
+      - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }}
+        name: Cache cargo registry index
+        uses: actions/cache@v2
+        with:
+          path: ~/.cargo/registry/index
+          key: cargo-index-${{ steps.ls-crates-io-index.outputs.head }}
+          restore-keys: cargo-index-
+
+      - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }}
+        name: Fetch dependencies and update registry index
+        run: cargo fetch --locked
+
+  test:
+    needs: update-deps
+    strategy:
+      matrix:
+        os: [ubuntu-latest, windows-latest, macos-latest]
+    runs-on: ${{ matrix.os }}
+    steps:
+      - uses: actions/checkout@v2
+
+      # https://github.com/actions/runner/issues/498
+      - if: ${{ runner.os == 'Windows' }}
+        name: Fix up Cargo.lock hash
+        shell: powershell
+        run: |
+          Get-ChildItem . -Recurse -Filter Cargo.lock |
+          Foreach-Object {
+            ((Get-Content $_.FullName) -join "`n") + "`n" |
+            Set-Content -NoNewline $_.FullName
+          }
+
+      - name: Restore cargo dependencies
+        uses: actions/cache@v2
+        with:
+          path: |
+            ~/.cargo/registry/index
+            ~/.cargo/registry/cache
+            ~/.cargo/git/db
+          key: cargo-deps-${{ hashFiles('**/Cargo.lock') }}
+
+      - name: Build and test
+        uses: actions-rs/cargo@v1
+        env:
+          CARGO_INCREMENTAL: 0
+        with:
+          command: test
+          args: --locked
+```
+
+### Testing a library
+
+Rust library projects typically [do not put][cargo-faq] `Cargo.lock` under
+version control. It can be generated with the `cargo generate-lockfile` command
+assisted by the registry index cache that is used and possibly updated
+for every workflow run. The same index cache is reused by the test jobs.
+
+[cargo-faq]: https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries
+
+```yaml
+jobs:
+  update-deps:
+    runs-on: ubuntu-latest
+    outputs:
+      crates-io-index-head: ${{ steps.ls-crates-io-index.outputs.head }}
+    steps:
+      - uses: actions/checkout@v2
+
+      - id: ls-crates-io-index
+        name: Get head commit hash of crates.io registry index
+        shell: bash
+        run: |
+          commit=$(
+            git ls-remote --heads https://github.com/rust-lang/crates.io-index.git master |
+            cut -f 1
+          )
+          echo "::set-output name=head::$commit"
+
+      - name: Cache cargo registry index
+        uses: actions/cache@v2
+        with:
+          path: ~/.cargo/registry/index
+          key: cargo-index-${{ steps.ls-crates-io-index.outputs.head }}
+          restore-keys: cargo-index-
+
+      - name: Generate Cargo.lock
+        run: cargo generate-lockfile
+
+      - id: cargo-deps
+        name: Cache dependency crates
+        uses: actions/cache@v2
+        with:
+          path: ~/.cargo/registry/cache
+          key: cargo-deps-${{ hashFiles('Cargo.lock') }}
+
+      - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }}
+        name: Fetch dependencies
+        run: cargo fetch --locked
+
+      - name: Upload Cargo.lock
+        uses: actions/upload-artifact@v2
+        with:
+          name: lockfile
+          path: Cargo.lock
+
+  test:
+    needs: update-deps
+    strategy:
+      matrix:
+        os: [ubuntu-latest, windows-latest, macos-latest]
+    runs-on: ${{ matrix.os }}
+    env:
+      CARGO_INCREMENTAL: 0
+    steps:
+      - uses: actions/checkout@v2
+
+      - name: Download Cargo.lock
+        uses: actions/download-artifact@v2
+        with:
+          name: lockfile
+
+      - name: Restore cargo registry index
+        uses: actions/cache@v2
+        with:
+          path: ~/.cargo/registry/index
+          key: cargo-index-${{ needs.update-deps.outputs.crates-io-index-head }}
+          # May miss on Windows:
+          # https://github.com/actions/cache/issues/330#issuecomment-637701649
+          restore-keys: cargo-index-
+
+      - name: Restore dependency crates
+        uses: actions/cache@v2
+        with:
+          path: ~/.cargo/registry/cache
+          key: cargo-deps-${{ hashFiles('Cargo.lock') }}
+
+      - name: Build
+        uses: actions-rs/cargo@v1
+        with:
+          command: build
+          args: --all-targets --locked
+
+      - name: Test
+        uses: actions-rs/cargo@v1
+        with:
+          command: test
+          args: --locked
 ```
 
 ## Scala - SBT