diff --git a/Cargo.lock b/Cargo.lock
index 3415cac09da72b6c920c1ce66a254588686dda1d..7152c66ddfe8ebecc5916804f0063827e46b6c6c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -504,6 +504,15 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
 
+[[package]]
+name = "checked_ops"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b491d76efc1d99d74de3c8529bee64c62312c275c7eb124f9185291de45801d5"
+dependencies = [
+ "num-traits",
+]
+
 [[package]]
 name = "chrono"
 version = "0.4.38"
@@ -658,6 +667,7 @@ dependencies = [
  "argon2",
  "axum 0.7.5",
  "bytes",
+ "checked_ops",
  "chrono",
  "either",
  "figment",
diff --git a/Cargo.toml b/Cargo.toml
index f6b23102bb1690d4f8e5bfade229cd34abcc1b85..c93c6736263d50575229de7a6c073e6593038b60 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -411,6 +411,9 @@ rev = "de26100b0db03e419a3d8e1dd26895d170d1fe50"
 version = "0.29.4"
 default-features = false
 
+[workspace.dependencies.checked_ops]
+version = "0.1"
+
 
 #
 # Patches
diff --git a/src/core/Cargo.toml b/src/core/Cargo.toml
index 2c0fc47d0ebc36917438c22844fec3fcba6bce73..e47f673e46dd4a03acf2f7d9200ea137878f23d7 100644
--- a/src/core/Cargo.toml
+++ b/src/core/Cargo.toml
@@ -53,6 +53,7 @@ sha256_media = []
 argon2.workspace = true
 axum.workspace = true
 bytes.workspace = true
+checked_ops.workspace = true
 chrono.workspace = true
 either.workspace = true
 figment.workspace = true
diff --git a/src/core/error.rs b/src/core/error.rs
index ea7acda5c6b228e09571f8105d92aac12d5add76..63729f313126a8c2c13830d2691f106ade36abac 100644
--- a/src/core/error.rs
+++ b/src/core/error.rs
@@ -35,6 +35,12 @@ pub enum Error {
 	FromUtf8Error(#[from] std::string::FromUtf8Error),
 	#[error("{0}")]
 	TryFromSliceError(#[from] std::array::TryFromSliceError),
+	#[error("{0}")]
+	TryFromIntError(#[from] std::num::TryFromIntError),
+	#[error("{0}")]
+	ParseIntError(#[from] std::num::ParseIntError),
+	#[error("{0}")]
+	ParseFloatError(#[from] std::num::ParseFloatError),
 
 	// third-party
 	#[error("Regex error: {0}")]
@@ -63,6 +69,8 @@ pub enum Error {
 	InconsistentRoomState(&'static str, ruma::OwnedRoomId),
 
 	// conduwuit
+	#[error("Arithmetic operation failed: {0}")]
+	Arithmetic(&'static str),
 	#[error("There was a problem with your configuration: {0}")]
 	BadConfig(String),
 	#[error("{0}")]
diff --git a/src/core/utils/math.rs b/src/core/utils/math.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d5dbf3a63d96a82490b4514b21db826b9bac73f6
--- /dev/null
+++ b/src/core/utils/math.rs
@@ -0,0 +1,26 @@
+use std::{cmp, time::Duration};
+
+pub use checked_ops::checked_ops;
+
+/// Checked arithmetic expression. Returns a Result<R, Error::Arithmetic>
+#[macro_export]
+macro_rules! checked {
+	($($input:tt)*) => {
+		$crate::utils::math::checked_ops!($($input)*)
+			.ok_or_else(|| $crate::Error::Arithmetic("operation overflowed or result invalid"))
+	}
+}
+
+/// in release-mode. Use for performance when the expression is obviously safe.
+/// The check remains in debug-mode for regression analysis.
+#[cfg(not(debug_assertions))]
+#[macro_export]
+macro_rules! validated {
+	($($input:tt)*) => { Ok($($input)*) }
+}
+
+#[cfg(debug_assertions)]
+#[macro_export]
+macro_rules! validated {
+	($($input:tt)*) => { $crate::checked!($($input)*) }
+}
diff --git a/src/core/utils/mod.rs b/src/core/utils/mod.rs
index f9f1b87ee1898f3a375b59f593761bdab220566f..2b79c3c4288c5a9fb4139ebd0201665fffc489ce 100644
--- a/src/core/utils/mod.rs
+++ b/src/core/utils/mod.rs
@@ -5,6 +5,7 @@
 pub mod hash;
 pub mod html;
 pub mod json;
+pub mod math;
 pub mod mutex_map;
 pub mod rand;
 pub mod string;
diff --git a/src/core/utils/tests.rs b/src/core/utils/tests.rs
index f5cd0a077ec8853584c3908d46a65e9fd8d26896..239e27e99a4eeda56a222f4cdfd93f05a57823b5 100644
--- a/src/core/utils/tests.rs
+++ b/src/core/utils/tests.rs
@@ -62,3 +62,22 @@ fn common_prefix_none() {
 	let output = string::common_prefix(&input);
 	assert_eq!(output, "");
 }
+
+#[test]
+fn checked_add() {
+	use utils::math::checked;
+
+	let a = 1234;
+	let res = checked!(a + 1).unwrap();
+	assert_eq!(res, 1235);
+}
+
+#[test]
+#[should_panic(expected = "overflow")]
+fn checked_add_overflow() {
+	use utils::math::checked;
+
+	let a: u64 = u64::MAX;
+	let res = checked!(a + 1).expect("overflow");
+	assert_eq!(res, 0);
+}