diff --git a/rls/src/build/cargo.rs b/rls/src/build/cargo.rs
index 01f6bc8f303..6e9929adc01 100644
--- a/rls/src/build/cargo.rs
+++ b/rls/src/build/cargo.rs
@@ -260,6 +260,17 @@ fn run_cargo_ws(
         Arc::clone(&reached_primary),
     );
 
+    // Cargo excludes target/ from backups since rust-lang/cargo@cf3bfc9/rust-lang/cargo#8378 but
+    // it does so if and only if the directory does not exist and it's about to create it.
+    // rls runs cargo internally with target directory set to target/rls/ so, if target/ doesn't
+    // exist yet and rls runs, target/ and target/rls/ will be created. While target/rls/ will be
+    // excluded from backups target/ won't be (as from our perspective it's not the target
+    // directory but its parent) and, when user runs "cargo build" themselves cargo will see
+    // target/ existing already and won't exclude it from backups. We can work around that by
+    // attempting to create a backup-excluded target/ ourelves using cargo paths:: machinery.
+    cargo::util::paths::create_dir_all_excluded_from_backups_atomic(
+        config.target_dir().unwrap().unwrap().as_path_unlocked().parent().unwrap(),
+    )?;
     let exec = Arc::new(exec) as Arc<dyn Executor>;
     match compile_with_exec(&ws, &compile_opts, &exec) {
         Ok(_) => {
diff --git a/tests/client.rs b/tests/client.rs
index e01a7fdeb67..18b2b75a6dd 100644
--- a/tests/client.rs
+++ b/tests/client.rs
@@ -1,3 +1,4 @@
+use std::fs;
 use std::path::Path;
 use std::time::{Duration, Instant};
 
@@ -2227,3 +2228,30 @@ fn client_parse_error_on_malformed_input() {
     // to provide better fault tolerance.
     cmd.wait().unwrap();
 }
+
+#[test]
+fn client_cargo_target_directory_is_excluded_from_backups() {
+    // This is to make sure that if it's rls that crates target/ directory the directory is
+    // excluded from backups just as if it was created by cargo itself. See a comment in
+    // run_cargo_ws() or rust-lang/cargo@cf3bfc9/rust-lang/cargo#8378 for more information.
+    let p = project("backup_exclusion_workspace")
+        .file("Cargo.toml", &basic_bin_manifest("foo"))
+        .file(
+            "src/main.rs",
+            r#"
+                fn main() {
+                    println!("Hello world!");
+                }
+            "#,
+        )
+        .build();
+    let root_path = p.root();
+    let mut rls = p.spawn_rls_async();
+    rls.request::<Initialize>(0, initialize_params(root_path));
+    let _ = rls.wait_for_indexing();
+    let cachedir_tag = p.root().join("target").join("CACHEDIR.TAG");
+    assert!(cachedir_tag.is_file());
+    assert!(fs::read_to_string(&cachedir_tag)
+        .unwrap()
+        .starts_with("Signature: 8a477f597d28d172789f06886806bc55"));
+}