diff --git a/Sources/XXMessengerClient/Utils/Stored.swift b/Sources/XXMessengerClient/Utils/Stored.swift
new file mode 100644
index 0000000000000000000000000000000000000000..56b5e97ef9db3fcc3d2ab7b8452b8fbb434acce6
--- /dev/null
+++ b/Sources/XXMessengerClient/Utils/Stored.swift
@@ -0,0 +1,41 @@
+import XCTestDynamicOverlay
+
+public struct Stored<Value> {
+  public var get: () -> Value
+  public var set: (Value) -> Void
+
+  public func callAsFunction() -> Value {
+    get()
+  }
+}
+
+extension Stored {
+  public static func inMemory(_ value: Value) -> Stored<Value> {
+    let memory = Memory(value)
+    return Stored(
+      get: { memory.value },
+      set: { memory.value = $0 }
+    )
+  }
+
+  public static func inMemory<V>() -> Stored<Optional<V>> where Value == Optional<V> {
+    inMemory(nil)
+  }
+}
+
+private final class Memory<Value> {
+  init(_ value: Value) {
+    self.value = value
+  }
+
+  var value: Value
+}
+
+extension Stored {
+  public static func unimplemented() -> Stored<Value> {
+    Stored<Value>(
+      get: XCTUnimplemented("\(Self.self).get"),
+      set: XCTUnimplemented("\(Self.self).set")
+    )
+  }
+}
diff --git a/Tests/XXMessengerClientTests/Messenger/Utils/StoredTests.swift b/Tests/XXMessengerClientTests/Messenger/Utils/StoredTests.swift
new file mode 100644
index 0000000000000000000000000000000000000000..154f61967627500def1526f2944aeb074792c748
--- /dev/null
+++ b/Tests/XXMessengerClientTests/Messenger/Utils/StoredTests.swift
@@ -0,0 +1,18 @@
+import XCTest
+@testable import XXMessengerClient
+
+final class StoredTests: XCTestCase {
+  func testInMemory() throws {
+    let stored: Stored<String?> = .inMemory()
+
+    XCTAssertNil(stored())
+
+    stored.set("test")
+
+    XCTAssertEqual(stored(), "test")
+
+    stored.set(nil)
+
+    XCTAssertNil(stored())
+  }
+}