You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2023/11/06 15:53:00 UTC

(lucene) branch branch_9x updated: Remove patching for doc blocks. (#12741)

This is an automated email from the ASF dual-hosted git repository.

mikemccand pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/lucene.git


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 0b2cac6b421 Remove patching for doc blocks. (#12741)
0b2cac6b421 is described below

commit 0b2cac6b421ead36024497873b5b5c0e9323a44e
Author: Jakub Slowinski <32...@users.noreply.github.com>
AuthorDate: Mon Nov 6 15:46:03 2023 +0000

    Remove patching for doc blocks. (#12741)
    
    * Change Postings back to using FOR in Lucene99PostingsFormat
    
    We are still keeping PFOR for positions only.
    This is a partial revert of https://github.com/apache/lucene/pull/69 which brings back ForDeltaUtil.
    
    * fix merge commit
    
    * Add forgotten forDeltaUtil calls to reader
    
    * Addressing comments: adding Lucene90RWPostingsFormat + more
    
    Also:
    * Change to Changes.txt
    * Removal of dead code which was only used in unit tests
    * Removal of test code from PForUtil
    
    * Changes.txt edit in right place now
    
    * Apply suggestions from code review: `90 -> 99 refactoring`
    
    Co-authored-by: gf2121 <52...@users.noreply.github.com>
    
    * Remove decodeTo32 from ForUtil and regenerate
    
    ---------
    
    Co-authored-by: gf2121 <52...@users.noreply.github.com>
---
 gradle/generation/forUtil.gradle                   |  28 +++-
 lucene/CHANGES.txt                                 |   3 +-
 ...generateForUtil.json => generateForUtil84.json} |   0
 .../src/generated/checksums/generateForUtil90.json |   4 +
 lucene/backward-codecs/src/java/module-info.java   |   3 +-
 .../lucene/backward_codecs}/lucene90/ForUtil.java  |   2 +-
 .../backward_codecs/lucene90/Lucene90Codec.java    |   1 -
 .../lucene90/Lucene90PostingsFormat.java           |  46 +-----
 .../lucene90/Lucene90PostingsReader.java           |  20 +--
 .../lucene90/Lucene90PostingsWriter.java           |  18 +-
 .../lucene90/Lucene90ScoreSkipReader.java          |   2 +-
 .../lucene90/Lucene90SkipReader.java               |   2 +-
 .../lucene90/Lucene90SkipWriter.java               |   5 +-
 .../lucene/backward_codecs}/lucene90/PForUtil.java |   2 +-
 .../backward_codecs}/lucene90/gen_ForUtil.py       |   2 +-
 .../backward_codecs/lucene91/Lucene91Codec.java    |   2 +-
 .../backward_codecs/lucene91/package-info.java     |  28 ++--
 .../backward_codecs/lucene92/Lucene92Codec.java    |   2 +-
 .../backward_codecs/lucene92/package-info.java     |  28 ++--
 .../backward_codecs/lucene94/Lucene94Codec.java    |   2 +-
 .../backward_codecs/lucene94/package-info.java     |  28 ++--
 .../backward_codecs/lucene95/Lucene95Codec.java    |   2 +-
 .../backward_codecs/lucene95/package-info.java     |  28 ++--
 .../org.apache.lucene.codecs.PostingsFormat        |   1 +
 .../backward_codecs/lucene90/Lucene90RWCodec.java  |   7 +
 .../lucene90/Lucene90RWPostingsFormat.java         | 184 +++++++++++++++++++++
 .../backward_codecs/lucene91/Lucene91RWCodec.java  |   8 +
 .../backward_codecs/lucene92/Lucene92RWCodec.java  |   8 +
 .../backward_codecs/lucene94/Lucene94RWCodec.java  |   9 +-
 .../backward_codecs/lucene95/Lucene95RWCodec.java  |   8 +
 .../blocktreeords/BlockTreeOrdsPostingsFormat.java |  10 +-
 .../lucene/codecs/memory/DirectPostingsFormat.java |   8 +-
 .../lucene/codecs/memory/FSTPostingsFormat.java    |   8 +-
 .../uniformsplit/DeltaBaseTermStateSerializer.java |  14 +-
 .../uniformsplit/UniformSplitPostingsFormat.java   |   8 +-
 .../lucene/codecs/uniformsplit/package-info.java   |   2 +-
 .../lucene90/tests/MockTermStateFactory.java       |   2 +-
 .../src/generated/checksums/generateForUtil.json   |   4 +-
 lucene/core/src/java/module-info.java              |   2 +-
 .../lucene/codecs/lucene99/ForDeltaUtil.java       |  78 +++++++++
 .../codecs/{lucene90 => lucene99}/ForUtil.java     | 141 +++++++++++++---
 .../lucene/codecs/lucene99/Lucene99Codec.java      |   6 +-
 .../Lucene99PostingsFormat.java}                   |  36 ++--
 .../Lucene99PostingsReader.java}                   | 109 ++++++------
 .../Lucene99PostingsWriter.java}                   |  41 ++---
 .../Lucene99ScoreSkipReader.java}                  |   6 +-
 .../Lucene99SkipReader.java}                       |  14 +-
 .../Lucene99SkipWriter.java}                       |  14 +-
 .../apache/lucene/codecs/lucene99/PForUtil.java    | 143 ++++++++++++++++
 .../codecs/{lucene90 => lucene99}/gen_ForUtil.py   | 113 +++++++++++--
 .../lucene/codecs/lucene99/package-info.java       |  16 +-
 .../java/org/apache/lucene/search/PhraseQuery.java |  10 +-
 .../org.apache.lucene.codecs.PostingsFormat        |   2 +-
 .../TestForDeltaUtil.java}                         |  39 ++---
 .../codecs/{lucene90 => lucene99}/TestForUtil.java |   2 +-
 .../TestLucene99PostingsFormat.java}               |  17 +-
 .../{lucene90 => lucene99}/TestPForUtil.java       |  38 +----
 .../queries/intervals/TermIntervalsSource.java     |  10 +-
 lucene/suggest/src/java/module-info.java           |   3 +-
 .../document/Completion50PostingsFormat.java       |   2 +-
 .../document/Completion84PostingsFormat.java       |   2 +-
 .../document/Completion90PostingsFormat.java       |   6 +-
 ...Format.java => Completion99PostingsFormat.java} |  16 +-
 .../org.apache.lucene.codecs.PostingsFormat        |   1 +
 .../search/suggest/document/TestSuggestField.java  |   2 +-
 .../tests/codecs/blockterms/LuceneFixedGap.java    |  12 +-
 .../blockterms/LuceneVarGapDocFreqInterval.java    |  12 +-
 .../blockterms/LuceneVarGapFixedInterval.java      |  12 +-
 .../mockrandom/MockRandomPostingsFormat.java       |   8 +-
 .../UniformSplitRot13PostingsFormat.java           |   8 +-
 .../org/apache/lucene/tests/util/TestUtil.java     |   6 +-
 71 files changed, 1028 insertions(+), 438 deletions(-)

diff --git a/gradle/generation/forUtil.gradle b/gradle/generation/forUtil.gradle
index 9ada40c8dde..96f5bfdf974 100644
--- a/gradle/generation/forUtil.gradle
+++ b/gradle/generation/forUtil.gradle
@@ -23,7 +23,7 @@ configure(project(":lucene:core")) {
     description "Regenerate gen_ForUtil.py"
     group "generation"
 
-    def genDir = file("src/java/org/apache/lucene/codecs/lucene90")
+    def genDir = file("src/java/org/apache/lucene/codecs/lucene99")
     def genScript = file("${genDir}/gen_ForUtil.py")
     def genOutput = file("${genDir}/ForUtil.java")
 
@@ -44,7 +44,7 @@ configure(project(":lucene:core")) {
 
 configure(project(":lucene:backward-codecs")) {
 
-  task generateForUtilInternal() {
+  task generateForUtil84Internal() {
     description "Regenerate gen_ForUtil.py"
     group "generation"
 
@@ -64,6 +64,28 @@ configure(project(":lucene:backward-codecs")) {
     }
   }
 
-  regenerate.dependsOn wrapWithPersistentChecksums(generateForUtilInternal, [ andThenTasks: ["spotlessJava", "spotlessJavaApply"] ])
+  regenerate.dependsOn wrapWithPersistentChecksums(generateForUtil84Internal, [ andThenTasks: ["spotlessJava", "spotlessJavaApply"] ])
+
+  task generateForUtil90Internal() {
+    description "Regenerate gen_ForUtil.py"
+    group "generation"
+
+    def genDir = file("src/java/org/apache/lucene/backward_codecs/lucene90")
+    def genScript = file("${genDir}/gen_ForUtil.py")
+    def genOutput = file("${genDir}/ForUtil.java")
+
+    inputs.file genScript
+    outputs.file genOutput
+
+    doLast {
+      quietExec {
+        workingDir genDir
+        executable project.externalTool("python3")
+        args = [ '-B', genScript ]
+      }
+    }
+  }
+
+  regenerate.dependsOn wrapWithPersistentChecksums(generateForUtil90Internal, [ andThenTasks: ["spotlessJava", "spotlessJavaApply"] ])
 }
 
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 72eaf9e0d0d..1c5b0e17824 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -119,11 +119,12 @@ Optimizations
 * GITHUB#12719: Top-level conjunctions that are not sorted by score now have a
   specialized bulk scorer. (Adrien Grand)
 
+* GITHUB#12696: Change Postings back to using FOR in Lucene99PostingsFormat. Freqs, positions and offset keep using PFOR. (Jakub Slowinski)
+
 * GITHUB#1052: Faster merging of terms enums. (Adrien Grand)
 
 * GITHUB#11903: Faster sort on high-cardinality string fields. (Adrien Grand)
 
-
 Changes in runtime behavior
 ---------------------
 
diff --git a/lucene/backward-codecs/src/generated/checksums/generateForUtil.json b/lucene/backward-codecs/src/generated/checksums/generateForUtil84.json
similarity index 100%
rename from lucene/backward-codecs/src/generated/checksums/generateForUtil.json
rename to lucene/backward-codecs/src/generated/checksums/generateForUtil84.json
diff --git a/lucene/backward-codecs/src/generated/checksums/generateForUtil90.json b/lucene/backward-codecs/src/generated/checksums/generateForUtil90.json
new file mode 100644
index 00000000000..15fd411b1cb
--- /dev/null
+++ b/lucene/backward-codecs/src/generated/checksums/generateForUtil90.json
@@ -0,0 +1,4 @@
+{
+    "lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/ForUtil.java": "861cab516c7424e6323831c16f0f521499391a90",
+    "lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/gen_ForUtil.py": "b66e2f8012759d6d5ce0d73fabb329ae4a391aa0"
+}
\ No newline at end of file
diff --git a/lucene/backward-codecs/src/java/module-info.java b/lucene/backward-codecs/src/java/module-info.java
index 5e23fb45cac..51a9128e38c 100644
--- a/lucene/backward-codecs/src/java/module-info.java
+++ b/lucene/backward-codecs/src/java/module-info.java
@@ -43,7 +43,8 @@ module org.apache.lucene.backward_codecs {
       org.apache.lucene.backward_codecs.lucene80.Lucene80DocValuesFormat;
   provides org.apache.lucene.codecs.PostingsFormat with
       org.apache.lucene.backward_codecs.lucene50.Lucene50PostingsFormat,
-      org.apache.lucene.backward_codecs.lucene84.Lucene84PostingsFormat;
+      org.apache.lucene.backward_codecs.lucene84.Lucene84PostingsFormat,
+      org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
   provides org.apache.lucene.codecs.KnnVectorsFormat with
       org.apache.lucene.backward_codecs.lucene90.Lucene90HnswVectorsFormat,
       org.apache.lucene.backward_codecs.lucene91.Lucene91HnswVectorsFormat,
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/ForUtil.java
similarity index 99%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/ForUtil.java
index a58c84e314b..c889c8b8626 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/ForUtil.java
@@ -16,7 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import org.apache.lucene.store.DataInput;
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90Codec.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90Codec.java
index b9465985063..77280dcff63 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90Codec.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90Codec.java
@@ -35,7 +35,6 @@ import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90LiveDocsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90NormsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90PointsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90StoredFieldsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat;
 import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsFormat.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsFormat.java
similarity index 94%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsFormat.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsFormat.java
index de0d9c381a8..0fceeb47296 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsFormat.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsFormat.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import org.apache.lucene.codecs.BlockTermState;
@@ -24,7 +24,6 @@ import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.codecs.MultiLevelSkipListWriter;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.PostingsReaderBase;
-import org.apache.lucene.codecs.PostingsWriterBase;
 import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsReader;
 import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsWriter;
 import org.apache.lucene.index.IndexOptions;
@@ -36,7 +35,9 @@ import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.packed.PackedInts;
 
 /**
- * Lucene 5.0 postings format, which encodes postings in packed integer blocks for fast decode.
+ * Lucene 9.0 postings format, which encodes postings in packed integer blocks for fast decode.
+ *
+ * <p>Note: Lucene90PostingsFormat is now READ ONLY.
  *
  * <p>Basic idea:
  *
@@ -371,30 +372,11 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
 
   // Increment version to change it
   static final int VERSION_START = 0;
-  static final int VERSION_CURRENT = VERSION_START;
-
-  private final int minTermBlockSize;
-  private final int maxTermBlockSize;
+  static final int VERSION_CURRENT = 1;
 
-  /** Creates {@code Lucene90PostingsFormat} with default settings. */
+  /** Creates read-only {@code Lucene90PostingsFormat}. */
   public Lucene90PostingsFormat() {
-    this(
-        Lucene90BlockTreeTermsWriter.DEFAULT_MIN_BLOCK_SIZE,
-        Lucene90BlockTreeTermsWriter.DEFAULT_MAX_BLOCK_SIZE);
-  }
-
-  /**
-   * Creates {@code Lucene90PostingsFormat} with custom values for {@code minBlockSize} and {@code
-   * maxBlockSize} passed to block terms dictionary.
-   *
-   * @see
-   *     Lucene90BlockTreeTermsWriter#Lucene90BlockTreeTermsWriter(SegmentWriteState,PostingsWriterBase,int,int)
-   */
-  public Lucene90PostingsFormat(int minTermBlockSize, int maxTermBlockSize) {
     super("Lucene90");
-    Lucene90BlockTreeTermsWriter.validateSettings(minTermBlockSize, maxTermBlockSize);
-    this.minTermBlockSize = minTermBlockSize;
-    this.maxTermBlockSize = maxTermBlockSize;
   }
 
   @Override
@@ -403,20 +385,8 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
   }
 
   @Override
-  public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
-    boolean success = false;
-    try {
-      FieldsConsumer ret =
-          new Lucene90BlockTreeTermsWriter(
-              state, postingsWriter, minTermBlockSize, maxTermBlockSize);
-      success = true;
-      return ret;
-    } finally {
-      if (!success) {
-        IOUtils.closeWhileHandlingException(postingsWriter);
-      }
-    }
+  public FieldsConsumer fieldsConsumer(SegmentWriteState state) {
+    throw new UnsupportedOperationException("Old codecs may only be used for reading");
   }
 
   @Override
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsReader.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsReader.java
similarity index 98%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsReader.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsReader.java
index 56f7bafd4fe..190fe5b1d1d 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsReader.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsReader.java
@@ -14,23 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
-import static org.apache.lucene.codecs.lucene90.ForUtil.BLOCK_SIZE;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.DOC_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.MAX_SKIP_LEVELS;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.PAY_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.POS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.TERMS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.VERSION_CURRENT;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.VERSION_START;
+import static org.apache.lucene.backward_codecs.lucene90.ForUtil.BLOCK_SIZE;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.DOC_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.MAX_SKIP_LEVELS;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.PAY_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.POS_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.TERMS_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.VERSION_CURRENT;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.VERSION_START;
 
 import java.io.IOException;
 import java.util.Arrays;
+import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
 import org.apache.lucene.codecs.BlockTermState;
 import org.apache.lucene.codecs.CodecUtil;
 import org.apache.lucene.codecs.PostingsReaderBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.Impacts;
 import org.apache.lucene.index.ImpactsEnum;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsWriter.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsWriter.java
similarity index 95%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsWriter.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsWriter.java
index f640d8d2c57..b745d4e1217 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsWriter.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90PostingsWriter.java
@@ -14,22 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
-import static org.apache.lucene.codecs.lucene90.ForUtil.BLOCK_SIZE;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.DOC_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.MAX_SKIP_LEVELS;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.PAY_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.POS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.TERMS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.VERSION_CURRENT;
+import static org.apache.lucene.backward_codecs.lucene90.ForUtil.BLOCK_SIZE;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.DOC_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.MAX_SKIP_LEVELS;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.PAY_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.POS_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.TERMS_CODEC;
+import static org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.VERSION_CURRENT;
 
 import java.io.IOException;
+import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
 import org.apache.lucene.codecs.BlockTermState;
 import org.apache.lucene.codecs.CodecUtil;
 import org.apache.lucene.codecs.CompetitiveImpactAccumulator;
 import org.apache.lucene.codecs.PushPostingsWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexFileNames;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90ScoreSkipReader.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90ScoreSkipReader.java
similarity index 98%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90ScoreSkipReader.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90ScoreSkipReader.java
index 44789a98334..504fd5294e1 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90ScoreSkipReader.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90ScoreSkipReader.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import java.util.AbstractList;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipReader.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90SkipReader.java
similarity index 99%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipReader.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90SkipReader.java
index da31bd75a80..cd2febadf8f 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipReader.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90SkipReader.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import java.util.Arrays;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipWriter.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90SkipWriter.java
similarity index 98%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipWriter.java
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90SkipWriter.java
index 48deafa4225..4448945e7d5 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipWriter.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/Lucene90SkipWriter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -94,8 +94,7 @@ final class Lucene90SkipWriter extends MultiLevelSkipListWriter {
     }
   }
 
-  public void setField(
-      boolean fieldHasPositions, boolean fieldHasOffsets, boolean fieldHasPayloads) {
+  void setField(boolean fieldHasPositions, boolean fieldHasOffsets, boolean fieldHasPayloads) {
     this.fieldHasPositions = fieldHasPositions;
     this.fieldHasOffsets = fieldHasOffsets;
     this.fieldHasPayloads = fieldHasPayloads;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/PForUtil.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/PForUtil.java
similarity index 99%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/PForUtil.java
rename to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/PForUtil.java
index 211912142a4..69b91660d10 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/PForUtil.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/PForUtil.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import java.util.Arrays;
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/gen_ForUtil.py
similarity index 99%
copy from lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py
copy to lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/gen_ForUtil.py
index a468c590cf9..6c58ce1a9a0 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene90/gen_ForUtil.py
@@ -40,7 +40,7 @@ HEADER = """// This file has been automatically generated, DO NOT EDIT
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.backward_codecs.lucene90;
 
 import java.io.IOException;
 import org.apache.lucene.store.DataInput;
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91Codec.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91Codec.java
index 9393d0fa5a1..a354dc0827c 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91Codec.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/Lucene91Codec.java
@@ -18,6 +18,7 @@ package org.apache.lucene.backward_codecs.lucene91;
 
 import java.util.Objects;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90FieldInfosFormat;
+import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90SegmentInfoFormat;
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.CompoundFormat;
@@ -37,7 +38,6 @@ import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90LiveDocsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90NormsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90PointsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90StoredFieldsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat;
 import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/package-info.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/package-info.java
index 21bc835b61e..6dc0e4edb59 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/package-info.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene91/package-info.java
@@ -151,17 +151,17 @@
  *       field names. These are used to store auxiliary information about the document, such as its
  *       title, url, or an identifier to access a database. The set of stored fields are what is
  *       returned for each hit when searching. This is keyed by document number.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term dictionary}. A
- *       dictionary containing all of the terms used in all of the indexed fields of all of the
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term dictionary}.
+ *       A dictionary containing all of the terms used in all of the indexed fields of all of the
  *       documents. The dictionary also contains the number of documents which contain the term, and
  *       pointers to the term's frequency and proximity data.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Frequency data}. For
- *       each term in the dictionary, the numbers of all the documents that contain that term, and
- *       the frequency of the term in that document, unless frequencies are omitted ({@link
- *       org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Proximity data}. For
- *       each term in the dictionary, the positions that the term occurs in each document. Note that
- *       this will not exist if all fields in all documents omit position data.
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Frequency
+ *       data}. For each term in the dictionary, the numbers of all the documents that contain that
+ *       term, and the frequency of the term in that document, unless frequencies are omitted
+ *       ({@link org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Proximity
+ *       data}. For each term in the dictionary, the positions that the term occurs in each
+ *       document. Note that this will not exist if all fields in all documents omit position data.
  *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90NormsFormat Normalization factors}. For
  *       each field in each document, a value is stored that is multiplied into the score for hits
  *       on that field.
@@ -255,27 +255,27 @@
  * <td>The stored fields for documents</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
  * <td>.tim</td>
  * <td>The term dictionary, stores term info</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
  * <td>.tip</td>
  * <td>The index into the Term Dictionary</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
  * <td>.doc</td>
  * <td>Contains the list of docs which contain each term along with frequency</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Positions}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Positions}</td>
  * <td>.pos</td>
  * <td>Stores position information about where a term occurs in the index</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
  * <td>.pay</td>
  * <td>Stores additional per-position metadata information such as character offsets and user payloads</td>
  * </tr>
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92Codec.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92Codec.java
index 28ba9923481..15a61fd0c0d 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92Codec.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/Lucene92Codec.java
@@ -18,6 +18,7 @@ package org.apache.lucene.backward_codecs.lucene92;
 
 import java.util.Objects;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90FieldInfosFormat;
+import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90SegmentInfoFormat;
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.CompoundFormat;
@@ -37,7 +38,6 @@ import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90LiveDocsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90NormsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90PointsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90StoredFieldsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat;
 import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/package-info.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/package-info.java
index 2e85de218e0..c993b78e9f1 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/package-info.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene92/package-info.java
@@ -151,17 +151,17 @@
  *       field names. These are used to store auxiliary information about the document, such as its
  *       title, url, or an identifier to access a database. The set of stored fields are what is
  *       returned for each hit when searching. This is keyed by document number.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term dictionary}. A
- *       dictionary containing all of the terms used in all of the indexed fields of all of the
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term dictionary}.
+ *       A dictionary containing all of the terms used in all of the indexed fields of all of the
  *       documents. The dictionary also contains the number of documents which contain the term, and
  *       pointers to the term's frequency and proximity data.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Frequency data}. For
- *       each term in the dictionary, the numbers of all the documents that contain that term, and
- *       the frequency of the term in that document, unless frequencies are omitted ({@link
- *       org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Proximity data}. For
- *       each term in the dictionary, the positions that the term occurs in each document. Note that
- *       this will not exist if all fields in all documents omit position data.
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Frequency
+ *       data}. For each term in the dictionary, the numbers of all the documents that contain that
+ *       term, and the frequency of the term in that document, unless frequencies are omitted
+ *       ({@link org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Proximity
+ *       data}. For each term in the dictionary, the positions that the term occurs in each
+ *       document. Note that this will not exist if all fields in all documents omit position data.
  *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90NormsFormat Normalization factors}. For
  *       each field in each document, a value is stored that is multiplied into the score for hits
  *       on that field.
@@ -255,27 +255,27 @@
  * <td>The stored fields for documents</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
  * <td>.tim</td>
  * <td>The term dictionary, stores term info</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
  * <td>.tip</td>
  * <td>The index into the Term Dictionary</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
  * <td>.doc</td>
  * <td>Contains the list of docs which contain each term along with frequency</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Positions}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Positions}</td>
  * <td>.pos</td>
  * <td>Stores position information about where a term occurs in the index</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
  * <td>.pay</td>
  * <td>Stores additional per-position metadata information such as character offsets and user payloads</td>
  * </tr>
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/Lucene94Codec.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/Lucene94Codec.java
index 324ee042967..d8bc7413feb 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/Lucene94Codec.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/Lucene94Codec.java
@@ -17,6 +17,7 @@
 package org.apache.lucene.backward_codecs.lucene94;
 
 import java.util.Objects;
+import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90SegmentInfoFormat;
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.CompoundFormat;
@@ -36,7 +37,6 @@ import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90LiveDocsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90NormsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90PointsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90StoredFieldsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat;
 import org.apache.lucene.codecs.lucene94.Lucene94FieldInfosFormat;
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/package-info.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/package-info.java
index ae2bffe0bbb..cd140076a82 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/package-info.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene94/package-info.java
@@ -151,17 +151,17 @@
  *       field names. These are used to store auxiliary information about the document, such as its
  *       title, url, or an identifier to access a database. The set of stored fields are what is
  *       returned for each hit when searching. This is keyed by document number.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term dictionary}. A
- *       dictionary containing all of the terms used in all of the indexed fields of all of the
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term dictionary}.
+ *       A dictionary containing all of the terms used in all of the indexed fields of all of the
  *       documents. The dictionary also contains the number of documents which contain the term, and
  *       pointers to the term's frequency and proximity data.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Frequency data}. For
- *       each term in the dictionary, the numbers of all the documents that contain that term, and
- *       the frequency of the term in that document, unless frequencies are omitted ({@link
- *       org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Proximity data}. For
- *       each term in the dictionary, the positions that the term occurs in each document. Note that
- *       this will not exist if all fields in all documents omit position data.
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Frequency
+ *       data}. For each term in the dictionary, the numbers of all the documents that contain that
+ *       term, and the frequency of the term in that document, unless frequencies are omitted
+ *       ({@link org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Proximity
+ *       data}. For each term in the dictionary, the positions that the term occurs in each
+ *       document. Note that this will not exist if all fields in all documents omit position data.
  *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90NormsFormat Normalization factors}. For
  *       each field in each document, a value is stored that is multiplied into the score for hits
  *       on that field.
@@ -255,27 +255,27 @@
  * <td>The stored fields for documents</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
  * <td>.tim</td>
  * <td>The term dictionary, stores term info</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
  * <td>.tip</td>
  * <td>The index into the Term Dictionary</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
  * <td>.doc</td>
  * <td>Contains the list of docs which contain each term along with frequency</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Positions}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Positions}</td>
  * <td>.pos</td>
  * <td>Stores position information about where a term occurs in the index</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
  * <td>.pay</td>
  * <td>Stores additional per-position metadata information such as character offsets and user payloads</td>
  * </tr>
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/Lucene95Codec.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/Lucene95Codec.java
index 4e42ff09472..e47de701502 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/Lucene95Codec.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/Lucene95Codec.java
@@ -17,6 +17,7 @@
 package org.apache.lucene.backward_codecs.lucene95;
 
 import java.util.Objects;
+import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90SegmentInfoFormat;
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.CompoundFormat;
@@ -36,7 +37,6 @@ import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90LiveDocsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90NormsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90PointsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90StoredFieldsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90TermVectorsFormat;
 import org.apache.lucene.codecs.lucene94.Lucene94FieldInfosFormat;
diff --git a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/package-info.java b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/package-info.java
index 4ad0f34364a..879704dd842 100644
--- a/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/package-info.java
+++ b/lucene/backward-codecs/src/java/org/apache/lucene/backward_codecs/lucene95/package-info.java
@@ -151,17 +151,17 @@
  *       field names. These are used to store auxiliary information about the document, such as its
  *       title, url, or an identifier to access a database. The set of stored fields are what is
  *       returned for each hit when searching. This is keyed by document number.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term dictionary}. A
- *       dictionary containing all of the terms used in all of the indexed fields of all of the
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term dictionary}.
+ *       A dictionary containing all of the terms used in all of the indexed fields of all of the
  *       documents. The dictionary also contains the number of documents which contain the term, and
  *       pointers to the term's frequency and proximity data.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Frequency data}. For
- *       each term in the dictionary, the numbers of all the documents that contain that term, and
- *       the frequency of the term in that document, unless frequencies are omitted ({@link
- *       org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Proximity data}. For
- *       each term in the dictionary, the positions that the term occurs in each document. Note that
- *       this will not exist if all fields in all documents omit position data.
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Frequency
+ *       data}. For each term in the dictionary, the numbers of all the documents that contain that
+ *       term, and the frequency of the term in that document, unless frequencies are omitted
+ *       ({@link org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
+ *   <li>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Proximity
+ *       data}. For each term in the dictionary, the positions that the term occurs in each
+ *       document. Note that this will not exist if all fields in all documents omit position data.
  *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90NormsFormat Normalization factors}. For
  *       each field in each document, a value is stored that is multiplied into the score for hits
  *       on that field.
@@ -255,27 +255,27 @@
  * <td>The stored fields for documents</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
  * <td>.tim</td>
  * <td>The term dictionary, stores term info</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
  * <td>.tip</td>
  * <td>The index into the Term Dictionary</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
  * <td>.doc</td>
  * <td>Contains the list of docs which contain each term along with frequency</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Positions}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Positions}</td>
  * <td>.pos</td>
  * <td>Stores position information about where a term occurs in the index</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
+ * <td>{@link org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
  * <td>.pay</td>
  * <td>Stores additional per-position metadata information such as character offsets and user payloads</td>
  * </tr>
diff --git a/lucene/backward-codecs/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat b/lucene/backward-codecs/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
index 620f7c81a9d..18ac359d2ae 100644
--- a/lucene/backward-codecs/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
+++ b/lucene/backward-codecs/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
@@ -15,3 +15,4 @@
 
 org.apache.lucene.backward_codecs.lucene50.Lucene50PostingsFormat
 org.apache.lucene.backward_codecs.lucene84.Lucene84PostingsFormat
+org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWCodec.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWCodec.java
index 7c032f7f58b..240a53f22db 100644
--- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWCodec.java
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWCodec.java
@@ -17,6 +17,7 @@
 package org.apache.lucene.backward_codecs.lucene90;
 
 import org.apache.lucene.codecs.KnnVectorsFormat;
+import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.SegmentInfoFormat;
 import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
 
@@ -32,6 +33,7 @@ public class Lucene90RWCodec extends Lucene90Codec {
           return defaultKnnVectorsFormat;
         }
       };
+  private final PostingsFormat postingsFormat = new Lucene90RWPostingsFormat();
 
   public Lucene90RWCodec() {
     this.defaultKnnVectorsFormat =
@@ -49,4 +51,9 @@ public class Lucene90RWCodec extends Lucene90Codec {
   public SegmentInfoFormat segmentInfoFormat() {
     return segmentInfosFormat;
   }
+
+  @Override
+  public PostingsFormat getPostingsFormatForField(String field) {
+    return postingsFormat;
+  }
 }
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWPostingsFormat.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWPostingsFormat.java
new file mode 100644
index 00000000000..6497bb13d11
--- /dev/null
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene90/Lucene90RWPostingsFormat.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.backward_codecs.lucene90;
+
+import java.io.IOException;
+import org.apache.lucene.codecs.BlockTermState;
+import org.apache.lucene.codecs.FieldsConsumer;
+import org.apache.lucene.codecs.FieldsProducer;
+import org.apache.lucene.codecs.PostingsFormat;
+import org.apache.lucene.codecs.PostingsReaderBase;
+import org.apache.lucene.codecs.PostingsWriterBase;
+import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsReader;
+import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsWriter;
+import org.apache.lucene.index.SegmentReadState;
+import org.apache.lucene.index.SegmentWriteState;
+import org.apache.lucene.index.TermState;
+import org.apache.lucene.util.IOUtils;
+
+public final class Lucene90RWPostingsFormat extends PostingsFormat {
+
+  /** Size of blocks. */
+  public static final int BLOCK_SIZE = ForUtil.BLOCK_SIZE;
+
+  /**
+   * Expert: The maximum number of skip levels. Smaller values result in slightly smaller indexes,
+   * but slower skipping in big posting lists.
+   */
+  static final int MAX_SKIP_LEVELS = 10;
+
+  static final String TERMS_CODEC = "Lucene90PostingsWriterTerms";
+  static final String DOC_CODEC = "Lucene90PostingsWriterDoc";
+  static final String POS_CODEC = "Lucene90PostingsWriterPos";
+  static final String PAY_CODEC = "Lucene90PostingsWriterPay";
+
+  private final int minTermBlockSize;
+  private final int maxTermBlockSize;
+
+  /** Creates {@code Lucene90RWPostingsFormat} with default settings. */
+  public Lucene90RWPostingsFormat() {
+    this(
+        Lucene90BlockTreeTermsWriter.DEFAULT_MIN_BLOCK_SIZE,
+        Lucene90BlockTreeTermsWriter.DEFAULT_MAX_BLOCK_SIZE);
+  }
+
+  public Lucene90RWPostingsFormat(int minTermBlockSize, int maxTermBlockSize) {
+    super("Lucene90");
+    Lucene90BlockTreeTermsWriter.validateSettings(minTermBlockSize, maxTermBlockSize);
+    this.minTermBlockSize = minTermBlockSize;
+    this.maxTermBlockSize = maxTermBlockSize;
+  }
+
+  @Override
+  public String toString() {
+    return getName();
+  }
+
+  @Override
+  public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
+    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
+    boolean success = false;
+    try {
+      FieldsConsumer ret =
+          new Lucene90BlockTreeTermsWriter(
+              state, postingsWriter, minTermBlockSize, maxTermBlockSize);
+      success = true;
+      return ret;
+    } finally {
+      if (!success) {
+        IOUtils.closeWhileHandlingException(postingsWriter);
+      }
+    }
+  }
+
+  @Override
+  public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
+    PostingsReaderBase postingsReader = new Lucene90PostingsReader(state);
+    boolean success = false;
+    try {
+      FieldsProducer ret = new Lucene90BlockTreeTermsReader(postingsReader, state);
+      success = true;
+      return ret;
+    } finally {
+      if (!success) {
+        IOUtils.closeWhileHandlingException(postingsReader);
+      }
+    }
+  }
+
+  /**
+   * Holds all state required for {@link Lucene90PostingsReader} to produce a {@link
+   * org.apache.lucene.index.PostingsEnum} without re-seeking the terms dict.
+   *
+   * @lucene.internal
+   */
+  public static final class IntBlockTermState extends BlockTermState {
+    /** file pointer to the start of the doc ids enumeration, in .doc file */
+    public long docStartFP;
+
+    /** file pointer to the start of the positions enumeration, in .pos file */
+    public long posStartFP;
+
+    /** file pointer to the start of the payloads enumeration, in .pay file */
+    public long payStartFP;
+
+    /**
+     * file offset for the start of the skip list, relative to docStartFP, if there are more than
+     * {@link ForUtil#BLOCK_SIZE} docs; otherwise -1
+     */
+    public long skipOffset;
+
+    /**
+     * file offset for the last position in the last block, if there are more than {@link
+     * ForUtil#BLOCK_SIZE} positions; otherwise -1
+     *
+     * <p>One might think to use total term frequency to track how many positions are left to read
+     * as we decode the blocks, and decode the last block differently when num_left_positions &lt;
+     * BLOCK_SIZE. Unfortunately this won't work since the tracking will be messed up when we skip
+     * blocks as the skipper will only tell us new position offset (start of block) and number of
+     * positions to skip for that block, without telling us how many positions it has skipped.
+     */
+    public long lastPosBlockOffset;
+
+    /**
+     * docid when there is a single pulsed posting, otherwise -1. freq is always implicitly
+     * totalTermFreq in this case.
+     */
+    public int singletonDocID;
+
+    /** Sole constructor. */
+    public IntBlockTermState() {
+      skipOffset = -1;
+      lastPosBlockOffset = -1;
+      singletonDocID = -1;
+    }
+
+    @Override
+    public IntBlockTermState clone() {
+      IntBlockTermState other = new IntBlockTermState();
+      other.copyFrom(this);
+      return other;
+    }
+
+    @Override
+    public void copyFrom(TermState _other) {
+      super.copyFrom(_other);
+      IntBlockTermState other = (IntBlockTermState) _other;
+      docStartFP = other.docStartFP;
+      posStartFP = other.posStartFP;
+      payStartFP = other.payStartFP;
+      lastPosBlockOffset = other.lastPosBlockOffset;
+      skipOffset = other.skipOffset;
+      singletonDocID = other.singletonDocID;
+    }
+
+    @Override
+    public String toString() {
+      return super.toString()
+          + " docStartFP="
+          + docStartFP
+          + " posStartFP="
+          + posStartFP
+          + " payStartFP="
+          + payStartFP
+          + " lastPosBlockOffset="
+          + lastPosBlockOffset
+          + " singletonDocID="
+          + singletonDocID;
+    }
+  }
+}
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene91/Lucene91RWCodec.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene91/Lucene91RWCodec.java
index f9bac90b906..ec775b513cd 100644
--- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene91/Lucene91RWCodec.java
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene91/Lucene91RWCodec.java
@@ -16,8 +16,10 @@
  */
 package org.apache.lucene.backward_codecs.lucene91;
 
+import org.apache.lucene.backward_codecs.lucene90.Lucene90RWPostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90RWSegmentInfoFormat;
 import org.apache.lucene.codecs.KnnVectorsFormat;
+import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.SegmentInfoFormat;
 import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
 
@@ -32,6 +34,7 @@ public class Lucene91RWCodec extends Lucene91Codec {
         }
       };
   private final SegmentInfoFormat segmentInfosFormat = new Lucene90RWSegmentInfoFormat();
+  private final PostingsFormat postingsFormat = new Lucene90RWPostingsFormat();
 
   public Lucene91RWCodec() {
     this.defaultKnnVectorsFormat =
@@ -49,4 +52,9 @@ public class Lucene91RWCodec extends Lucene91Codec {
   public SegmentInfoFormat segmentInfoFormat() {
     return segmentInfosFormat;
   }
+
+  @Override
+  public PostingsFormat getPostingsFormatForField(String field) {
+    return postingsFormat;
+  }
 }
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene92/Lucene92RWCodec.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene92/Lucene92RWCodec.java
index 6008fa5df39..8d086787413 100644
--- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene92/Lucene92RWCodec.java
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene92/Lucene92RWCodec.java
@@ -16,8 +16,10 @@
  */
 package org.apache.lucene.backward_codecs.lucene92;
 
+import org.apache.lucene.backward_codecs.lucene90.Lucene90RWPostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90RWSegmentInfoFormat;
 import org.apache.lucene.codecs.KnnVectorsFormat;
+import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.SegmentInfoFormat;
 import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
 
@@ -33,6 +35,7 @@ public class Lucene92RWCodec extends Lucene92Codec {
         }
       };
   private final SegmentInfoFormat segmentInfosFormat = new Lucene90RWSegmentInfoFormat();
+  private final PostingsFormat postingsFormat = new Lucene90RWPostingsFormat();
 
   /** Instantiates a new codec. */
   public Lucene92RWCodec() {
@@ -51,4 +54,9 @@ public class Lucene92RWCodec extends Lucene92Codec {
   public SegmentInfoFormat segmentInfoFormat() {
     return segmentInfosFormat;
   }
+
+  @Override
+  public PostingsFormat getPostingsFormatForField(String field) {
+    return postingsFormat;
+  }
 }
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene94/Lucene94RWCodec.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene94/Lucene94RWCodec.java
index 88edd2431f8..678dec4ad19 100644
--- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene94/Lucene94RWCodec.java
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene94/Lucene94RWCodec.java
@@ -16,8 +16,10 @@
  */
 package org.apache.lucene.backward_codecs.lucene94;
 
+import org.apache.lucene.backward_codecs.lucene90.Lucene90RWPostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90RWSegmentInfoFormat;
 import org.apache.lucene.codecs.KnnVectorsFormat;
+import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.SegmentInfoFormat;
 import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
 
@@ -32,8 +34,8 @@ public class Lucene94RWCodec extends Lucene94Codec {
           return defaultKnnVectorsFormat;
         }
       };
-
   private final SegmentInfoFormat segmentInfosFormat = new Lucene90RWSegmentInfoFormat();
+  private final PostingsFormat postingsFormat = new Lucene90RWPostingsFormat();
 
   /** Instantiates a new codec. */
   public Lucene94RWCodec() {
@@ -52,4 +54,9 @@ public class Lucene94RWCodec extends Lucene94Codec {
   public SegmentInfoFormat segmentInfoFormat() {
     return segmentInfosFormat;
   }
+
+  @Override
+  public PostingsFormat getPostingsFormatForField(String field) {
+    return postingsFormat;
+  }
 }
diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene95/Lucene95RWCodec.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene95/Lucene95RWCodec.java
index c8311dfd115..e51a2a391dd 100644
--- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene95/Lucene95RWCodec.java
+++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene95/Lucene95RWCodec.java
@@ -16,9 +16,11 @@
  */
 package org.apache.lucene.backward_codecs.lucene95;
 
+import org.apache.lucene.backward_codecs.lucene90.Lucene90RWPostingsFormat;
 import org.apache.lucene.backward_codecs.lucene90.Lucene90RWSegmentInfoFormat;
 import org.apache.lucene.backward_codecs.lucene94.Lucene94HnswVectorsFormat;
 import org.apache.lucene.codecs.KnnVectorsFormat;
+import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.SegmentInfoFormat;
 import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
 
@@ -33,6 +35,7 @@ public class Lucene95RWCodec extends Lucene95Codec {
           return defaultKnnVectorsFormat;
         }
       };
+  private final PostingsFormat postingsFormat = new Lucene90RWPostingsFormat();
   private final SegmentInfoFormat segmentInfosFormat = new Lucene90RWSegmentInfoFormat();
 
   /** Instantiates a new codec. */
@@ -52,4 +55,9 @@ public class Lucene95RWCodec extends Lucene95Codec {
   public SegmentInfoFormat segmentInfoFormat() {
     return segmentInfosFormat;
   }
+
+  @Override
+  public PostingsFormat getPostingsFormatForField(String field) {
+    return postingsFormat;
+  }
 }
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/BlockTreeOrdsPostingsFormat.java b/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/BlockTreeOrdsPostingsFormat.java
index 5ee3451c9e8..d389372d8f8 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/BlockTreeOrdsPostingsFormat.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/BlockTreeOrdsPostingsFormat.java
@@ -22,14 +22,14 @@ import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.PostingsReaderBase;
 import org.apache.lucene.codecs.PostingsWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
 import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 import org.apache.lucene.util.IOUtils;
 
-/** Uses {@link OrdsBlockTreeTermsWriter} with {@link Lucene90PostingsWriter}. */
+/** Uses {@link OrdsBlockTreeTermsWriter} with {@link Lucene99PostingsWriter}. */
 public class BlockTreeOrdsPostingsFormat extends PostingsFormat {
 
   private final int minTermBlockSize;
@@ -67,7 +67,7 @@ public class BlockTreeOrdsPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
+    PostingsWriterBase postingsWriter = new Lucene99PostingsWriter(state);
 
     boolean success = false;
     try {
@@ -84,7 +84,7 @@ public class BlockTreeOrdsPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postingsReader = new Lucene90PostingsReader(state);
+    PostingsReaderBase postingsReader = new Lucene99PostingsReader(state);
     boolean success = false;
     try {
       FieldsProducer ret = new OrdsBlockTreeTermsReader(postingsReader, state);
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java
index f66ca453fd9..dfd0291019c 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java
@@ -24,7 +24,7 @@ import java.util.TreeMap;
 import org.apache.lucene.codecs.FieldsConsumer;
 import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.codecs.PostingsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
 import org.apache.lucene.index.BaseTermsEnum;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.Fields;
@@ -53,7 +53,7 @@ import org.apache.lucene.util.automaton.Transition;
 //   - or: longer dense skip lists than just next byte?
 
 /**
- * Wraps {@link Lucene90PostingsFormat} format for on-disk storage, but then at read time loads and
+ * Wraps {@link Lucene99PostingsFormat} format for on-disk storage, but then at read time loads and
  * stores all terms and postings directly in RAM as byte[], int[].
  *
  * <p><b>WARNING</b>: This is exceptionally RAM intensive: it makes no effort to compress the
@@ -96,12 +96,12 @@ public final class DirectPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    return PostingsFormat.forName("Lucene90").fieldsConsumer(state);
+    return PostingsFormat.forName("Lucene99").fieldsConsumer(state);
   }
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    FieldsProducer postings = PostingsFormat.forName("Lucene90").fieldsProducer(state);
+    FieldsProducer postings = PostingsFormat.forName("Lucene99").fieldsProducer(state);
     if (state.context.context != IOContext.Context.MERGE) {
       FieldsProducer loadedPostings;
       try {
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTPostingsFormat.java b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTPostingsFormat.java
index 4e0fec1587f..0a18b75ac00 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTPostingsFormat.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/FSTPostingsFormat.java
@@ -22,8 +22,8 @@ import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.PostingsReaderBase;
 import org.apache.lucene.codecs.PostingsWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 import org.apache.lucene.util.IOUtils;
@@ -41,7 +41,7 @@ public final class FSTPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
+    PostingsWriterBase postingsWriter = new Lucene99PostingsWriter(state);
 
     boolean success = false;
     try {
@@ -57,7 +57,7 @@ public final class FSTPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postingsReader = new Lucene90PostingsReader(state);
+    PostingsReaderBase postingsReader = new Lucene99PostingsReader(state);
     boolean success = false;
     try {
       FieldsProducer ret = new FSTTermsReader(state, postingsReader);
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/DeltaBaseTermStateSerializer.java b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/DeltaBaseTermStateSerializer.java
index 6881aedbd50..ae01216ccf6 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/DeltaBaseTermStateSerializer.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/DeltaBaseTermStateSerializer.java
@@ -17,13 +17,13 @@
 
 package org.apache.lucene.codecs.uniformsplit;
 
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.BLOCK_SIZE;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.BLOCK_SIZE;
 
 import java.io.IOException;
 import org.apache.lucene.codecs.BlockTermState;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.IntBlockTermState;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.TermState;
@@ -34,7 +34,7 @@ import org.apache.lucene.util.RamUsageEstimator;
 
 /**
  * {@link TermState} serializer which encodes each file pointer as a delta relative to a base file
- * pointer. It differs from {@link Lucene90PostingsWriter#encodeTerm} which encodes each file
+ * pointer. It differs from {@link Lucene99PostingsWriter#encodeTerm} which encodes each file
  * pointer as a delta relative to the previous file pointer.
  *
  * <p>It automatically sets the base file pointer to the first valid file pointer for doc start FP,
@@ -95,7 +95,7 @@ public class DeltaBaseTermStateSerializer implements Accountable {
   /**
    * Writes a {@link BlockTermState} to the provided {@link DataOutput}.
    *
-   * <p>Simpler variant of {@link Lucene90PostingsWriter#encodeTerm(DataOutput, FieldInfo,
+   * <p>Simpler variant of {@link Lucene99PostingsWriter#encodeTerm(DataOutput, FieldInfo,
    * BlockTermState, boolean)}.
    */
   public void writeTermState(
@@ -148,7 +148,7 @@ public class DeltaBaseTermStateSerializer implements Accountable {
   /**
    * Reads a {@link BlockTermState} from the provided {@link DataInput}.
    *
-   * <p>Simpler variant of {@link Lucene90PostingsReader#decodeTerm(DataInput, FieldInfo,
+   * <p>Simpler variant of {@link Lucene99PostingsReader#decodeTerm(DataInput, FieldInfo,
    * BlockTermState, boolean)}.
    *
    * @param reuse {@link BlockTermState} to reuse; or null to create a new one.
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/UniformSplitPostingsFormat.java b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/UniformSplitPostingsFormat.java
index 5ac38e78b8f..8e2b7bb7d54 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/UniformSplitPostingsFormat.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/UniformSplitPostingsFormat.java
@@ -23,8 +23,8 @@ import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.PostingsReaderBase;
 import org.apache.lucene.codecs.PostingsWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 import org.apache.lucene.util.IOUtils;
@@ -113,7 +113,7 @@ public class UniformSplitPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
+    PostingsWriterBase postingsWriter = new Lucene99PostingsWriter(state);
     boolean success = false;
     try {
       FieldsConsumer termsWriter =
@@ -130,7 +130,7 @@ public class UniformSplitPostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postingsReader = new Lucene90PostingsReader(state);
+    PostingsReaderBase postingsReader = new Lucene99PostingsReader(state);
     boolean success = false;
     try {
       FieldsProducer termsReader =
diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/package-info.java b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/package-info.java
index f1df01d09b2..a0fa67508f3 100644
--- a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/package-info.java
+++ b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/package-info.java
@@ -28,7 +28,7 @@
  *       org.apache.lucene.search.PhraseQuery})
  *   <li>Quite efficient for {@link org.apache.lucene.search.PrefixQuery}
  *   <li>Not efficient for spell-check and {@link org.apache.lucene.search.FuzzyQuery}, in this case
- *       prefer {@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat}
+ *       prefer {@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat}
  * </ul>
  */
 package org.apache.lucene.codecs.uniformsplit;
diff --git a/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java b/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java
index 69c36e792c0..dde59993f6e 100644
--- a/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java
+++ b/lucene/codecs/src/test/org/apache/lucene/codecs/lucene90/tests/MockTermStateFactory.java
@@ -17,7 +17,7 @@
 
 package org.apache.lucene.codecs.lucene90.tests;
 
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.IntBlockTermState;
 
 /** Test utility class to create mock {@link IntBlockTermState}. */
 public class MockTermStateFactory {
diff --git a/lucene/core/src/generated/checksums/generateForUtil.json b/lucene/core/src/generated/checksums/generateForUtil.json
index 6cd91640bd1..527070d7bf0 100644
--- a/lucene/core/src/generated/checksums/generateForUtil.json
+++ b/lucene/core/src/generated/checksums/generateForUtil.json
@@ -1,4 +1,4 @@
 {
-    "lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java": "a67f47001bad680d75c57a864a1552a78fc85600",
-    "lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py": "3219c6d0289cc64d80dbdbc5db4bd05b8774e797"
+    "lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForUtil.java": "1292ad354d255b1272ffd3db684aa2ddb2bc49ec",
+    "lucene/core/src/java/org/apache/lucene/codecs/lucene99/gen_ForUtil.py": "ab7b63a1b73986cc04e43de1c8f474b97aef5116"
 }
\ No newline at end of file
diff --git a/lucene/core/src/java/module-info.java b/lucene/core/src/java/module-info.java
index 98210a89300..096c965dc98 100644
--- a/lucene/core/src/java/module-info.java
+++ b/lucene/core/src/java/module-info.java
@@ -72,7 +72,7 @@ module org.apache.lucene.core {
   provides org.apache.lucene.codecs.KnnVectorsFormat with
       Lucene99HnswVectorsFormat;
   provides org.apache.lucene.codecs.PostingsFormat with
-      org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
+      org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
   provides org.apache.lucene.index.SortFieldProvider with
       org.apache.lucene.search.SortField.Provider,
       org.apache.lucene.search.SortedNumericSortField.Provider,
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForDeltaUtil.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForDeltaUtil.java
new file mode 100644
index 00000000000..2403c997435
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForDeltaUtil.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.codecs.lucene99;
+
+import java.io.IOException;
+import org.apache.lucene.store.DataInput;
+import org.apache.lucene.store.DataOutput;
+import org.apache.lucene.util.packed.PackedInts;
+
+/** Utility class to encode/decode increasing sequences of 128 integers. */
+public class ForDeltaUtil {
+
+  // IDENTITY_PLUS_ONE[i] == i+1
+  private static final long[] IDENTITY_PLUS_ONE = new long[ForUtil.BLOCK_SIZE];
+
+  static {
+    for (int i = 0; i < ForUtil.BLOCK_SIZE; ++i) {
+      IDENTITY_PLUS_ONE[i] = i + 1;
+    }
+  }
+
+  private static void prefixSumOfOnes(long[] arr, long base) {
+    System.arraycopy(IDENTITY_PLUS_ONE, 0, arr, 0, ForUtil.BLOCK_SIZE);
+    // This loop gets auto-vectorized
+    for (int i = 0; i < ForUtil.BLOCK_SIZE; ++i) {
+      arr[i] += base;
+    }
+  }
+
+  private final ForUtil forUtil;
+
+  ForDeltaUtil(ForUtil forUtil) {
+    this.forUtil = forUtil;
+  }
+
+  /**
+   * Encode deltas of a strictly monotonically increasing sequence of integers. The provided {@code
+   * longs} are expected to be deltas between consecutive values.
+   */
+  void encodeDeltas(long[] longs, DataOutput out) throws IOException {
+    if (longs[0] == 1 && PForUtil.allEqual(longs)) { // happens with very dense postings
+      out.writeByte((byte) 0);
+    } else {
+      long or = 0;
+      for (long l : longs) {
+        or |= l;
+      }
+      assert or != 0;
+      final int bitsPerValue = PackedInts.bitsRequired(or);
+      out.writeByte((byte) bitsPerValue);
+      forUtil.encode(longs, bitsPerValue, out);
+    }
+  }
+
+  /** Decode deltas, compute the prefix sum and add {@code base} to all decoded longs. */
+  void decodeAndPrefixSum(DataInput in, long base, long[] longs) throws IOException {
+    final int bitsPerValue = Byte.toUnsignedInt(in.readByte());
+    if (bitsPerValue == 0) {
+      prefixSumOfOnes(longs, base);
+    } else {
+      forUtil.decodeAndPrefixSum(bitsPerValue, in, base, longs);
+    }
+  }
+}
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForUtil.java
similarity index 92%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForUtil.java
index a58c84e314b..3126cdb02c0 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/ForUtil.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/ForUtil.java
@@ -16,7 +16,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import java.io.IOException;
 import org.apache.lucene.store.DataInput;
@@ -132,6 +132,94 @@ final class ForUtil {
     }
   }
 
+  private static void prefixSum8(long[] arr, long base) {
+    expand8To32(arr);
+    prefixSum32(arr, base);
+  }
+
+  private static void prefixSum16(long[] arr, long base) {
+    // We need to move to the next primitive size to avoid overflows
+    expand16To32(arr);
+    prefixSum32(arr, base);
+  }
+
+  private static void prefixSum32(long[] arr, long base) {
+    arr[0] += base << 32;
+    innerPrefixSum32(arr);
+    expand32(arr);
+    final long l = arr[BLOCK_SIZE / 2 - 1];
+    for (int i = BLOCK_SIZE / 2; i < BLOCK_SIZE; ++i) {
+      arr[i] += l;
+    }
+  }
+
+  // For some reason unrolling seems to help
+  private static void innerPrefixSum32(long[] arr) {
+    arr[1] += arr[0];
+    arr[2] += arr[1];
+    arr[3] += arr[2];
+    arr[4] += arr[3];
+    arr[5] += arr[4];
+    arr[6] += arr[5];
+    arr[7] += arr[6];
+    arr[8] += arr[7];
+    arr[9] += arr[8];
+    arr[10] += arr[9];
+    arr[11] += arr[10];
+    arr[12] += arr[11];
+    arr[13] += arr[12];
+    arr[14] += arr[13];
+    arr[15] += arr[14];
+    arr[16] += arr[15];
+    arr[17] += arr[16];
+    arr[18] += arr[17];
+    arr[19] += arr[18];
+    arr[20] += arr[19];
+    arr[21] += arr[20];
+    arr[22] += arr[21];
+    arr[23] += arr[22];
+    arr[24] += arr[23];
+    arr[25] += arr[24];
+    arr[26] += arr[25];
+    arr[27] += arr[26];
+    arr[28] += arr[27];
+    arr[29] += arr[28];
+    arr[30] += arr[29];
+    arr[31] += arr[30];
+    arr[32] += arr[31];
+    arr[33] += arr[32];
+    arr[34] += arr[33];
+    arr[35] += arr[34];
+    arr[36] += arr[35];
+    arr[37] += arr[36];
+    arr[38] += arr[37];
+    arr[39] += arr[38];
+    arr[40] += arr[39];
+    arr[41] += arr[40];
+    arr[42] += arr[41];
+    arr[43] += arr[42];
+    arr[44] += arr[43];
+    arr[45] += arr[44];
+    arr[46] += arr[45];
+    arr[47] += arr[46];
+    arr[48] += arr[47];
+    arr[49] += arr[48];
+    arr[50] += arr[49];
+    arr[51] += arr[50];
+    arr[52] += arr[51];
+    arr[53] += arr[52];
+    arr[54] += arr[53];
+    arr[55] += arr[54];
+    arr[56] += arr[55];
+    arr[57] += arr[56];
+    arr[58] += arr[57];
+    arr[59] += arr[58];
+    arr[60] += arr[59];
+    arr[61] += arr[60];
+    arr[62] += arr[61];
+    arr[63] += arr[62];
+  }
+
   private final long[] tmp = new long[BLOCK_SIZE / 2];
 
   /** Encode 128 integers from {@code longs} into {@code out}. */
@@ -423,104 +511,109 @@ final class ForUtil {
     }
   }
 
-  /**
-   * Decodes 128 integers into 64 {@code longs} such that each long contains two values, each
-   * represented with 32 bits. Values [0..63] are encoded in the high-order bits of {@code longs}
-   * [0..63], and values [64..127] are encoded in the low-order bits of {@code longs} [0..63]. This
-   * representation may allow subsequent operations to be performed on two values at a time.
-   */
-  void decodeTo32(int bitsPerValue, DataInput in, long[] longs) throws IOException {
+  /** Delta-decode 128 integers into {@code longs}. */
+  void decodeAndPrefixSum(int bitsPerValue, DataInput in, long base, long[] longs)
+      throws IOException {
     switch (bitsPerValue) {
       case 1:
         decode1(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 2:
         decode2(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 3:
         decode3(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 4:
         decode4(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 5:
         decode5(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 6:
         decode6(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 7:
         decode7(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 8:
         decode8(in, tmp, longs);
-        expand8To32(longs);
+        prefixSum8(longs, base);
         break;
       case 9:
         decode9(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 10:
         decode10(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 11:
         decode11(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 12:
         decode12(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 13:
         decode13(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 14:
         decode14(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 15:
         decode15(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 16:
         decode16(in, tmp, longs);
-        expand16To32(longs);
+        prefixSum16(longs, base);
         break;
       case 17:
         decode17(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 18:
         decode18(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 19:
         decode19(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 20:
         decode20(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 21:
         decode21(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 22:
         decode22(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 23:
         decode23(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       case 24:
         decode24(in, tmp, longs);
+        prefixSum32(longs, base);
         break;
       default:
         decodeSlow(bitsPerValue, in, tmp, longs);
+        prefixSum32(longs, base);
         break;
     }
   }
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99Codec.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99Codec.java
index 9633c386ec1..ce6c40f9402 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99Codec.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99Codec.java
@@ -98,7 +98,7 @@ public class Lucene99Codec extends Codec {
     super("Lucene99");
     this.storedFieldsFormat =
         new Lucene90StoredFieldsFormat(Objects.requireNonNull(mode).storedMode);
-    this.defaultPostingsFormat = new Lucene90PostingsFormat();
+    this.defaultPostingsFormat = new Lucene99PostingsFormat();
     this.defaultDVFormat = new Lucene90DocValuesFormat();
     this.defaultKnnVectorsFormat = new Lucene99HnswVectorsFormat();
   }
@@ -151,7 +151,7 @@ public class Lucene99Codec extends Codec {
   /**
    * Returns the postings format that should be used for writing new segments of <code>field</code>.
    *
-   * <p>The default implementation always returns "Lucene90".
+   * <p>The default implementation always returns "Lucene99".
    *
    * <p><b>WARNING:</b> if you subclass, you are responsible for index backwards compatibility:
    * future version of Lucene are only guaranteed to be able to read the default implementation,
@@ -164,7 +164,7 @@ public class Lucene99Codec extends Codec {
    * Returns the docvalues format that should be used for writing new segments of <code>field</code>
    * .
    *
-   * <p>The default implementation always returns "Lucene90".
+   * <p>The default implementation always returns "Lucene99".
    *
    * <p><b>WARNING:</b> if you subclass, you are responsible for index backwards compatibility:
    * future version of Lucene are only guaranteed to be able to read the default implementation.
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsFormat.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsFormat.java
similarity index 96%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsFormat.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsFormat.java
index de0d9c381a8..f233276c6c5 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsFormat.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsFormat.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import java.io.IOException;
 import org.apache.lucene.codecs.BlockTermState;
@@ -36,7 +36,7 @@ import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.packed.PackedInts;
 
 /**
- * Lucene 5.0 postings format, which encodes postings in packed integer blocks for fast decode.
+ * Lucene 9.9 postings format, which encodes postings in packed integer blocks for fast decode.
  *
  * <p>Basic idea:
  *
@@ -48,7 +48,7 @@ import org.apache.lucene.util.packed.PackedInts;
  *       <p>In VInt blocks, integers are encoded as {@link DataOutput#writeVInt VInt}: the block
  *       size is variable.
  *   <li><b>Block structure</b>:
- *       <p>When the postings are long enough, Lucene90PostingsFormat will try to encode most
+ *       <p>When the postings are long enough, Lucene99PostingsFormat will try to encode most
  *       integer data as a packed block.
  *       <p>Take a term with 259 documents as an example, the first 256 document ids are encoded as
  *       two packed blocks, while the remaining 3 are encoded as one VInt block.
@@ -137,7 +137,7 @@ import org.apache.lucene.util.packed.PackedInts;
  *             total number of positions i.e. totalTermFreq is less or equal to PackedBlockSize).
  *         <li>SkipFPDelta determines the position of this term's SkipData within the .doc file. In
  *             particular, it is the length of the TermFreq data. SkipDelta is only stored if
- *             DocFreq is not smaller than SkipMinimum (i.e. 128 in Lucene90PostingsFormat).
+ *             DocFreq is not smaller than SkipMinimum (i.e. 128 in Lucene99PostingsFormat).
  *         <li>SingletonDocID is an optimization when a term only appears in one document. In this
  *             case, instead of writing a file pointer to the .doc file (DocFPDelta), and then a
  *             VIntBlock at that location, the single document ID is written to the term dictionary.
@@ -215,11 +215,11 @@ import org.apache.lucene.util.packed.PackedInts;
  *             trick since the definition of skip entry is a little different from base interface.
  *             In {@link MultiLevelSkipListWriter}, skip data is assumed to be saved for
  *             skipInterval<sup>th</sup>, 2*skipInterval<sup>th</sup> ... posting in the list.
- *             However, in Lucene90PostingsFormat, the skip data is saved for
+ *             However, in Lucene99PostingsFormat, the skip data is saved for
  *             skipInterval+1<sup>th</sup>, 2*skipInterval+1<sup>th</sup> ... posting
  *             (skipInterval==PackedBlockSize in this case). When DocFreq is multiple of
  *             PackedBlockSize, MultiLevelSkipListWriter will expect one more skip data than
- *             Lucene90SkipWriter.
+ *             Lucene99SkipWriter.
  *         <li>SkipDatum is the metadata of one skip entry. For the first block (no matter packed or
  *             VInt), it is omitted.
  *         <li>DocSkip records the document number of every PackedBlockSize<sup>th</sup> document
@@ -338,7 +338,7 @@ import org.apache.lucene.util.packed.PackedInts;
  *
  * @lucene.experimental
  */
-public final class Lucene90PostingsFormat extends PostingsFormat {
+public final class Lucene99PostingsFormat extends PostingsFormat {
 
   /**
    * Filename extension for document number, frequencies, and skip data. See chapter: <a
@@ -365,9 +365,9 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
   static final int MAX_SKIP_LEVELS = 10;
 
   static final String TERMS_CODEC = "Lucene90PostingsWriterTerms";
-  static final String DOC_CODEC = "Lucene90PostingsWriterDoc";
-  static final String POS_CODEC = "Lucene90PostingsWriterPos";
-  static final String PAY_CODEC = "Lucene90PostingsWriterPay";
+  static final String DOC_CODEC = "Lucene99PostingsWriterDoc";
+  static final String POS_CODEC = "Lucene99PostingsWriterPos";
+  static final String PAY_CODEC = "Lucene99PostingsWriterPay";
 
   // Increment version to change it
   static final int VERSION_START = 0;
@@ -376,22 +376,22 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
   private final int minTermBlockSize;
   private final int maxTermBlockSize;
 
-  /** Creates {@code Lucene90PostingsFormat} with default settings. */
-  public Lucene90PostingsFormat() {
+  /** Creates {@code Lucene99PostingsFormat} with default settings. */
+  public Lucene99PostingsFormat() {
     this(
         Lucene90BlockTreeTermsWriter.DEFAULT_MIN_BLOCK_SIZE,
         Lucene90BlockTreeTermsWriter.DEFAULT_MAX_BLOCK_SIZE);
   }
 
   /**
-   * Creates {@code Lucene90PostingsFormat} with custom values for {@code minBlockSize} and {@code
+   * Creates {@code Lucene99PostingsFormat} with custom values for {@code minBlockSize} and {@code
    * maxBlockSize} passed to block terms dictionary.
    *
    * @see
    *     Lucene90BlockTreeTermsWriter#Lucene90BlockTreeTermsWriter(SegmentWriteState,PostingsWriterBase,int,int)
    */
-  public Lucene90PostingsFormat(int minTermBlockSize, int maxTermBlockSize) {
-    super("Lucene90");
+  public Lucene99PostingsFormat(int minTermBlockSize, int maxTermBlockSize) {
+    super("Lucene99");
     Lucene90BlockTreeTermsWriter.validateSettings(minTermBlockSize, maxTermBlockSize);
     this.minTermBlockSize = minTermBlockSize;
     this.maxTermBlockSize = maxTermBlockSize;
@@ -404,7 +404,7 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
+    PostingsWriterBase postingsWriter = new Lucene99PostingsWriter(state);
     boolean success = false;
     try {
       FieldsConsumer ret =
@@ -421,7 +421,7 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postingsReader = new Lucene90PostingsReader(state);
+    PostingsReaderBase postingsReader = new Lucene99PostingsReader(state);
     boolean success = false;
     try {
       FieldsProducer ret = new Lucene90BlockTreeTermsReader(postingsReader, state);
@@ -435,7 +435,7 @@ public final class Lucene90PostingsFormat extends PostingsFormat {
   }
 
   /**
-   * Holds all state required for {@link Lucene90PostingsReader} to produce a {@link
+   * Holds all state required for {@link Lucene99PostingsReader} to produce a {@link
    * org.apache.lucene.index.PostingsEnum} without re-seeking the terms dict.
    *
    * @lucene.internal
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsReader.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsReader.java
similarity index 95%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsReader.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsReader.java
index 56f7bafd4fe..77e50e23ce8 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsReader.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsReader.java
@@ -14,23 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
-import static org.apache.lucene.codecs.lucene90.ForUtil.BLOCK_SIZE;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.DOC_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.MAX_SKIP_LEVELS;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.PAY_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.POS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.TERMS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.VERSION_CURRENT;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.VERSION_START;
+import static org.apache.lucene.codecs.lucene99.ForUtil.BLOCK_SIZE;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.DOC_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.MAX_SKIP_LEVELS;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.PAY_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.POS_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.TERMS_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.VERSION_CURRENT;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.VERSION_START;
 
 import java.io.IOException;
 import java.util.Arrays;
 import org.apache.lucene.codecs.BlockTermState;
 import org.apache.lucene.codecs.CodecUtil;
 import org.apache.lucene.codecs.PostingsReaderBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.IntBlockTermState;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.Impacts;
 import org.apache.lucene.index.ImpactsEnum;
@@ -51,7 +51,7 @@ import org.apache.lucene.util.IOUtils;
  *
  * @lucene.experimental
  */
-public final class Lucene90PostingsReader extends PostingsReaderBase {
+public final class Lucene99PostingsReader extends PostingsReaderBase {
 
   private final IndexInput docIn;
   private final IndexInput posIn;
@@ -60,7 +60,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
   private final int version;
 
   /** Sole constructor. */
-  public Lucene90PostingsReader(SegmentReadState state) throws IOException {
+  public Lucene99PostingsReader(SegmentReadState state) throws IOException {
     boolean success = false;
     IndexInput docIn = null;
     IndexInput posIn = null;
@@ -73,7 +73,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
 
     String docName =
         IndexFileNames.segmentFileName(
-            state.segmentInfo.name, state.segmentSuffix, Lucene90PostingsFormat.DOC_EXTENSION);
+            state.segmentInfo.name, state.segmentSuffix, Lucene99PostingsFormat.DOC_EXTENSION);
     try {
       docIn = state.directory.openInput(docName, state.context);
       version =
@@ -89,7 +89,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       if (state.fieldInfos.hasProx()) {
         String proxName =
             IndexFileNames.segmentFileName(
-                state.segmentInfo.name, state.segmentSuffix, Lucene90PostingsFormat.POS_EXTENSION);
+                state.segmentInfo.name, state.segmentSuffix, Lucene99PostingsFormat.POS_EXTENSION);
         posIn = state.directory.openInput(proxName, state.context);
         CodecUtil.checkIndexHeader(
             posIn, POS_CODEC, version, version, state.segmentInfo.getId(), state.segmentSuffix);
@@ -100,7 +100,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
               IndexFileNames.segmentFileName(
                   state.segmentInfo.name,
                   state.segmentSuffix,
-                  Lucene90PostingsFormat.PAY_EXTENSION);
+                  Lucene99PostingsFormat.PAY_EXTENSION);
           payIn = state.directory.openInput(payName, state.context);
           CodecUtil.checkIndexHeader(
               payIn, PAY_CODEC, version, version, state.segmentInfo.getId(), state.segmentSuffix);
@@ -306,14 +306,16 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
 
   final class BlockDocsEnum extends PostingsEnum {
 
-    final PForUtil pforUtil = new PForUtil(new ForUtil());
+    final ForUtil forUtil = new ForUtil();
+    final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(forUtil);
+    final PForUtil pforUtil = new PForUtil(forUtil);
 
     private final long[] docBuffer = new long[BLOCK_SIZE + 1];
     private final long[] freqBuffer = new long[BLOCK_SIZE];
 
     private int docBufferUpto;
 
-    private Lucene90SkipReader skipper;
+    private Lucene99SkipReader skipper;
     private boolean skipped;
 
     final IndexInput startDocIn;
@@ -350,7 +352,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     private int singletonDocID; // docid when there is a single pulsed posting, otherwise -1
 
     public BlockDocsEnum(FieldInfo fieldInfo) throws IOException {
-      this.startDocIn = Lucene90PostingsReader.this.docIn;
+      this.startDocIn = Lucene99PostingsReader.this.docIn;
       this.docIn = null;
       indexHasFreq = fieldInfo.getIndexOptions().compareTo(IndexOptions.DOCS_AND_FREQS) >= 0;
       indexHasPos =
@@ -452,7 +454,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       assert left >= 0;
 
       if (left >= BLOCK_SIZE) {
-        pforUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
+        forDeltaUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
 
         if (indexHasFreq) {
           if (needsFreq) {
@@ -500,7 +502,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
         if (skipper == null) {
           // Lazy init: first time this enum has ever been used for skipping
           skipper =
-              new Lucene90SkipReader(
+              new Lucene99SkipReader(
                   docIn.clone(), MAX_SKIP_LEVELS, indexHasPos, indexHasOffsets, indexHasPayloads);
         }
 
@@ -512,7 +514,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
           skipped = true;
         }
 
-        // always plus one to fix the result, since skip position in Lucene90SkipReader
+        // always plus one to fix the result, since skip position in Lucene99SkipReader
         // is a little different from MultiLevelSkipListReader
         final int newDocUpto = skipper.skipTo(target) + 1;
 
@@ -563,7 +565,9 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
   // Also handles payloads + offsets
   final class EverythingEnum extends PostingsEnum {
 
-    final PForUtil pforUtil = new PForUtil(new ForUtil());
+    final ForUtil forUtil = new ForUtil();
+    final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(forUtil);
+    final PForUtil pforUtil = new PForUtil(forUtil);
 
     private final long[] docBuffer = new long[BLOCK_SIZE + 1];
     private final long[] freqBuffer = new long[BLOCK_SIZE + 1];
@@ -584,7 +588,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     private int docBufferUpto;
     private int posBufferUpto;
 
-    private Lucene90SkipReader skipper;
+    private Lucene99SkipReader skipper;
     private boolean skipped;
 
     final IndexInput startDocIn;
@@ -651,11 +655,11 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
               >= 0;
       indexHasPayloads = fieldInfo.hasPayloads();
 
-      this.startDocIn = Lucene90PostingsReader.this.docIn;
+      this.startDocIn = Lucene99PostingsReader.this.docIn;
       this.docIn = null;
-      this.posIn = Lucene90PostingsReader.this.posIn.clone();
+      this.posIn = Lucene99PostingsReader.this.posIn.clone();
       if (indexHasOffsets || indexHasPayloads) {
-        this.payIn = Lucene90PostingsReader.this.payIn.clone();
+        this.payIn = Lucene99PostingsReader.this.payIn.clone();
       } else {
         this.payIn = null;
       }
@@ -751,7 +755,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       assert left >= 0;
 
       if (left >= BLOCK_SIZE) {
-        pforUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
+        forDeltaUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
         pforUtil.decode(docIn, freqBuffer);
         blockUpto += BLOCK_SIZE;
       } else if (docFreq == 1) {
@@ -863,7 +867,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
         if (skipper == null) {
           // Lazy init: first time this enum has ever been used for skipping
           skipper =
-              new Lucene90SkipReader(
+              new Lucene99SkipReader(
                   docIn.clone(), MAX_SKIP_LEVELS, true, indexHasOffsets, indexHasPayloads);
         }
 
@@ -1047,14 +1051,16 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
 
   final class BlockImpactsDocsEnum extends ImpactsEnum {
 
-    final PForUtil pforUtil = new PForUtil(new ForUtil());
+    final ForUtil forUtil = new ForUtil();
+    final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(forUtil);
+    final PForUtil pforUtil = new PForUtil(forUtil);
 
     private final long[] docBuffer = new long[BLOCK_SIZE + 1];
     private final long[] freqBuffer = new long[BLOCK_SIZE];
 
     private int docBufferUpto;
 
-    private final Lucene90ScoreSkipReader skipper;
+    private final Lucene99ScoreSkipReader skipper;
 
     final IndexInput docIn;
 
@@ -1086,7 +1092,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
               >= 0;
       final boolean indexHasPayloads = fieldInfo.hasPayloads();
 
-      this.docIn = Lucene90PostingsReader.this.docIn.clone();
+      this.docIn = Lucene99PostingsReader.this.docIn.clone();
 
       docFreq = termState.docFreq;
       docIn.seek(termState.docStartFP);
@@ -1097,7 +1103,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       docBufferUpto = BLOCK_SIZE;
 
       skipper =
-          new Lucene90ScoreSkipReader(
+          new Lucene99ScoreSkipReader(
               docIn.clone(), MAX_SKIP_LEVELS, indexHasPositions, indexHasOffsets, indexHasPayloads);
       skipper.init(
           termState.docStartFP + termState.skipOffset,
@@ -1141,7 +1147,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       assert left >= 0;
 
       if (left >= BLOCK_SIZE) {
-        pforUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
+        forDeltaUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
         if (indexHasFreqs) {
           isFreqsRead = false;
         }
@@ -1160,7 +1166,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     @Override
     public void advanceShallow(int target) throws IOException {
       if (target > nextSkipDoc) {
-        // always plus one to fix the result, since skip position in Lucene90SkipReader
+        // always plus one to fix the result, since skip position in Lucene99SkipReader
         // is a little different from MultiLevelSkipListReader
         final int newDocUpto = skipper.skipTo(target) + 1;
 
@@ -1249,8 +1255,9 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
   }
 
   final class BlockImpactsPostingsEnum extends ImpactsEnum {
-
-    final PForUtil pforUtil = new PForUtil(new ForUtil());
+    final ForUtil forUtil = new ForUtil();
+    final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(forUtil);
+    final PForUtil pforUtil = new PForUtil(forUtil);
 
     private final long[] docBuffer = new long[BLOCK_SIZE];
     private final long[] freqBuffer = new long[BLOCK_SIZE];
@@ -1259,7 +1266,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     private int docBufferUpto;
     private int posBufferUpto;
 
-    private final Lucene90ScoreSkipReader skipper;
+    private final Lucene99ScoreSkipReader skipper;
 
     final IndexInput docIn;
     final IndexInput posIn;
@@ -1311,9 +1318,9 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
               >= 0;
       indexHasPayloads = fieldInfo.hasPayloads();
 
-      this.docIn = Lucene90PostingsReader.this.docIn.clone();
+      this.docIn = Lucene99PostingsReader.this.docIn.clone();
 
-      this.posIn = Lucene90PostingsReader.this.posIn.clone();
+      this.posIn = Lucene99PostingsReader.this.posIn.clone();
 
       docFreq = termState.docFreq;
       docTermStartFP = termState.docStartFP;
@@ -1337,7 +1344,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       docBufferUpto = BLOCK_SIZE;
 
       skipper =
-          new Lucene90ScoreSkipReader(
+          new Lucene99ScoreSkipReader(
               docIn.clone(), MAX_SKIP_LEVELS, true, indexHasOffsets, indexHasPayloads);
       skipper.init(
           docTermStartFP + termState.skipOffset,
@@ -1362,7 +1369,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       assert left >= 0;
 
       if (left >= BLOCK_SIZE) {
-        pforUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
+        forDeltaUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
         pforUtil.decode(docIn, freqBuffer);
       } else {
         readVIntBlock(docIn, docBuffer, freqBuffer, left, true);
@@ -1405,7 +1412,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     @Override
     public void advanceShallow(int target) throws IOException {
       if (target > nextSkipDoc) {
-        // always plus one to fix the result, since skip position in Lucene90SkipReader
+        // always plus one to fix the result, since skip position in Lucene99SkipReader
         // is a little different from MultiLevelSkipListReader
         final int newDocUpto = skipper.skipTo(target) + 1;
 
@@ -1542,7 +1549,9 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
 
   final class BlockImpactsEverythingEnum extends ImpactsEnum {
 
-    final PForUtil pforUtil = new PForUtil(new ForUtil());
+    final ForUtil forUtil = new ForUtil();
+    final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(forUtil);
+    final PForUtil pforUtil = new PForUtil(forUtil);
 
     private final long[] docBuffer = new long[BLOCK_SIZE];
     private final long[] freqBuffer = new long[BLOCK_SIZE];
@@ -1563,7 +1572,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     private int docBufferUpto;
     private int posBufferUpto;
 
-    private final Lucene90ScoreSkipReader skipper;
+    private final Lucene99ScoreSkipReader skipper;
 
     final IndexInput docIn;
     final IndexInput posIn;
@@ -1637,16 +1646,16 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       needsOffsets = PostingsEnum.featureRequested(flags, PostingsEnum.OFFSETS);
       needsPayloads = PostingsEnum.featureRequested(flags, PostingsEnum.PAYLOADS);
 
-      this.docIn = Lucene90PostingsReader.this.docIn.clone();
+      this.docIn = Lucene99PostingsReader.this.docIn.clone();
 
       if (indexHasPos && needsPositions) {
-        this.posIn = Lucene90PostingsReader.this.posIn.clone();
+        this.posIn = Lucene99PostingsReader.this.posIn.clone();
       } else {
         this.posIn = null;
       }
 
       if ((indexHasOffsets && needsOffsets) || (indexHasPayloads && needsPayloads)) {
-        this.payIn = Lucene90PostingsReader.this.payIn.clone();
+        this.payIn = Lucene99PostingsReader.this.payIn.clone();
       } else {
         this.payIn = null;
       }
@@ -1696,7 +1705,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       docBufferUpto = BLOCK_SIZE;
 
       skipper =
-          new Lucene90ScoreSkipReader(
+          new Lucene99ScoreSkipReader(
               docIn.clone(), MAX_SKIP_LEVELS, indexHasPos, indexHasOffsets, indexHasPayloads);
       skipper.init(
           docTermStartFP + termState.skipOffset,
@@ -1751,7 +1760,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
       assert left >= 0;
 
       if (left >= BLOCK_SIZE) {
-        pforUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
+        forDeltaUtil.decodeAndPrefixSum(docIn, accum, docBuffer);
         if (indexHasFreq) {
           isFreqsRead =
               false; // freq block will be loaded lazily when necessary, we don't load it here
@@ -1839,7 +1848,7 @@ public final class Lucene90PostingsReader extends PostingsReaderBase {
     @Override
     public void advanceShallow(int target) throws IOException {
       if (target > nextSkipDoc) {
-        // always plus one to fix the result, since skip position in Lucene90SkipReader
+        // always plus one to fix the result, since skip position in Lucene99SkipReader
         // is a little different from MultiLevelSkipListReader
         final int newDocUpto = skipper.skipTo(target) + 1;
 
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsWriter.java
similarity index 93%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsWriter.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsWriter.java
index f640d8d2c57..34b4c9c62a3 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90PostingsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99PostingsWriter.java
@@ -14,22 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
-import static org.apache.lucene.codecs.lucene90.ForUtil.BLOCK_SIZE;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.DOC_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.MAX_SKIP_LEVELS;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.PAY_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.POS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.TERMS_CODEC;
-import static org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.VERSION_CURRENT;
+import static org.apache.lucene.codecs.lucene99.ForUtil.BLOCK_SIZE;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.DOC_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.MAX_SKIP_LEVELS;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.PAY_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.POS_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.TERMS_CODEC;
+import static org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.VERSION_CURRENT;
 
 import java.io.IOException;
 import org.apache.lucene.codecs.BlockTermState;
 import org.apache.lucene.codecs.CodecUtil;
 import org.apache.lucene.codecs.CompetitiveImpactAccumulator;
 import org.apache.lucene.codecs.PushPostingsWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat.IntBlockTermState;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat.IntBlockTermState;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexFileNames;
@@ -48,10 +48,10 @@ import org.apache.lucene.util.IOUtils;
  *
  * <p>Postings list for each term will be stored separately.
  *
- * @see Lucene90SkipWriter for details about skipping setting and postings layout.
+ * @see Lucene99SkipWriter for details about skipping setting and postings layout.
  * @lucene.experimental
  */
-public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
+public final class Lucene99PostingsWriter extends PushPostingsWriterBase {
 
   IndexOutput docOut;
   IndexOutput posOut;
@@ -90,7 +90,8 @@ public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
   private int docCount;
 
   private final PForUtil pforUtil;
-  private final Lucene90SkipWriter skipWriter;
+  private final ForDeltaUtil forDeltaUtil;
+  private final Lucene99SkipWriter skipWriter;
 
   private boolean fieldHasNorms;
   private NumericDocValues norms;
@@ -98,11 +99,11 @@ public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
       new CompetitiveImpactAccumulator();
 
   /** Creates a postings writer */
-  public Lucene90PostingsWriter(SegmentWriteState state) throws IOException {
+  public Lucene99PostingsWriter(SegmentWriteState state) throws IOException {
 
     String docFileName =
         IndexFileNames.segmentFileName(
-            state.segmentInfo.name, state.segmentSuffix, Lucene90PostingsFormat.DOC_EXTENSION);
+            state.segmentInfo.name, state.segmentSuffix, Lucene99PostingsFormat.DOC_EXTENSION);
     docOut = state.directory.createOutput(docFileName, state.context);
     IndexOutput posOut = null;
     IndexOutput payOut = null;
@@ -110,12 +111,14 @@ public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
     try {
       CodecUtil.writeIndexHeader(
           docOut, DOC_CODEC, VERSION_CURRENT, state.segmentInfo.getId(), state.segmentSuffix);
-      pforUtil = new PForUtil(new ForUtil());
+      final ForUtil forUtil = new ForUtil();
+      forDeltaUtil = new ForDeltaUtil(forUtil);
+      pforUtil = new PForUtil(forUtil);
       if (state.fieldInfos.hasProx()) {
         posDeltaBuffer = new long[BLOCK_SIZE];
         String posFileName =
             IndexFileNames.segmentFileName(
-                state.segmentInfo.name, state.segmentSuffix, Lucene90PostingsFormat.POS_EXTENSION);
+                state.segmentInfo.name, state.segmentSuffix, Lucene99PostingsFormat.POS_EXTENSION);
         posOut = state.directory.createOutput(posFileName, state.context);
         CodecUtil.writeIndexHeader(
             posOut, POS_CODEC, VERSION_CURRENT, state.segmentInfo.getId(), state.segmentSuffix);
@@ -141,7 +144,7 @@ public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
               IndexFileNames.segmentFileName(
                   state.segmentInfo.name,
                   state.segmentSuffix,
-                  Lucene90PostingsFormat.PAY_EXTENSION);
+                  Lucene99PostingsFormat.PAY_EXTENSION);
           payOut = state.directory.createOutput(payFileName, state.context);
           CodecUtil.writeIndexHeader(
               payOut, PAY_CODEC, VERSION_CURRENT, state.segmentInfo.getId(), state.segmentSuffix);
@@ -167,7 +170,7 @@ public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
 
     // TODO: should we try skipping every 2/4 blocks...?
     skipWriter =
-        new Lucene90SkipWriter(
+        new Lucene99SkipWriter(
             MAX_SKIP_LEVELS, BLOCK_SIZE, state.segmentInfo.maxDoc(), docOut, posOut, payOut);
   }
 
@@ -240,7 +243,7 @@ public final class Lucene90PostingsWriter extends PushPostingsWriterBase {
     docCount++;
 
     if (docBufferUpto == BLOCK_SIZE) {
-      pforUtil.encode(docDeltaBuffer, docOut);
+      forDeltaUtil.encodeDeltas(docDeltaBuffer, docOut);
       if (writeFreqs) {
         pforUtil.encode(freqBuffer, docOut);
       }
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90ScoreSkipReader.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99ScoreSkipReader.java
similarity index 97%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90ScoreSkipReader.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99ScoreSkipReader.java
index 44789a98334..f2882c085c4 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90ScoreSkipReader.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99ScoreSkipReader.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import java.io.IOException;
 import java.util.AbstractList;
@@ -27,7 +27,7 @@ import org.apache.lucene.store.ByteArrayDataInput;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.util.ArrayUtil;
 
-final class Lucene90ScoreSkipReader extends Lucene90SkipReader {
+final class Lucene99ScoreSkipReader extends Lucene99SkipReader {
 
   private final byte[][] impactData;
   private final int[] impactDataLength;
@@ -36,7 +36,7 @@ final class Lucene90ScoreSkipReader extends Lucene90SkipReader {
   private int numLevels = 1;
   private final MutableImpactList[] perLevelImpacts;
 
-  public Lucene90ScoreSkipReader(
+  public Lucene99ScoreSkipReader(
       IndexInput skipStream,
       int maxSkipLevels,
       boolean hasPos,
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipReader.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99SkipReader.java
similarity index 94%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipReader.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99SkipReader.java
index da31bd75a80..a6cb7c3a811 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipReader.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99SkipReader.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -33,13 +33,13 @@ import org.apache.lucene.store.IndexInput;
  * 0 1 2 3 4 5
  * d d d d d d    (posting list)
  *     ^     ^    (skip point in MultiLeveSkipWriter)
- *       ^        (skip point in Lucene90SkipWriter)
+ *       ^        (skip point in Lucene99SkipWriter)
  * </pre>
  *
  * <p>In this case, MultiLevelSkipListReader will use the last document as a skip point, while
- * Lucene90SkipReader should assume no skip point will comes.
+ * Lucene99SkipReader should assume no skip point will comes.
  *
- * <p>If we use the interface directly in Lucene90SkipReader, it may silly try to read another skip
+ * <p>If we use the interface directly in Lucene99SkipReader, it may silly try to read another skip
  * data after the only skip point is loaded.
  *
  * <p>To illustrate this, we can call skipTo(d[5]), since skip point d[3] has smaller docId, and
@@ -48,7 +48,7 @@ import org.apache.lucene.store.IndexInput;
  *
  * <p>Therefore, we'll trim df before passing it to the interface. see trim(int)
  */
-class Lucene90SkipReader extends MultiLevelSkipListReader {
+public class Lucene99SkipReader extends MultiLevelSkipListReader {
   private long[] docPointer;
   private long[] posPointer;
   private long[] payPointer;
@@ -61,7 +61,7 @@ class Lucene90SkipReader extends MultiLevelSkipListReader {
   private long lastDocPointer;
   private int lastPosBufferUpto;
 
-  public Lucene90SkipReader(
+  public Lucene99SkipReader(
       IndexInput skipStream,
       int maxSkipLevels,
       boolean hasPos,
@@ -90,7 +90,7 @@ class Lucene90SkipReader extends MultiLevelSkipListReader {
   /**
    * Trim original docFreq to tell skipReader read proper number of skip points.
    *
-   * <p>Since our definition in Lucene90Skip* is a little different from MultiLevelSkip* This
+   * <p>Since our definition in Lucene99Skip* is a little different from MultiLevelSkip* This
    * trimmed docFreq will prevent skipReader from: 1. silly reading a non-existed skip point after
    * the last block boundary 2. moving into the vInt block
    */
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99SkipWriter.java
similarity index 95%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipWriter.java
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99SkipWriter.java
index 48deafa4225..ec50e5e5c16 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90SkipWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/Lucene99SkipWriter.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -45,12 +45,11 @@ import org.apache.lucene.store.IndexOutput;
  * docID[11], etc. 2. its related file points(position, payload), 3. related numbers or
  * uptos(position, payload). 4. start offset.
  */
-final class Lucene90SkipWriter extends MultiLevelSkipListWriter {
+public final class Lucene99SkipWriter extends MultiLevelSkipListWriter {
   private int[] lastSkipDoc;
   private long[] lastSkipDocPointer;
   private long[] lastSkipPosPointer;
   private long[] lastSkipPayPointer;
-  private int[] lastPayloadByteUpto;
 
   private final IndexOutput docOut;
   private final IndexOutput posOut;
@@ -67,7 +66,7 @@ final class Lucene90SkipWriter extends MultiLevelSkipListWriter {
   private boolean fieldHasOffsets;
   private boolean fieldHasPayloads;
 
-  public Lucene90SkipWriter(
+  public Lucene99SkipWriter(
       int maxSkipLevels,
       int blockSize,
       int docCount,
@@ -86,7 +85,6 @@ final class Lucene90SkipWriter extends MultiLevelSkipListWriter {
       if (payOut != null) {
         lastSkipPayPointer = new long[maxSkipLevels];
       }
-      lastPayloadByteUpto = new int[maxSkipLevels];
     }
     curCompetitiveFreqNorms = new CompetitiveImpactAccumulator[maxSkipLevels];
     for (int i = 0; i < maxSkipLevels; ++i) {
@@ -137,9 +135,6 @@ final class Lucene90SkipWriter extends MultiLevelSkipListWriter {
       Arrays.fill(lastSkipDocPointer, lastDocFP);
       if (fieldHasPositions) {
         Arrays.fill(lastSkipPosPointer, lastPosFP);
-        if (fieldHasPayloads) {
-          Arrays.fill(lastPayloadByteUpto, 0);
-        }
         if (fieldHasOffsets || fieldHasPayloads) {
           Arrays.fill(lastSkipPayPointer, lastPayFP);
         }
@@ -216,7 +211,8 @@ final class Lucene90SkipWriter extends MultiLevelSkipListWriter {
     competitiveFreqNorms.clear();
   }
 
-  static void writeImpacts(CompetitiveImpactAccumulator acc, DataOutput out) throws IOException {
+  public static void writeImpacts(CompetitiveImpactAccumulator acc, DataOutput out)
+      throws IOException {
     Collection<Impact> impacts = acc.getCompetitiveFreqNormPairs();
     Impact previous = new Impact(0, 0);
     for (Impact impact : impacts) {
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene99/PForUtil.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/PForUtil.java
new file mode 100644
index 00000000000..93ebb3d0f9d
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/PForUtil.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.lucene.codecs.lucene99;
+
+import java.io.IOException;
+import java.util.Arrays;
+import org.apache.lucene.store.DataInput;
+import org.apache.lucene.store.DataOutput;
+import org.apache.lucene.util.LongHeap;
+import org.apache.lucene.util.packed.PackedInts;
+
+/** Utility class to encode sequences of 128 small positive integers. */
+final class PForUtil {
+
+  private static final int MAX_EXCEPTIONS = 7;
+
+  // IDENTITY_PLUS_ONE[i] == i + 1
+  private static final long[] IDENTITY_PLUS_ONE = new long[ForUtil.BLOCK_SIZE];
+
+  static {
+    for (int i = 0; i < ForUtil.BLOCK_SIZE; ++i) {
+      IDENTITY_PLUS_ONE[i] = i + 1;
+    }
+  }
+
+  static boolean allEqual(long[] l) {
+    for (int i = 1; i < ForUtil.BLOCK_SIZE; ++i) {
+      if (l[i] != l[0]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  private final ForUtil forUtil;
+
+  PForUtil(ForUtil forUtil) {
+    assert ForUtil.BLOCK_SIZE <= 256 : "blocksize must fit in one byte. got " + ForUtil.BLOCK_SIZE;
+    this.forUtil = forUtil;
+  }
+
+  /** Encode 128 integers from {@code longs} into {@code out}. */
+  void encode(long[] longs, DataOutput out) throws IOException {
+    // Determine the top MAX_EXCEPTIONS + 1 values
+    final LongHeap top = new LongHeap(MAX_EXCEPTIONS + 1);
+    for (int i = 0; i <= MAX_EXCEPTIONS; ++i) {
+      top.push(longs[i]);
+    }
+    long topValue = top.top();
+    for (int i = MAX_EXCEPTIONS + 1; i < ForUtil.BLOCK_SIZE; ++i) {
+      if (longs[i] > topValue) {
+        topValue = top.updateTop(longs[i]);
+      }
+    }
+
+    long max = 0L;
+    for (int i = 1; i <= top.size(); ++i) {
+      max = Math.max(max, top.get(i));
+    }
+
+    final int maxBitsRequired = PackedInts.bitsRequired(max);
+    // We store the patch on a byte, so we can't decrease the number of bits required by more than 8
+    final int patchedBitsRequired =
+        Math.max(PackedInts.bitsRequired(topValue), maxBitsRequired - 8);
+    int numExceptions = 0;
+    final long maxUnpatchedValue = (1L << patchedBitsRequired) - 1;
+    for (int i = 2; i <= top.size(); ++i) {
+      if (top.get(i) > maxUnpatchedValue) {
+        numExceptions++;
+      }
+    }
+    final byte[] exceptions = new byte[numExceptions * 2];
+    if (numExceptions > 0) {
+      int exceptionCount = 0;
+      for (int i = 0; i < ForUtil.BLOCK_SIZE; ++i) {
+        if (longs[i] > maxUnpatchedValue) {
+          exceptions[exceptionCount * 2] = (byte) i;
+          exceptions[exceptionCount * 2 + 1] = (byte) (longs[i] >>> patchedBitsRequired);
+          longs[i] &= maxUnpatchedValue;
+          exceptionCount++;
+        }
+      }
+      assert exceptionCount == numExceptions : exceptionCount + " " + numExceptions;
+    }
+
+    if (allEqual(longs) && maxBitsRequired <= 8) {
+      for (int i = 0; i < numExceptions; ++i) {
+        exceptions[2 * i + 1] =
+            (byte) (Byte.toUnsignedLong(exceptions[2 * i + 1]) << patchedBitsRequired);
+      }
+      out.writeByte((byte) (numExceptions << 5));
+      out.writeVLong(longs[0]);
+    } else {
+      final int token = (numExceptions << 5) | patchedBitsRequired;
+      out.writeByte((byte) token);
+      forUtil.encode(longs, patchedBitsRequired, out);
+    }
+    out.writeBytes(exceptions, exceptions.length);
+  }
+
+  /** Decode 128 integers into {@code ints}. */
+  void decode(DataInput in, long[] longs) throws IOException {
+    final int token = Byte.toUnsignedInt(in.readByte());
+    final int bitsPerValue = token & 0x1f;
+    final int numExceptions = token >>> 5;
+    if (bitsPerValue == 0) {
+      Arrays.fill(longs, 0, ForUtil.BLOCK_SIZE, in.readVLong());
+    } else {
+      forUtil.decode(bitsPerValue, in, longs);
+    }
+    for (int i = 0; i < numExceptions; ++i) {
+      longs[Byte.toUnsignedInt(in.readByte())] |=
+          Byte.toUnsignedLong(in.readByte()) << bitsPerValue;
+    }
+  }
+
+  /** Skip 128 integers. */
+  void skip(DataInput in) throws IOException {
+    final int token = Byte.toUnsignedInt(in.readByte());
+    final int bitsPerValue = token & 0x1f;
+    final int numExceptions = token >>> 5;
+    if (bitsPerValue == 0) {
+      in.readVLong();
+      in.skipBytes((numExceptions << 1));
+    } else {
+      in.skipBytes(forUtil.numBytes(bitsPerValue) + (numExceptions << 1));
+    }
+  }
+}
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/gen_ForUtil.py
similarity index 84%
rename from lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py
rename to lucene/core/src/java/org/apache/lucene/codecs/lucene99/gen_ForUtil.py
index a468c590cf9..cd81d493570 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/gen_ForUtil.py
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/gen_ForUtil.py
@@ -40,7 +40,7 @@ HEADER = """// This file has been automatically generated, DO NOT EDIT
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import java.io.IOException;
 import org.apache.lucene.store.DataInput;
@@ -156,6 +156,94 @@ final class ForUtil {
     }
   }
 
+  private static void prefixSum8(long[] arr, long base) {
+    expand8To32(arr);
+    prefixSum32(arr, base);
+  }
+
+  private static void prefixSum16(long[] arr, long base) {
+    // We need to move to the next primitive size to avoid overflows
+    expand16To32(arr);
+    prefixSum32(arr, base);
+  }
+
+  private static void prefixSum32(long[] arr, long base) {
+    arr[0] += base << 32;
+    innerPrefixSum32(arr);
+    expand32(arr);
+    final long l = arr[BLOCK_SIZE/2-1];
+    for (int i = BLOCK_SIZE/2; i < BLOCK_SIZE; ++i) {
+      arr[i] += l;
+    }
+  }
+
+  // For some reason unrolling seems to help
+  private static void innerPrefixSum32(long[] arr) {
+    arr[1] += arr[0];
+    arr[2] += arr[1];
+    arr[3] += arr[2];
+    arr[4] += arr[3];
+    arr[5] += arr[4];
+    arr[6] += arr[5];
+    arr[7] += arr[6];
+    arr[8] += arr[7];
+    arr[9] += arr[8];
+    arr[10] += arr[9];
+    arr[11] += arr[10];
+    arr[12] += arr[11];
+    arr[13] += arr[12];
+    arr[14] += arr[13];
+    arr[15] += arr[14];
+    arr[16] += arr[15];
+    arr[17] += arr[16];
+    arr[18] += arr[17];
+    arr[19] += arr[18];
+    arr[20] += arr[19];
+    arr[21] += arr[20];
+    arr[22] += arr[21];
+    arr[23] += arr[22];
+    arr[24] += arr[23];
+    arr[25] += arr[24];
+    arr[26] += arr[25];
+    arr[27] += arr[26];
+    arr[28] += arr[27];
+    arr[29] += arr[28];
+    arr[30] += arr[29];
+    arr[31] += arr[30];
+    arr[32] += arr[31];
+    arr[33] += arr[32];
+    arr[34] += arr[33];
+    arr[35] += arr[34];
+    arr[36] += arr[35];
+    arr[37] += arr[36];
+    arr[38] += arr[37];
+    arr[39] += arr[38];
+    arr[40] += arr[39];
+    arr[41] += arr[40];
+    arr[42] += arr[41];
+    arr[43] += arr[42];
+    arr[44] += arr[43];
+    arr[45] += arr[44];
+    arr[46] += arr[45];
+    arr[47] += arr[46];
+    arr[48] += arr[47];
+    arr[49] += arr[48];
+    arr[50] += arr[49];
+    arr[51] += arr[50];
+    arr[52] += arr[51];
+    arr[53] += arr[52];
+    arr[54] += arr[53];
+    arr[55] += arr[54];
+    arr[56] += arr[55];
+    arr[57] += arr[56];
+    arr[58] += arr[57];
+    arr[59] += arr[58];
+    arr[60] += arr[59];
+    arr[61] += arr[60];
+    arr[62] += arr[61];
+    arr[63] += arr[62];
+  }
+
   private final long[] tmp = new long[BLOCK_SIZE / 2];
 
   /** Encode 128 integers from {@code longs} into {@code out}. */
@@ -405,12 +493,9 @@ if __name__ == '__main__':
 
   f.write("""
   /**
-   * Decodes 128 integers into 64 {@code longs} such that each long contains two values, each
-   * represented with 32 bits. Values [0..63] are encoded in the high-order bits of {@code longs}
-   * [0..63], and values [64..127] are encoded in the low-order bits of {@code longs} [0..63]. This
-   * representation may allow subsequent operations to be performed on two values at a time.
+   * Delta-decode 128 integers into {@code longs}.
    */
-  void decodeTo32(int bitsPerValue, DataInput in, long[] longs) throws IOException {
+  void decodeAndPrefixSum(int bitsPerValue, DataInput in, long base, long[] longs) throws IOException {
     switch (bitsPerValue) {
 """)
   for bpv in range(1, MAX_SPECIALIZED_BITS_PER_VALUE+1):
@@ -419,14 +504,14 @@ if __name__ == '__main__':
       next_primitive = 8
     elif bpv <= 16:
       next_primitive = 16
-    f.write('      case %d:\n' %bpv)
-    f.write('        decode%d(in, tmp, longs);\n' %bpv)
-    if next_primitive <= 16:
-      f.write('        expand%dTo32(longs);\n' %next_primitive)
-    f.write('        break;\n')
-  f.write('      default:\n')
-  f.write('        decodeSlow(bitsPerValue, in, tmp, longs);\n')
-  f.write('        break;\n')
+    f.write('    case %d:\n' %bpv)
+    f.write('      decode%d(in, tmp, longs);\n' %bpv)
+    f.write('      prefixSum%d(longs, base);\n' %next_primitive)
+    f.write('      break;\n')
+  f.write('    default:\n')
+  f.write('      decodeSlow(bitsPerValue, in, tmp, longs);\n')
+  f.write('      prefixSum32(longs, base);\n')
+  f.write('      break;\n')
   f.write('    }\n')
   f.write('  }\n')
 
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene99/package-info.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/package-info.java
index 2511e3be0da..2df2cfc9a30 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene99/package-info.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene99/package-info.java
@@ -151,15 +151,15 @@
  *       field names. These are used to store auxiliary information about the document, such as its
  *       title, url, or an identifier to access a database. The set of stored fields are what is
  *       returned for each hit when searching. This is keyed by document number.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term dictionary}. A
+ *   <li>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Term dictionary}. A
  *       dictionary containing all of the terms used in all of the indexed fields of all of the
  *       documents. The dictionary also contains the number of documents which contain the term, and
  *       pointers to the term's frequency and proximity data.
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Frequency data}. For
+ *   <li>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Term Frequency data}. For
  *       each term in the dictionary, the numbers of all the documents that contain that term, and
  *       the frequency of the term in that document, unless frequencies are omitted ({@link
  *       org.apache.lucene.index.IndexOptions#DOCS IndexOptions.DOCS})
- *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Proximity data}. For
+ *   <li>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Term Proximity data}. For
  *       each term in the dictionary, the positions that the term occurs in each document. Note that
  *       this will not exist if all fields in all documents omit position data.
  *   <li>{@link org.apache.lucene.codecs.lucene90.Lucene90NormsFormat Normalization factors}. For
@@ -255,27 +255,27 @@
  * <td>The stored fields for documents</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Dictionary}</td>
+ * <td>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Term Dictionary}</td>
  * <td>.tim</td>
  * <td>The term dictionary, stores term info</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Term Index}</td>
+ * <td>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Term Index}</td>
  * <td>.tip</td>
  * <td>The index into the Term Dictionary</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Frequencies}</td>
+ * <td>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Frequencies}</td>
  * <td>.doc</td>
  * <td>Contains the list of docs which contain each term along with frequency</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Positions}</td>
+ * <td>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Positions}</td>
  * <td>.pos</td>
  * <td>Stores position information about where a term occurs in the index</td>
  * </tr>
  * <tr>
- * <td>{@link org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat Payloads}</td>
+ * <td>{@link org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat Payloads}</td>
  * <td>.pay</td>
  * <td>Stores additional per-position metadata information such as character offsets and user payloads</td>
  * </tr>
diff --git a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
index 853e8f9b0c7..ea9df193413 100644
--- a/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
+++ b/lucene/core/src/java/org/apache/lucene/search/PhraseQuery.java
@@ -21,8 +21,8 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
 import org.apache.lucene.index.ImpactsEnum;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
@@ -401,10 +401,10 @@ public class PhraseQuery extends Query {
   /**
    * A guess of the average number of simple operations for the initial seek and buffer refill per
    * document for the positions of a term. See also {@link
-   * Lucene90PostingsReader.BlockImpactsPostingsEnum#nextPosition()}.
+   * Lucene99PostingsReader.BlockImpactsPostingsEnum#nextPosition()}.
    *
    * <p>Aside: Instead of being constant this could depend among others on {@link
-   * Lucene90PostingsFormat#BLOCK_SIZE}, {@link TermsEnum#docFreq()}, {@link
+   * Lucene99PostingsFormat#BLOCK_SIZE}, {@link TermsEnum#docFreq()}, {@link
    * TermsEnum#totalTermFreq()}, {@link DocIdSetIterator#cost()} (expected number of matching docs),
    * {@link LeafReader#maxDoc()} (total number of docs in the segment), and the seek time and block
    * size of the device storing the index.
@@ -413,7 +413,7 @@ public class PhraseQuery extends Query {
 
   /**
    * Number of simple operations in {@link
-   * Lucene90PostingsReader.BlockImpactsPostingsEnum#nextPosition()} when no seek or buffer refill
+   * Lucene99PostingsReader.BlockImpactsPostingsEnum#nextPosition()} when no seek or buffer refill
    * is done.
    */
   private static final int TERM_OPS_PER_POS = 7;
diff --git a/lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat b/lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
index 15681e8a2e5..0fd87daff7d 100644
--- a/lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
+++ b/lucene/core/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
@@ -13,4 +13,4 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat
+org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestForUtil.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestForDeltaUtil.java
similarity index 70%
copy from lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestForUtil.java
copy to lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestForDeltaUtil.java
index 363226423ee..29448ff1e41 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestForUtil.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestForDeltaUtil.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
 import java.io.IOException;
@@ -26,20 +26,19 @@ import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.lucene.tests.util.TestUtil;
-import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.packed.PackedInts;
 
-public class TestForUtil extends LuceneTestCase {
+public class TestForDeltaUtil extends LuceneTestCase {
 
   public void testEncodeDecode() throws IOException {
     final int iterations = RandomNumbers.randomIntBetween(random(), 50, 1000);
     final int[] values = new int[iterations * ForUtil.BLOCK_SIZE];
 
     for (int i = 0; i < iterations; ++i) {
-      final int bpv = TestUtil.nextInt(random(), 1, 31);
+      final int bpv = TestUtil.nextInt(random(), 1, 31 - 7);
       for (int j = 0; j < ForUtil.BLOCK_SIZE; ++j) {
         values[i * ForUtil.BLOCK_SIZE + j] =
-            RandomNumbers.randomIntBetween(random(), 0, (int) PackedInts.maxValue(bpv));
+            RandomNumbers.randomIntBetween(random(), 1, (int) PackedInts.maxValue(bpv));
       }
     }
 
@@ -49,18 +48,14 @@ public class TestForUtil extends LuceneTestCase {
     {
       // encode
       IndexOutput out = d.createOutput("test.bin", IOContext.DEFAULT);
-      final ForUtil forUtil = new ForUtil();
+      final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(new ForUtil());
 
       for (int i = 0; i < iterations; ++i) {
         long[] source = new long[ForUtil.BLOCK_SIZE];
-        long or = 0;
         for (int j = 0; j < ForUtil.BLOCK_SIZE; ++j) {
           source[j] = values[i * ForUtil.BLOCK_SIZE + j];
-          or |= source[j];
         }
-        final int bpv = PackedInts.bitsRequired(or);
-        out.writeByte((byte) bpv);
-        forUtil.encode(source, bpv, out);
+        forDeltaUtil.encodeDeltas(source, out);
       }
       endPointer = out.getFilePointer();
       out.close();
@@ -69,21 +64,21 @@ public class TestForUtil extends LuceneTestCase {
     {
       // decode
       IndexInput in = d.openInput("test.bin", IOContext.READONCE);
-      final ForUtil forUtil = new ForUtil();
+      final ForDeltaUtil forDeltaUtil = new ForDeltaUtil(new ForUtil());
       for (int i = 0; i < iterations; ++i) {
-        final int bitsPerValue = in.readByte();
-        final long currentFilePointer = in.getFilePointer();
+        long base = 0;
         final long[] restored = new long[ForUtil.BLOCK_SIZE];
-        forUtil.decode(bitsPerValue, in, restored);
-        int[] ints = new int[ForUtil.BLOCK_SIZE];
+        forDeltaUtil.decodeAndPrefixSum(in, base, restored);
+        final long[] expected = new long[ForUtil.BLOCK_SIZE];
         for (int j = 0; j < ForUtil.BLOCK_SIZE; ++j) {
-          ints[j] = Math.toIntExact(restored[j]);
+          expected[j] = values[i * ForUtil.BLOCK_SIZE + j];
+          if (j > 0) {
+            expected[j] += expected[j - 1];
+          } else {
+            expected[j] += base;
+          }
         }
-        assertArrayEquals(
-            Arrays.toString(ints),
-            ArrayUtil.copyOfSubArray(values, i * ForUtil.BLOCK_SIZE, (i + 1) * ForUtil.BLOCK_SIZE),
-            ints);
-        assertEquals(forUtil.numBytes(bitsPerValue), in.getFilePointer() - currentFilePointer);
+        assertArrayEquals(Arrays.toString(restored), expected, restored);
       }
       assertEquals(endPointer, in.getFilePointer());
       in.close();
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestForUtil.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestForUtil.java
similarity index 98%
rename from lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestForUtil.java
rename to lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestForUtil.java
index 363226423ee..2f179c743af 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestForUtil.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestForUtil.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
 import java.io.IOException;
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestLucene90PostingsFormat.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestLucene99PostingsFormat.java
similarity index 91%
rename from lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestLucene90PostingsFormat.java
rename to lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestLucene99PostingsFormat.java
index 90a9ebe5369..99c0e0a6ae2 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestLucene90PostingsFormat.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestLucene99PostingsFormat.java
@@ -14,7 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
+
+import static org.apache.lucene.codecs.lucene99.Lucene99ScoreSkipReader.readImpacts;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -22,9 +24,9 @@ import java.util.Collections;
 import java.util.List;
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.CompetitiveImpactAccumulator;
-import org.apache.lucene.codecs.lucene90.Lucene90ScoreSkipReader.MutableImpactList;
 import org.apache.lucene.codecs.lucene90.blocktree.FieldReader;
 import org.apache.lucene.codecs.lucene90.blocktree.Stats;
+import org.apache.lucene.codecs.lucene99.Lucene99ScoreSkipReader.MutableImpactList;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.DirectoryReader;
@@ -40,8 +42,8 @@ import org.apache.lucene.tests.analysis.MockAnalyzer;
 import org.apache.lucene.tests.index.BasePostingsFormatTestCase;
 import org.apache.lucene.tests.util.TestUtil;
 
-public class TestLucene90PostingsFormat extends BasePostingsFormatTestCase {
-  private final Codec codec = TestUtil.alwaysPostingsFormat(new Lucene90PostingsFormat());
+public class TestLucene99PostingsFormat extends BasePostingsFormatTestCase {
+  private final Codec codec = TestUtil.alwaysPostingsFormat(new Lucene99PostingsFormat());
 
   @Override
   protected Codec getCodec() {
@@ -77,7 +79,7 @@ public class TestLucene90PostingsFormat extends BasePostingsFormatTestCase {
     expectThrows(
         IllegalArgumentException.class,
         () -> {
-          new Lucene90PostingsFormat(minItemsInBlock, maxItemsInBlock);
+          new Lucene99PostingsFormat(minItemsInBlock, maxItemsInBlock);
         });
   }
 
@@ -131,13 +133,12 @@ public class TestLucene90PostingsFormat extends BasePostingsFormatTestCase {
     }
     try (Directory dir = newDirectory()) {
       try (IndexOutput out = dir.createOutput("foo", IOContext.DEFAULT)) {
-        Lucene90SkipWriter.writeImpacts(acc, out);
+        Lucene99SkipWriter.writeImpacts(acc, out);
       }
       try (IndexInput in = dir.openInput("foo", IOContext.DEFAULT)) {
         byte[] b = new byte[Math.toIntExact(in.length())];
         in.readBytes(b, 0, b.length);
-        List<Impact> impacts2 =
-            Lucene90ScoreSkipReader.readImpacts(new ByteArrayDataInput(b), new MutableImpactList());
+        List<Impact> impacts2 = readImpacts(new ByteArrayDataInput(b), new MutableImpactList());
         assertEquals(impacts, impacts2);
       }
     }
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestPForUtil.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestPForUtil.java
similarity index 73%
rename from lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestPForUtil.java
rename to lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestPForUtil.java
index a7b37030ad1..16f719e93b2 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/lucene90/TestPForUtil.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene99/TestPForUtil.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.lucene.codecs.lucene90;
+package org.apache.lucene.codecs.lucene99;
 
 import com.carrotsearch.randomizedtesting.generators.RandomNumbers;
 import java.io.IOException;
@@ -62,42 +62,6 @@ public class TestPForUtil extends LuceneTestCase {
     d.close();
   }
 
-  public void testDeltaEncodeDecode() throws IOException {
-    final int iterations = RandomNumbers.randomIntBetween(random(), 50, 1000);
-    // cap at 31 - 7 bpv to ensure we don't overflow when working with deltas (i.e., 128 24 bit
-    // values treated as deltas will result in a final value that can fit in 31 bits)
-    final int[] values = createTestData(iterations, 31 - 7);
-
-    final Directory d = new ByteBuffersDirectory();
-    final long endPointer = encodeTestData(iterations, values, d);
-
-    IndexInput in = d.openInput("test.bin", IOContext.READONCE);
-    final PForUtil pForUtil = new PForUtil(new ForUtil());
-    for (int i = 0; i < iterations; ++i) {
-      if (random().nextInt(5) == 0) {
-        pForUtil.skip(in);
-        continue;
-      }
-      long base = 0;
-      final long[] restored = new long[ForUtil.BLOCK_SIZE];
-      pForUtil.decodeAndPrefixSum(in, base, restored);
-      final long[] expected = new long[ForUtil.BLOCK_SIZE];
-      for (int j = 0; j < ForUtil.BLOCK_SIZE; ++j) {
-        expected[j] = values[i * ForUtil.BLOCK_SIZE + j];
-        if (j > 0) {
-          expected[j] += expected[j - 1];
-        } else {
-          expected[j] += base;
-        }
-      }
-      assertArrayEquals(Arrays.toString(restored), expected, restored);
-    }
-    assertEquals(endPointer, in.getFilePointer());
-    in.close();
-
-    d.close();
-  }
-
   private int[] createTestData(int iterations, int maxBpv) {
     final int[] values = new int[iterations * ForUtil.BLOCK_SIZE];
 
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/TermIntervalsSource.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/TermIntervalsSource.java
index 414d360d5d1..2a5d8fffd01 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/TermIntervalsSource.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/TermIntervalsSource.java
@@ -21,8 +21,8 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Objects;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
 import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
@@ -261,10 +261,10 @@ class TermIntervalsSource extends IntervalsSource {
   /**
    * A guess of the average number of simple operations for the initial seek and buffer refill per
    * document for the positions of a term. See also {@link
-   * Lucene90PostingsReader.EverythingEnum#nextPosition()}.
+   * Lucene99PostingsReader.EverythingEnum#nextPosition()}.
    *
    * <p>Aside: Instead of being constant this could depend among others on {@link
-   * Lucene90PostingsFormat#BLOCK_SIZE}, {@link TermsEnum#docFreq()}, {@link
+   * Lucene99PostingsFormat#BLOCK_SIZE}, {@link TermsEnum#docFreq()}, {@link
    * TermsEnum#totalTermFreq()}, {@link DocIdSetIterator#cost()} (expected number of matching docs),
    * {@link LeafReader#maxDoc()} (total number of docs in the segment), and the seek time and block
    * size of the device storing the index.
@@ -272,7 +272,7 @@ class TermIntervalsSource extends IntervalsSource {
   private static final int TERM_POSNS_SEEK_OPS_PER_DOC = 128;
 
   /**
-   * Number of simple operations in {@link Lucene90PostingsReader.EverythingEnum#nextPosition()}
+   * Number of simple operations in {@link Lucene99PostingsReader.EverythingEnum#nextPosition()}
    * when no seek or buffer refill is done.
    */
   private static final int TERM_OPS_PER_POS = 7;
diff --git a/lucene/suggest/src/java/module-info.java b/lucene/suggest/src/java/module-info.java
index 4444a9dd2f1..673fa391213 100644
--- a/lucene/suggest/src/java/module-info.java
+++ b/lucene/suggest/src/java/module-info.java
@@ -30,7 +30,8 @@ module org.apache.lucene.suggest {
   provides org.apache.lucene.codecs.PostingsFormat with
       org.apache.lucene.search.suggest.document.Completion50PostingsFormat,
       org.apache.lucene.search.suggest.document.Completion84PostingsFormat,
-      org.apache.lucene.search.suggest.document.Completion90PostingsFormat;
+      org.apache.lucene.search.suggest.document.Completion90PostingsFormat,
+      org.apache.lucene.search.suggest.document.Completion99PostingsFormat;
   provides org.apache.lucene.analysis.TokenFilterFactory with
       org.apache.lucene.search.suggest.analyzing.SuggestStopFilterFactory;
 }
diff --git a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion50PostingsFormat.java b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion50PostingsFormat.java
index 02536cc7f26..e53e991db22 100644
--- a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion50PostingsFormat.java
+++ b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion50PostingsFormat.java
@@ -22,7 +22,7 @@ import org.apache.lucene.codecs.PostingsFormat;
  * {@link org.apache.lucene.search.suggest.document.CompletionPostingsFormat} for {@code
  * org.apache.lucene.backward_codecs.lucene50.Lucene50PostingsFormat}. This format is only used for
  * backward-compatibility of the index format and cannot be used to write data, use {@link
- * Completion90PostingsFormat} on new indices.
+ * Completion99PostingsFormat} on new indices.
  *
  * @lucene.experimental
  */
diff --git a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion84PostingsFormat.java b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion84PostingsFormat.java
index 8551fc3a80a..76e29811834 100644
--- a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion84PostingsFormat.java
+++ b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion84PostingsFormat.java
@@ -22,7 +22,7 @@ import org.apache.lucene.codecs.PostingsFormat;
  * {@link org.apache.lucene.search.suggest.document.CompletionPostingsFormat} for {@code
  * org.apache.lucene.backward_codecs.lucene84.Lucene84PostingsFormat}. This format is only used for
  * backward-compatibility of the index format and cannot be used to write data, use {@link
- * Completion90PostingsFormat} on new indices.
+ * Completion99PostingsFormat} on new indices.
  *
  * @lucene.experimental
  */
diff --git a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java
index cf2a9103aa7..db45303bcd7 100644
--- a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java
+++ b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java
@@ -19,8 +19,10 @@ package org.apache.lucene.search.suggest.document;
 import org.apache.lucene.codecs.PostingsFormat;
 
 /**
- * {@link CompletionPostingsFormat} for {@link
- * org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat}
+ * {@link org.apache.lucene.search.suggest.document.CompletionPostingsFormat} for {@code
+ * org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat}. This format is only used for
+ * backward-compatibility of the index format and cannot be used to write data, use {@link
+ * Completion90PostingsFormat} on new indices.
  *
  * @lucene.experimental
  */
diff --git a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion99PostingsFormat.java
similarity index 74%
copy from lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java
copy to lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion99PostingsFormat.java
index cf2a9103aa7..4449d754e29 100644
--- a/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion90PostingsFormat.java
+++ b/lucene/suggest/src/java/org/apache/lucene/search/suggest/document/Completion99PostingsFormat.java
@@ -20,26 +20,26 @@ import org.apache.lucene.codecs.PostingsFormat;
 
 /**
  * {@link CompletionPostingsFormat} for {@link
- * org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat}
+ * org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat}
  *
  * @lucene.experimental
  */
-public class Completion90PostingsFormat extends CompletionPostingsFormat {
-  /** Creates a {@link Completion90PostingsFormat} that will load the completion FST on-heap. */
-  public Completion90PostingsFormat() {
+public class Completion99PostingsFormat extends CompletionPostingsFormat {
+  /** Creates a {@link Completion99PostingsFormat} that will load the completion FST on-heap. */
+  public Completion99PostingsFormat() {
     this(FSTLoadMode.ON_HEAP);
   }
 
   /**
-   * Creates a {@link Completion90PostingsFormat} that will use the provided <code>fstLoadMode
+   * Creates a {@link Completion99PostingsFormat} that will use the provided <code>fstLoadMode
    * </code> to determine if the completion FST should be loaded on or off heap.
    */
-  public Completion90PostingsFormat(FSTLoadMode fstLoadMode) {
-    super("Completion90", fstLoadMode);
+  public Completion99PostingsFormat(FSTLoadMode fstLoadMode) {
+    super("Completion99", fstLoadMode);
   }
 
   @Override
   protected PostingsFormat delegatePostingsFormat() {
-    return PostingsFormat.forName("Lucene90");
+    return PostingsFormat.forName("Lucene99");
   }
 }
diff --git a/lucene/suggest/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat b/lucene/suggest/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
index a4070471047..81d1ed9465d 100644
--- a/lucene/suggest/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
+++ b/lucene/suggest/src/resources/META-INF/services/org.apache.lucene.codecs.PostingsFormat
@@ -33,3 +33,4 @@
 org.apache.lucene.search.suggest.document.Completion50PostingsFormat
 org.apache.lucene.search.suggest.document.Completion84PostingsFormat
 org.apache.lucene.search.suggest.document.Completion90PostingsFormat
+org.apache.lucene.search.suggest.document.Completion99PostingsFormat
diff --git a/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java b/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java
index 682363f29cb..30201a8eac8 100644
--- a/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java
+++ b/lucene/suggest/src/test/org/apache/lucene/search/suggest/document/TestSuggestField.java
@@ -965,7 +965,7 @@ public class TestSuggestField extends LuceneTestCase {
         new FilterCodec(TestUtil.getDefaultCodec().getName(), TestUtil.getDefaultCodec()) {
           CompletionPostingsFormat.FSTLoadMode fstLoadMode =
               RandomPicks.randomFrom(random(), CompletionPostingsFormat.FSTLoadMode.values());
-          PostingsFormat postingsFormat = new Completion90PostingsFormat(fstLoadMode);
+          PostingsFormat postingsFormat = new Completion99PostingsFormat(fstLoadMode);
 
           @Override
           public PostingsFormat postingsFormat() {
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneFixedGap.java b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneFixedGap.java
index 3c21de0f128..0a0c8f673db 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneFixedGap.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneFixedGap.java
@@ -28,9 +28,9 @@ import org.apache.lucene.codecs.blockterms.FixedGapTermsIndexReader;
 import org.apache.lucene.codecs.blockterms.FixedGapTermsIndexWriter;
 import org.apache.lucene.codecs.blockterms.TermsIndexReaderBase;
 import org.apache.lucene.codecs.blockterms.TermsIndexWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat; // javadocs
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat; // javadocs
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 
@@ -38,7 +38,7 @@ import org.apache.lucene.index.SegmentWriteState;
 // any PostingsFormat and make it ord-able...
 
 /**
- * Customized version of {@link Lucene90PostingsFormat} that uses {@link FixedGapTermsIndexWriter}.
+ * Customized version of {@link Lucene99PostingsFormat} that uses {@link FixedGapTermsIndexWriter}.
  */
 public final class LuceneFixedGap extends PostingsFormat {
   final int termIndexInterval;
@@ -54,7 +54,7 @@ public final class LuceneFixedGap extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase docs = new Lucene90PostingsWriter(state);
+    PostingsWriterBase docs = new Lucene99PostingsWriter(state);
 
     // TODO: should we make the terms index more easily
     // pluggable?  Ie so that this codec would record which
@@ -91,7 +91,7 @@ public final class LuceneFixedGap extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postings = new Lucene90PostingsReader(state);
+    PostingsReaderBase postings = new Lucene99PostingsReader(state);
     TermsIndexReaderBase indexReader;
 
     boolean success = false;
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapDocFreqInterval.java b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapDocFreqInterval.java
index 6a38882c153..a864263b7c3 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapDocFreqInterval.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapDocFreqInterval.java
@@ -29,9 +29,9 @@ import org.apache.lucene.codecs.blockterms.TermsIndexReaderBase;
 import org.apache.lucene.codecs.blockterms.TermsIndexWriterBase;
 import org.apache.lucene.codecs.blockterms.VariableGapTermsIndexReader;
 import org.apache.lucene.codecs.blockterms.VariableGapTermsIndexWriter;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat; // javadocs
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat; // javadocs
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 
@@ -39,7 +39,7 @@ import org.apache.lucene.index.SegmentWriteState;
 // any PostingsFormat and make it ord-able...
 
 /**
- * Customized version of {@link Lucene90PostingsFormat} that uses {@link
+ * Customized version of {@link Lucene99PostingsFormat} that uses {@link
  * VariableGapTermsIndexWriter} with a fixed interval, but forcing high docfreq terms to be indexed
  * terms.
  */
@@ -59,7 +59,7 @@ public final class LuceneVarGapDocFreqInterval extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase docs = new Lucene90PostingsWriter(state);
+    PostingsWriterBase docs = new Lucene99PostingsWriter(state);
 
     // TODO: should we make the terms index more easily
     // pluggable?  Ie so that this codec would record which
@@ -100,7 +100,7 @@ public final class LuceneVarGapDocFreqInterval extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postings = new Lucene90PostingsReader(state);
+    PostingsReaderBase postings = new Lucene99PostingsReader(state);
     TermsIndexReaderBase indexReader;
 
     boolean success = false;
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapFixedInterval.java b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapFixedInterval.java
index 838d2968c7f..667acf0ceb3 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapFixedInterval.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/blockterms/LuceneVarGapFixedInterval.java
@@ -29,9 +29,9 @@ import org.apache.lucene.codecs.blockterms.TermsIndexReaderBase;
 import org.apache.lucene.codecs.blockterms.TermsIndexWriterBase;
 import org.apache.lucene.codecs.blockterms.VariableGapTermsIndexReader;
 import org.apache.lucene.codecs.blockterms.VariableGapTermsIndexWriter;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat; // javadocs
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat; // javadocs
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 
@@ -39,7 +39,7 @@ import org.apache.lucene.index.SegmentWriteState;
 // any PostingsFormat and make it ord-able...
 
 /**
- * Customized version of {@link Lucene90PostingsFormat} that uses {@link
+ * Customized version of {@link Lucene99PostingsFormat} that uses {@link
  * VariableGapTermsIndexWriter} with a fixed interval.
  */
 public final class LuceneVarGapFixedInterval extends PostingsFormat {
@@ -56,7 +56,7 @@ public final class LuceneVarGapFixedInterval extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
-    PostingsWriterBase docs = new Lucene90PostingsWriter(state);
+    PostingsWriterBase docs = new Lucene99PostingsWriter(state);
 
     // TODO: should we make the terms index more easily
     // pluggable?  Ie so that this codec would record which
@@ -95,7 +95,7 @@ public final class LuceneVarGapFixedInterval extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
-    PostingsReaderBase postings = new Lucene90PostingsReader(state);
+    PostingsReaderBase postings = new Lucene99PostingsReader(state);
     TermsIndexReaderBase indexReader;
 
     boolean success = false;
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/mockrandom/MockRandomPostingsFormat.java b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/mockrandom/MockRandomPostingsFormat.java
index 814075d0efc..dd8d6fedc77 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/mockrandom/MockRandomPostingsFormat.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/mockrandom/MockRandomPostingsFormat.java
@@ -35,10 +35,10 @@ import org.apache.lucene.codecs.blockterms.VariableGapTermsIndexReader;
 import org.apache.lucene.codecs.blockterms.VariableGapTermsIndexWriter;
 import org.apache.lucene.codecs.blocktreeords.OrdsBlockTreeTermsReader;
 import org.apache.lucene.codecs.blocktreeords.OrdsBlockTreeTermsWriter;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
 import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsReader;
 import org.apache.lucene.codecs.lucene90.blocktree.Lucene90BlockTreeTermsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.codecs.memory.FSTTermsReader;
 import org.apache.lucene.codecs.memory.FSTTermsWriter;
 import org.apache.lucene.index.FieldInfo;
@@ -121,7 +121,7 @@ public final class MockRandomPostingsFormat extends PostingsFormat {
 
     random.nextInt(); // consume a random for buffersize
 
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(state);
+    PostingsWriterBase postingsWriter = new Lucene99PostingsWriter(state);
 
     final FieldsConsumer fields;
     final int t1 = random.nextInt(4);
@@ -289,7 +289,7 @@ public final class MockRandomPostingsFormat extends PostingsFormat {
       System.out.println("MockRandomCodec: readBufferSize=" + readBufferSize);
     }
 
-    PostingsReaderBase postingsReader = new Lucene90PostingsReader(state);
+    PostingsReaderBase postingsReader = new Lucene99PostingsReader(state);
 
     final FieldsProducer fields;
     final int t1 = random.nextInt(4);
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/uniformsplit/UniformSplitRot13PostingsFormat.java b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/uniformsplit/UniformSplitRot13PostingsFormat.java
index 7291c7e54da..0c469b392a2 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/uniformsplit/UniformSplitRot13PostingsFormat.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/codecs/uniformsplit/UniformSplitRot13PostingsFormat.java
@@ -23,8 +23,8 @@ import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.PostingsReaderBase;
 import org.apache.lucene.codecs.PostingsWriterBase;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsReader;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsWriter;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsReader;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsWriter;
 import org.apache.lucene.codecs.uniformsplit.BlockDecoder;
 import org.apache.lucene.codecs.uniformsplit.BlockEncoder;
 import org.apache.lucene.codecs.uniformsplit.IndexDictionary;
@@ -67,7 +67,7 @@ public class UniformSplitRot13PostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsConsumer fieldsConsumer(SegmentWriteState segmentWriteState) throws IOException {
-    PostingsWriterBase postingsWriter = new Lucene90PostingsWriter(segmentWriteState);
+    PostingsWriterBase postingsWriter = new Lucene99PostingsWriter(segmentWriteState);
     boolean success = false;
     try {
       FieldsConsumer fieldsConsumer = createFieldsConsumer(segmentWriteState, postingsWriter);
@@ -145,7 +145,7 @@ public class UniformSplitRot13PostingsFormat extends PostingsFormat {
 
   @Override
   public FieldsProducer fieldsProducer(SegmentReadState segmentReadState) throws IOException {
-    PostingsReaderBase postingsReader = new Lucene90PostingsReader(segmentReadState);
+    PostingsReaderBase postingsReader = new Lucene99PostingsReader(segmentReadState);
     boolean success = false;
     try {
       FieldsProducer fieldsProducer = createFieldsProducer(segmentReadState, postingsReader);
diff --git a/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java b/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java
index b1c5e8d9b93..6d1d8573e5e 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/tests/util/TestUtil.java
@@ -54,9 +54,9 @@ import org.apache.lucene.codecs.KnnVectorsFormat;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.blocktreeords.BlockTreeOrdsPostingsFormat;
 import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
-import org.apache.lucene.codecs.lucene90.Lucene90PostingsFormat;
 import org.apache.lucene.codecs.lucene99.Lucene99Codec;
 import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
+import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
 import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
 import org.apache.lucene.codecs.perfield.PerFieldPostingsFormat;
 import org.apache.lucene.document.BinaryDocValuesField;
@@ -1244,7 +1244,7 @@ public final class TestUtil {
    * Lucene.
    */
   public static PostingsFormat getDefaultPostingsFormat() {
-    return new Lucene90PostingsFormat();
+    return new Lucene99PostingsFormat();
   }
 
   /**
@@ -1255,7 +1255,7 @@ public final class TestUtil {
    */
   public static PostingsFormat getDefaultPostingsFormat(
       int minItemsPerBlock, int maxItemsPerBlock) {
-    return new Lucene90PostingsFormat(minItemsPerBlock, maxItemsPerBlock);
+    return new Lucene99PostingsFormat(minItemsPerBlock, maxItemsPerBlock);
   }
 
   /** Returns a random postings format that supports term ordinals */