diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 862e93be83cd2348b87801e526029f2dfd8a98db_LmdpdGxhYi1jaS55bWw=..9be2e5b333c4431a522c6c1fab5659da47a8636a_LmdpdGxhYi1jaS55bWw= 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -10,6 +10,7 @@
   BASE_IMAGES_MERCURIAL: $BASE_IMAGES_COLLECTION/mercurial
   # good enough for now, will have to depend on branch at some point:
   MERCURIAL_RUST_DEP_REVISION: default
+  CARGO_HOME: ${CI_PROJECT_DIR}/cargo_home
 
 
 check-sdist:
@@ -50,6 +51,16 @@
   script:
     - ./run-all-tests
 
+.cargo-cache:
+  cache:
+    key: cargo-${CI_COMMIT_HG_BRANCH}
+    paths:
+      # not caching bin/ nor .crates files as these are for installed binaries
+      # and should be treated as artifacts instead
+      - ${CARGO_HOME}/registry/index/
+      - ${CARGO_HOME}/registry/cache/
+      - ${CARGO_HOME}/git/db/
+
 tests-rust:
   stage: main
   image: ${BASE_IMAGES_COLLECTION}/hgitaly-rust:${CI_COMMIT_HG_BRANCH}
@@ -53,6 +64,9 @@
 tests-rust:
   stage: main
   image: ${BASE_IMAGES_COLLECTION}/hgitaly-rust:${CI_COMMIT_HG_BRANCH}
+  extends: .cargo-cache
+  cache:
+    policy: pull-push
   script:
     - ci/prepare-rhgitaly
     - cargo test --manifest-path rust/Cargo.toml
@@ -56,6 +70,10 @@
   script:
     - ci/prepare-rhgitaly
     - cargo test --manifest-path rust/Cargo.toml
+  artifacts:
+    expire_in: 1d
+    paths:
+      - rust/target
 
 tests-hg-current:
   variables:
@@ -68,6 +86,9 @@
 gitaly-comparison:
   extends:
     - .pytests
+    - .cargo-cache
+  cache:
+    policy: pull
   stage: compat
   image: ${BASE_IMAGES_COLLECTION}/heptapod-gitaly:${CI_COMMIT_HG_BRANCH}
   variables: