diff --git a/Cargo.lock b/Cargo.lock
index 92169d96a..d9e2e9fd5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -73,11 +73,22 @@ checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
 
 [[package]]
 name = "bincode"
-version = "1.3.3"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
 dependencies = [
+ "bincode_derive",
  "serde",
+ "unty",
+]
+
+[[package]]
+name = "bincode_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
+dependencies = [
+ "virtue",
 ]
 
 [[package]]
@@ -675,12 +686,24 @@ version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
+[[package]]
+name = "unty"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
+
 [[package]]
 name = "utf8parse"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
+[[package]]
+name = "virtue"
+version = "0.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
+
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
diff --git a/Cargo.toml b/Cargo.toml
index 69146bb9b..aca55f79f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,7 +25,7 @@ libc = "0.2.155"
 streaming-iterator = "0.1.5"
 serde = {version = "1.0.203", features = ["derive"], optional = true}
 serde_json = {version = "1.0.120", optional = true}
-bincode = {version = "1.3.1", optional = true}
+bincode = {version = "2", optional = true, features = ["serde"]}
 tskit-derive = {version = "0.2.0", path = "tskit-derive", optional = true}
 chrono = { version = "0.4.40", default-features = false, features = ["now", "std"] , optional = true}
 
@@ -35,7 +35,7 @@ clap = {version = "4.4.6", features = ["derive"]}
 serde = {version = "1.0.203", features = ["derive"]}
 serde-pickle = "1.1.0"
 serde_json = {version = "1.0.120"}
-bincode = "1.3.1"
+bincode = {version = "2", features = ["serde"]}
 rand = "0.8.3"
 rand_distr = "0.4.0"
 
diff --git a/python/tskit_glue/Cargo.lock b/python/tskit_glue/Cargo.lock
index 855545b27..11ecb7c72 100644
--- a/python/tskit_glue/Cargo.lock
+++ b/python/tskit_glue/Cargo.lock
@@ -10,11 +10,22 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
 
 [[package]]
 name = "bincode"
-version = "1.3.3"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
+checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740"
 dependencies = [
+ "bincode_derive",
  "serde",
+ "unty",
+]
+
+[[package]]
+name = "bincode_derive"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09"
+dependencies = [
+ "virtue",
 ]
 
 [[package]]
@@ -200,3 +211,15 @@ name = "unindent"
 version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
+
+[[package]]
+name = "unty"
+version = "0.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae"
+
+[[package]]
+name = "virtue"
+version = "0.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1"
diff --git a/python/tskit_glue/Cargo.toml b/python/tskit_glue/Cargo.toml
index 535019b98..46ba2f12d 100644
--- a/python/tskit_glue/Cargo.toml
+++ b/python/tskit_glue/Cargo.toml
@@ -11,4 +11,4 @@ crate-type = ["cdylib"]
 [dependencies]
 pyo3 = "0.24.0"
 serde = {version = "1.0.203", features = ["derive"]}
-bincode = {version = "1.3.1"}
+bincode = {version = "2"}
diff --git a/src/test_fixtures.rs b/src/test_fixtures.rs
index c952eb42b..2682048c0 100644
--- a/src/test_fixtures.rs
+++ b/src/test_fixtures.rs
@@ -17,11 +17,17 @@ impl Default for GenericMetadata {
 #[cfg(test)]
 impl crate::metadata::MetadataRoundtrip for GenericMetadata {
     fn encode(&self) -> Result<Vec<u8>, crate::metadata::MetadataError> {
-        handle_metadata_return!(bincode::serialize(&self))
+        handle_metadata_return!(bincode::serde::encode_to_vec(
+            &self,
+            bincode::config::standard()
+        ))
     }
 
     fn decode(md: &[u8]) -> Result<Self, crate::metadata::MetadataError> {
-        handle_metadata_return!(bincode::deserialize(md))
+        handle_metadata_return!(bincode::serde::decode_from_slice(
+            md,
+            bincode::config::standard()
+        ))
     }
 }
 
diff --git a/tskit-derive/src/lib.rs b/tskit-derive/src/lib.rs
index 88e48c57b..e242299d0 100644
--- a/tskit-derive/src/lib.rs
+++ b/tskit-derive/src/lib.rs
@@ -30,7 +30,7 @@ fn impl_serde_bincode_roundtrip(name: &syn::Ident) -> TokenStream {
     let gen = quote::quote!(
         impl ::tskit::metadata::MetadataRoundtrip for #name {
             fn encode(&self) -> Result<Vec<u8>, ::tskit::metadata::MetadataError> {
-                match ::bincode::serialize(&self) {
+                match ::bincode::serde::serialize(&self) {
                     Ok(x) => Ok(x),
                     Err(e) => {
                         Err(::tskit::metadata::MetadataError::RoundtripError { value: Box::new(e) })