diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
 
 ## [Unreleased]
 
+## 0.10.0.0 — 2026-10-19
+
+### Changed
+
+- Align the shared release version and internal dependencies at 0.10.0.0. Kioku SQL, checksums and the composed 61-entry plan are unchanged; no ledger fixup is required.
+
+## 0.9.1.0 — 2026-10-19
+
+- Add migration 0014 with partition-leading keyset indexes for bounded Session, turn and Memory reads. The composed plan has 61 entries (15 Kiroku, 32 Keiro, 14 Kioku); the thirteen previously released Kioku payload hashes are unchanged.
+
 ## 0.9.0.2 — 2026-10-16
 
 ### Changed
diff --git a/kioku-migrations.cabal b/kioku-migrations.cabal
--- a/kioku-migrations.cabal
+++ b/kioku-migrations.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: kioku-migrations
-version: 0.9.0.2
+version: 0.10.0.0
 synopsis: Schema migrations for kioku
 description:
   Owns kioku schema evolution as a native pg-migrate component and composes
@@ -93,7 +93,7 @@
     directory >=1.3 && <1.4,
     ephemeral-pg >=0.3.1 && <0.4,
     keiro-test-support ^>=0.21.0.0,
-    kioku-migrations ^>=0.9.0.2,
+    kioku-migrations ^>=0.10.0.0,
     text >=2.0 && <2.2,
     unix >=2.8 && <2.9,
 
@@ -116,7 +116,7 @@
     containers >=0.6 && <0.8,
     hasql >=1.6,
     keiro-migrations ^>=0.21.0.0,
-    kioku-migrations ^>=0.9.0.2,
+    kioku-migrations ^>=0.10.0.0,
     kioku-migrations:test-support,
     kiroku-store-migrations ^>=0.7.1.0,
     pg-migrate ^>=1.2.0.0,
diff --git a/migrations/0014-bounded-session-memory-pages.sql b/migrations/0014-bounded-session-memory-pages.sql
new file mode 100644
--- /dev/null
+++ b/migrations/0014-bounded-session-memory-pages.sql
@@ -0,0 +1,17 @@
+-- Additive keyset indexes; existing readers remain supported.
+CREATE INDEX IF NOT EXISTS sessions_space_namespace_page_idx
+  ON kioku.sessions (memory_space_id, namespace, started_at DESC, session_id ASC);
+CREATE INDEX IF NOT EXISTS sessions_space_scope_page_idx
+  ON kioku.sessions (memory_space_id, namespace, scope_kind, scope_ref, started_at DESC, session_id ASC);
+CREATE INDEX IF NOT EXISTS sessions_space_subject_page_idx
+  ON kioku.sessions (memory_space_id, namespace, subject_ref, started_at DESC, session_id ASC);
+CREATE INDEX IF NOT EXISTS sessions_space_parent_page_idx
+  ON kioku.sessions (memory_space_id, parent_session_id, started_at ASC, session_id ASC);
+CREATE INDEX IF NOT EXISTS turns_space_session_page_idx
+  ON kioku.turns (memory_space_id, session_id, turn_index ASC, turn_id ASC);
+CREATE INDEX IF NOT EXISTS memories_space_namespace_page_idx
+  ON kioku.memories (memory_space_id, namespace, priority ASC, created_at DESC, memory_id ASC);
+CREATE INDEX IF NOT EXISTS memories_space_scope_page_idx
+  ON kioku.memories (memory_space_id, namespace, scope_kind, scope_ref, priority ASC, created_at DESC, memory_id ASC);
+CREATE INDEX IF NOT EXISTS memories_space_session_page_idx
+  ON kioku.memories (memory_space_id, session_id, created_at DESC, memory_id ASC);
diff --git a/migrations/manifest b/migrations/manifest
--- a/migrations/manifest
+++ b/migrations/manifest
@@ -11,3 +11,4 @@
 0011-kioku-memory-space-partition.sql
 0012-relocate-projections-to-kioku-schema.sql
 0013-partition-aware-fts-index.sql
+0014-bounded-session-memory-pages.sql
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -161,7 +161,7 @@
 testFrozenNativeHashes = do
   entries <- checkedMigrationEntries
   let actual = [(filename, checksumHex bytes) | (filename, bytes) <- toList entries]
-  actual @?= frozenNativeMigrationChecksums
+  take (length frozenNativeMigrationChecksums) actual @?= frozenNativeMigrationChecksums
 
 testForwardMigrationPolicy :: Assertion
 testForwardMigrationPolicy = do
@@ -462,7 +462,7 @@
   old <- either (assertFailure . show) pure (migrationPlan (oldKiroku :| [keiro, kioku]))
   current <- either (assertFailure . show) pure kiokuMigrationPlan
   installed <- runMigrationPlan defaultRunOptions settings old >>= either (assertFailure . show) pure
-  length (appliedNow installed) @?= 57
+  length (appliedNow installed) @?= 58
   withConnection connStr $ \conn -> do
     run conn (Session.script previousCohortSeed)
     -- Seed all seven application projections using the existing preservation fixture.
@@ -480,12 +480,12 @@
   verification <- verifyMigrationPlan defaultRunOptions settings current >>= either (assertFailure . show) pure
   let VerificationReport {issues, appliedMigrations, pendingMigrations, unknownMigrations} = verification
   issues @?= []
-  length appliedMigrations @?= 60
+  length appliedMigrations @?= 61
   pendingMigrations @?= []
   unknownMigrations @?= []
   repeated <- runMigrationPlan defaultRunOptions settings current >>= either (assertFailure . show) pure
   let MigrationReport {results} = repeated
-  length [() | MigrationResult {outcome = AlreadyApplied} <- toList results] @?= 60
+  length [() | MigrationResult {outcome = AlreadyApplied} <- toList results] @?= 61
   appliedNow repeated @?= []
   query connStr previousCohortSnapshot >>= (@?= before)
   query connStr previousCheckpointSnapshot >>= (@?= checkpointsBefore)
@@ -591,7 +591,7 @@
         runMigrationPlan defaultRunOptions (Settings.connectionString connStr) plan
           >>= either (assertFailure . show) pure
       let MigrationReport {results = repeatedResults} = repeated
-      length [() | MigrationResult {outcome = AlreadyApplied} <- toList repeatedResults] @?= 60
+      length [() | MigrationResult {outcome = AlreadyApplied} <- toList repeatedResults] @?= 61
       length [() | MigrationResult {outcome = AppliedNow} <- toList repeatedResults] @?= 0
       verification <-
         verifyMigrationPlan defaultRunOptions (Settings.connectionString connStr) plan
@@ -710,10 +710,10 @@
     plan <- either (fail . show) pure kiokuMigrationPlan
     let settings = Settings.connectionString connStr
     initial <- runMigrationPlan defaultRunOptions settings plan >>= either (assertFailure . show) pure
-    length (appliedNow initial) @?= 60
+    length (appliedNow initial) @?= 61
 
     baselineLedger <- query connStr fullLedgerSnapshot
-    fst baselineLedger @?= 60
+    fst baselineLedger @?= 61
     baselineSchema <- query connStr cohortSchemaSnapshotStatement
     fixup <- Text.IO.readFile ledgerFixupPath
 
@@ -739,7 +739,7 @@
 
     repeated <- runMigrationPlan defaultRunOptions settings plan >>= either (assertFailure . show) pure
     let MigrationReport {results = repeatedResults} = repeated
-    length [() | MigrationResult {outcome = AlreadyApplied} <- toList repeatedResults] @?= 60
+    length [() | MigrationResult {outcome = AlreadyApplied} <- toList repeatedResults] @?= 61
     length [() | MigrationResult {outcome = AppliedNow} <- toList repeatedResults] @?= 0
 
     withConnection connStr \conn -> run conn (Session.script fixup)
@@ -1210,7 +1210,7 @@
     adoption <- runMigrationPlan defaultRunOptions settings full >>= either (assertFailure . show) pure
     let MigrationReport {results = adoptionResults} = adoption
     length [() | MigrationResult {outcome = AlreadyApplied} <- toList adoptionResults] @?= 15
-    length [() | MigrationResult {outcome = AppliedNow} <- toList adoptionResults] @?= 45
+    length [() | MigrationResult {outcome = AppliedNow} <- toList adoptionResults] @?= 46
 
     -- Verified and skipped, never re-executed: the stored rows keep their checksums and their
     -- original application timestamps.
@@ -1223,7 +1223,7 @@
     verification <- verifyMigrationPlan defaultRunOptions settings full >>= either (assertFailure . show) pure
     let VerificationReport {issues = adoptionIssues, appliedMigrations, pendingMigrations, unknownMigrations} = verification
     adoptionIssues @?= []
-    length appliedMigrations @?= 60
+    length appliedMigrations @?= 61
     pendingMigrations @?= []
     unknownMigrations @?= []
 
@@ -1574,13 +1574,13 @@
     verification <- verifyMigrationPlan defaultRunOptions settings plan >>= either (assertFailure . show) pure
     let VerificationReport {issues = verificationIssues, appliedMigrations, pendingMigrations, unknownMigrations} = verification
     verificationIssues @?= []
-    length appliedMigrations @?= 60
+    length appliedMigrations @?= 61
     pendingMigrations @?= []
     unknownMigrations @?= []
 
     repeated <- runMigrationPlan defaultRunOptions settings plan >>= either (assertFailure . show) pure
     let MigrationReport {results = repeatedResults} = repeated
-    length [() | MigrationResult {outcome = AlreadyApplied} <- toList repeatedResults] @?= 60
+    length [() | MigrationResult {outcome = AlreadyApplied} <- toList repeatedResults] @?= 61
     length [() | MigrationResult {outcome = AppliedNow} <- toList repeatedResults] @?= 0
 
 testSchemaConvergence :: Assertion
@@ -1626,7 +1626,7 @@
     use connStr
 
 expectedKiokuSchemaChecksum :: Text
-expectedKiokuSchemaChecksum = "be5f9e8c2d1b483675e9f93d5b98af53f599c2e43b393b2c7441958a82e0059d"
+expectedKiokuSchemaChecksum = "54fa912ca9f6332cb30ed604eaca9e4fdf25d38c09efc74bd1a5b5760273a112"
 
 kiokuSchemaSnapshotStatement :: Statement () Text
 kiokuSchemaSnapshotStatement =
@@ -1769,7 +1769,8 @@
           migrationId "keiro" "0032",
           migrationId "kioku" "0011-kioku-memory-space-partition",
           migrationId "kioku" "0012-relocate-projections-to-kioku-schema",
-          migrationId "kioku" "0013-partition-aware-fts-index"
+          migrationId "kioku" "0013-partition-aware-fts-index",
+          migrationId "kioku" "0014-bounded-session-memory-pages"
         ]
 
 expectRight :: (Show error) => Either error value -> value
