diff --git a/Sources/PIRProcessDatabase/PIRProcessDatabase.docc/PIRProcessDatabase.md b/Sources/PIRProcessDatabase/PIRProcessDatabase.docc/PIRProcessDatabase.md
index af72d7b9..c132e8e7 100644
--- a/Sources/PIRProcessDatabase/PIRProcessDatabase.docc/PIRProcessDatabase.md
+++ b/Sources/PIRProcessDatabase/PIRProcessDatabase.docc/PIRProcessDatabase.md
@@ -130,7 +130,7 @@ Three arguments enable this best-effort approach towards symmetric PIR:
 * `maxSerializedBucketSize`. We can set size equal to the number of bytes in a plaintexts. This roughly says that each
   bucket can hold as many bytes as a single plaintext.
 * `useMaxSerializedBucketSize`. When enabled, the IndexPIR layer will assume that each entry is as large as
-  `maxSerializedBucketSize`. This avoids packing multiple hash buckets into a single plaintexts.
+  `maxSerializedBucketSize`. This avoids packing multiple hash buckets into a single plaintext.
 
 Together these options can be used to control the number of entries in a response.
 
diff --git a/Sources/PrivateInformationRetrieval/KeywordPirProtocol.swift b/Sources/PrivateInformationRetrieval/KeywordPirProtocol.swift
index 286891ad..f6837f12 100644
--- a/Sources/PrivateInformationRetrieval/KeywordPirProtocol.swift
+++ b/Sources/PrivateInformationRetrieval/KeywordPirProtocol.swift
@@ -162,9 +162,7 @@ public final class KeywordPirServer<PirServer: IndexPirServer>: KeywordPirProtoc
         throws -> ProcessedDatabaseWithParameters<Scheme>
     {
         func onCuckooEvent(event: CuckooTable.Event) throws {
-            try onEvent(
-                ProcessKeywordDatabase.ProcessShardEvent
-                    .cuckooTableEvent(event))
+            try onEvent(ProcessKeywordDatabase.ProcessShardEvent.cuckooTableEvent(event))
         }
 
         let cuckooTableConfig = config.cuckooTableConfig
diff --git a/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_api.pb.swift b/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_api.pb.swift
index bef234b7..23217f3f 100644
--- a/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_api.pb.swift
+++ b/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_api.pb.swift
@@ -36,7 +36,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
 }
 
 /// Request for server side configurations.
-public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest: Sendable {
+public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest: @unchecked Sendable {
   // SwiftProtobuf.Message conformance is added in an extension below. See the
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
   // methods supported on all messages.
@@ -45,6 +45,9 @@ public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest: Sendabl
   /// When set to empty array, all configs will be returned.
   public var usecases: [String] = []
 
+  /// For each usecase, the existing config id, if one exists.
+  public var existingConfigIds: [Data] = []
+
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   public init() {}
@@ -71,6 +74,9 @@ public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_Config: @unchecked Sen
   /// Unique identifier for the configuration.
   public var configID: Data = Data()
 
+  /// Indicator that the config is the same config as in the ConfigRequest. If set, all other fields can be unset.
+  public var reuseExistingConfig: Bool = false
+
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   /// Configuration.
@@ -199,6 +205,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest: SwiftProtob
   public static let protoMessageName: String = _protobuf_package + ".ConfigRequest"
   public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
     1: .same(proto: "usecases"),
+    2: .standard(proto: "existing_config_ids"),
   ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@@ -208,6 +215,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest: SwiftProtob
       // enabled. https://github.com/apple/swift-protobuf/issues/1034
       switch fieldNumber {
       case 1: try { try decoder.decodeRepeatedStringField(value: &self.usecases) }()
+      case 2: try { try decoder.decodeRepeatedBytesField(value: &self.existingConfigIds) }()
       default: break
       }
     }
@@ -217,11 +225,15 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest: SwiftProtob
     if !self.usecases.isEmpty {
       try visitor.visitRepeatedStringField(value: self.usecases, fieldNumber: 1)
     }
+    if !self.existingConfigIds.isEmpty {
+      try visitor.visitRepeatedBytesField(value: self.existingConfigIds, fieldNumber: 2)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest, rhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_ConfigRequest) -> Bool {
     if lhs.usecases != rhs.usecases {return false}
+    if lhs.existingConfigIds != rhs.existingConfigIds {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
@@ -232,6 +244,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_Config: SwiftProtobuf.Mess
   public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
     1: .standard(proto: "pir_config"),
     3: .standard(proto: "config_id"),
+    4: .standard(proto: "reuse_existing_config"),
   ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@@ -254,6 +267,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_Config: SwiftProtobuf.Mess
         }
       }()
       case 3: try { try decoder.decodeSingularBytesField(value: &self.configID) }()
+      case 4: try { try decoder.decodeSingularBoolField(value: &self.reuseExistingConfig) }()
       default: break
       }
     }
@@ -270,12 +284,16 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_Config: SwiftProtobuf.Mess
     if !self.configID.isEmpty {
       try visitor.visitSingularBytesField(value: self.configID, fieldNumber: 3)
     }
+    if self.reuseExistingConfig != false {
+      try visitor.visitSingularBoolField(value: self.reuseExistingConfig, fieldNumber: 4)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_Config, rhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_Config) -> Bool {
     if lhs.config != rhs.config {return false}
     if lhs.configID != rhs.configID {return false}
+    if lhs.reuseExistingConfig != rhs.reuseExistingConfig {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
diff --git a/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_pir.pb.swift b/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_pir.pb.swift
index 4be5c1f8..140c8a1b 100644
--- a/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_pir.pb.swift
+++ b/Sources/PrivateInformationRetrievalProtobuf/generated/apple_swift_homomorphic_encryption_api_pir_v1_pir.pb.swift
@@ -99,42 +99,119 @@ public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig: @unchecked
 
   /// Encryption parameters.
   public var encryptionParameters: HomomorphicEncryptionProtobuf.Apple_SwiftHomomorphicEncryption_V1_EncryptionParameters {
-    get {return _encryptionParameters ?? HomomorphicEncryptionProtobuf.Apple_SwiftHomomorphicEncryption_V1_EncryptionParameters()}
-    set {_encryptionParameters = newValue}
+    get {return _storage._encryptionParameters ?? HomomorphicEncryptionProtobuf.Apple_SwiftHomomorphicEncryption_V1_EncryptionParameters()}
+    set {_uniqueStorage()._encryptionParameters = newValue}
   }
   /// Returns true if `encryptionParameters` has been explicitly set.
-  public var hasEncryptionParameters: Bool {return self._encryptionParameters != nil}
+  public var hasEncryptionParameters: Bool {return _storage._encryptionParameters != nil}
   /// Clears the value of `encryptionParameters`. Subsequent reads from it will return its default value.
-  public mutating func clearEncryptionParameters() {self._encryptionParameters = nil}
+  public mutating func clearEncryptionParameters() {_uniqueStorage()._encryptionParameters = nil}
 
-  /// Configuration for each shard.
-  public var shardConfigs: [Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfig] = []
+  /// Configuration for each shard; can be overridden by `pir_shard_configs` (field 10).
+  public var shardConfigs: [Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfig] {
+    get {return _storage._shardConfigs}
+    set {_uniqueStorage()._shardConfigs = newValue}
+  }
 
   /// Parameters specific to KeywordPIR.
   public var keywordPirParams: Apple_SwiftHomomorphicEncryption_Pir_V1_KeywordPirParameters {
-    get {return _keywordPirParams ?? Apple_SwiftHomomorphicEncryption_Pir_V1_KeywordPirParameters()}
-    set {_keywordPirParams = newValue}
+    get {return _storage._keywordPirParams ?? Apple_SwiftHomomorphicEncryption_Pir_V1_KeywordPirParameters()}
+    set {_uniqueStorage()._keywordPirParams = newValue}
   }
   /// Returns true if `keywordPirParams` has been explicitly set.
-  public var hasKeywordPirParams: Bool {return self._keywordPirParams != nil}
+  public var hasKeywordPirParams: Bool {return _storage._keywordPirParams != nil}
   /// Clears the value of `keywordPirParams`. Subsequent reads from it will return its default value.
-  public mutating func clearKeywordPirParams() {self._keywordPirParams = nil}
+  public mutating func clearKeywordPirParams() {_uniqueStorage()._keywordPirParams = nil}
 
   /// Server-side PIR algorithm.
-  public var algorithm: Apple_SwiftHomomorphicEncryption_Pir_V1_PirAlgorithm = .aclsPir
+  public var algorithm: Apple_SwiftHomomorphicEncryption_Pir_V1_PirAlgorithm {
+    get {return _storage._algorithm}
+    set {_uniqueStorage()._algorithm = newValue}
+  }
 
   /// Maximum number of queries allowed in a single request.
-  public var batchSize: UInt64 = 0
+  public var batchSize: UInt64 {
+    get {return _storage._batchSize}
+    set {_uniqueStorage()._batchSize = newValue}
+  }
 
   /// Hash of EvaluationKeyConfig.
-  public var evaluationKeyConfigHash: Data = Data()
+  public var evaluationKeyConfigHash: Data {
+    get {return _storage._evaluationKeyConfigHash}
+    set {_uniqueStorage()._evaluationKeyConfigHash = newValue}
+  }
+
+  /// Configuration for each shard; overrides `shard_configs` (field 2).
+  public var pirShardConfigs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs {
+    get {return _storage._pirShardConfigs ?? Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs()}
+    set {_uniqueStorage()._pirShardConfigs = newValue}
+  }
+  /// Returns true if `pirShardConfigs` has been explicitly set.
+  public var hasPirShardConfigs: Bool {return _storage._pirShardConfigs != nil}
+  /// Clears the value of `pirShardConfigs`. Subsequent reads from it will return its default value.
+  public mutating func clearPirShardConfigs() {_uniqueStorage()._pirShardConfigs = nil}
+
+  public var unknownFields = SwiftProtobuf.UnknownStorage()
+
+  public init() {}
+
+  fileprivate var _storage = _StorageClass.defaultInstance
+}
+
+/// Configuration for PIR shards.
+public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs: Sendable {
+  // SwiftProtobuf.Message conformance is added in an extension below. See the
+  // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
+  // methods supported on all messages.
+
+  /// Different shard configuration formats.
+  public var shardConfigs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs.OneOf_ShardConfigs? = nil
+
+  /// Repeated shard configuration.
+  public var repeatedShardConfig: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig {
+    get {
+      if case .repeatedShardConfig(let v)? = shardConfigs {return v}
+      return Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig()
+    }
+    set {shardConfigs = .repeatedShardConfig(newValue)}
+  }
+
+  public var unknownFields = SwiftProtobuf.UnknownStorage()
+
+  /// Different shard configuration formats.
+  public enum OneOf_ShardConfigs: Equatable, Sendable {
+    /// Repeated shard configuration.
+    case repeatedShardConfig(Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig)
+
+  }
+
+  public init() {}
+}
+
+/// Every shard configuration is the same.
+public struct Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig: Sendable {
+  // SwiftProtobuf.Message conformance is added in an extension below. See the
+  // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
+  // methods supported on all messages.
+
+  /// Shard configuration for all the shards.
+  public var shardConfig: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfig {
+    get {return _shardConfig ?? Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfig()}
+    set {_shardConfig = newValue}
+  }
+  /// Returns true if `shardConfig` has been explicitly set.
+  public var hasShardConfig: Bool {return self._shardConfig != nil}
+  /// Clears the value of `shardConfig`. Subsequent reads from it will return its default value.
+  public mutating func clearShardConfig() {self._shardConfig = nil}
+
+  /// Number of shards.
+  public var shardCount: UInt32 = 0
 
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   public init() {}
 
-  fileprivate var _encryptionParameters: HomomorphicEncryptionProtobuf.Apple_SwiftHomomorphicEncryption_V1_EncryptionParameters? = nil
-  fileprivate var _keywordPirParams: Apple_SwiftHomomorphicEncryption_Pir_V1_KeywordPirParameters? = nil
+  fileprivate var _shardConfig: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfig? = nil
 }
 
 /// PIR Request.
@@ -292,6 +369,125 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig: SwiftProtobuf.M
     4: .same(proto: "algorithm"),
     5: .standard(proto: "batch_size"),
     6: .standard(proto: "evaluation_key_config_hash"),
+    10: .standard(proto: "pir_shard_configs"),
+  ]
+
+  fileprivate class _StorageClass {
+    var _encryptionParameters: HomomorphicEncryptionProtobuf.Apple_SwiftHomomorphicEncryption_V1_EncryptionParameters? = nil
+    var _shardConfigs: [Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfig] = []
+    var _keywordPirParams: Apple_SwiftHomomorphicEncryption_Pir_V1_KeywordPirParameters? = nil
+    var _algorithm: Apple_SwiftHomomorphicEncryption_Pir_V1_PirAlgorithm = .aclsPir
+    var _batchSize: UInt64 = 0
+    var _evaluationKeyConfigHash: Data = Data()
+    var _pirShardConfigs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs? = nil
+
+    #if swift(>=5.10)
+      // This property is used as the initial default value for new instances of the type.
+      // The type itself is protecting the reference to its storage via CoW semantics.
+      // This will force a copy to be made of this reference when the first mutation occurs;
+      // hence, it is safe to mark this as `nonisolated(unsafe)`.
+      static nonisolated(unsafe) let defaultInstance = _StorageClass()
+    #else
+      static let defaultInstance = _StorageClass()
+    #endif
+
+    private init() {}
+
+    init(copying source: _StorageClass) {
+      _encryptionParameters = source._encryptionParameters
+      _shardConfigs = source._shardConfigs
+      _keywordPirParams = source._keywordPirParams
+      _algorithm = source._algorithm
+      _batchSize = source._batchSize
+      _evaluationKeyConfigHash = source._evaluationKeyConfigHash
+      _pirShardConfigs = source._pirShardConfigs
+    }
+  }
+
+  fileprivate mutating func _uniqueStorage() -> _StorageClass {
+    if !isKnownUniquelyReferenced(&_storage) {
+      _storage = _StorageClass(copying: _storage)
+    }
+    return _storage
+  }
+
+  public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
+    _ = _uniqueStorage()
+    try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
+      while let fieldNumber = try decoder.nextFieldNumber() {
+        // The use of inline closures is to circumvent an issue where the compiler
+        // allocates stack space for every case branch when no optimizations are
+        // enabled. https://github.com/apple/swift-protobuf/issues/1034
+        switch fieldNumber {
+        case 1: try { try decoder.decodeSingularMessageField(value: &_storage._encryptionParameters) }()
+        case 2: try { try decoder.decodeRepeatedMessageField(value: &_storage._shardConfigs) }()
+        case 3: try { try decoder.decodeSingularMessageField(value: &_storage._keywordPirParams) }()
+        case 4: try { try decoder.decodeSingularEnumField(value: &_storage._algorithm) }()
+        case 5: try { try decoder.decodeSingularUInt64Field(value: &_storage._batchSize) }()
+        case 6: try { try decoder.decodeSingularBytesField(value: &_storage._evaluationKeyConfigHash) }()
+        case 10: try { try decoder.decodeSingularMessageField(value: &_storage._pirShardConfigs) }()
+        default: break
+        }
+      }
+    }
+  }
+
+  public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
+    try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
+      // The use of inline closures is to circumvent an issue where the compiler
+      // allocates stack space for every if/case branch local when no optimizations
+      // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
+      // https://github.com/apple/swift-protobuf/issues/1182
+      try { if let v = _storage._encryptionParameters {
+        try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
+      } }()
+      if !_storage._shardConfigs.isEmpty {
+        try visitor.visitRepeatedMessageField(value: _storage._shardConfigs, fieldNumber: 2)
+      }
+      try { if let v = _storage._keywordPirParams {
+        try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
+      } }()
+      if _storage._algorithm != .aclsPir {
+        try visitor.visitSingularEnumField(value: _storage._algorithm, fieldNumber: 4)
+      }
+      if _storage._batchSize != 0 {
+        try visitor.visitSingularUInt64Field(value: _storage._batchSize, fieldNumber: 5)
+      }
+      if !_storage._evaluationKeyConfigHash.isEmpty {
+        try visitor.visitSingularBytesField(value: _storage._evaluationKeyConfigHash, fieldNumber: 6)
+      }
+      try { if let v = _storage._pirShardConfigs {
+        try visitor.visitSingularMessageField(value: v, fieldNumber: 10)
+      } }()
+    }
+    try unknownFields.traverse(visitor: &visitor)
+  }
+
+  public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig, rhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig) -> Bool {
+    if lhs._storage !== rhs._storage {
+      let storagesAreEqual: Bool = withExtendedLifetime((lhs._storage, rhs._storage)) { (_args: (_StorageClass, _StorageClass)) in
+        let _storage = _args.0
+        let rhs_storage = _args.1
+        if _storage._encryptionParameters != rhs_storage._encryptionParameters {return false}
+        if _storage._shardConfigs != rhs_storage._shardConfigs {return false}
+        if _storage._keywordPirParams != rhs_storage._keywordPirParams {return false}
+        if _storage._algorithm != rhs_storage._algorithm {return false}
+        if _storage._batchSize != rhs_storage._batchSize {return false}
+        if _storage._evaluationKeyConfigHash != rhs_storage._evaluationKeyConfigHash {return false}
+        if _storage._pirShardConfigs != rhs_storage._pirShardConfigs {return false}
+        return true
+      }
+      if !storagesAreEqual {return false}
+    }
+    if lhs.unknownFields != rhs.unknownFields {return false}
+    return true
+  }
+}
+
+extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+  public static let protoMessageName: String = _protobuf_package + ".PIRShardConfigs"
+  public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
+    1: .standard(proto: "repeated_shard_config"),
   ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@@ -300,12 +496,19 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig: SwiftProtobuf.M
       // allocates stack space for every case branch when no optimizations are
       // enabled. https://github.com/apple/swift-protobuf/issues/1034
       switch fieldNumber {
-      case 1: try { try decoder.decodeSingularMessageField(value: &self._encryptionParameters) }()
-      case 2: try { try decoder.decodeRepeatedMessageField(value: &self.shardConfigs) }()
-      case 3: try { try decoder.decodeSingularMessageField(value: &self._keywordPirParams) }()
-      case 4: try { try decoder.decodeSingularEnumField(value: &self.algorithm) }()
-      case 5: try { try decoder.decodeSingularUInt64Field(value: &self.batchSize) }()
-      case 6: try { try decoder.decodeSingularBytesField(value: &self.evaluationKeyConfigHash) }()
+      case 1: try {
+        var v: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig?
+        var hadOneofValue = false
+        if let current = self.shardConfigs {
+          hadOneofValue = true
+          if case .repeatedShardConfig(let m) = current {v = m}
+        }
+        try decoder.decodeSingularMessageField(value: &v)
+        if let v = v {
+          if hadOneofValue {try decoder.handleConflictingOneOf()}
+          self.shardConfigs = .repeatedShardConfig(v)
+        }
+      }()
       default: break
       }
     }
@@ -316,34 +519,56 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig: SwiftProtobuf.M
     // allocates stack space for every if/case branch local when no optimizations
     // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
     // https://github.com/apple/swift-protobuf/issues/1182
-    try { if let v = self._encryptionParameters {
+    try { if case .repeatedShardConfig(let v)? = self.shardConfigs {
       try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
     } }()
-    if !self.shardConfigs.isEmpty {
-      try visitor.visitRepeatedMessageField(value: self.shardConfigs, fieldNumber: 2)
+    try unknownFields.traverse(visitor: &visitor)
+  }
+
+  public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs, rhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRShardConfigs) -> Bool {
+    if lhs.shardConfigs != rhs.shardConfigs {return false}
+    if lhs.unknownFields != rhs.unknownFields {return false}
+    return true
+  }
+}
+
+extension Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+  public static let protoMessageName: String = _protobuf_package + ".PIRFixedShardConfig"
+  public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
+    1: .standard(proto: "shard_config"),
+    2: .standard(proto: "shard_count"),
+  ]
+
+  public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
+    while let fieldNumber = try decoder.nextFieldNumber() {
+      // The use of inline closures is to circumvent an issue where the compiler
+      // allocates stack space for every case branch when no optimizations are
+      // enabled. https://github.com/apple/swift-protobuf/issues/1034
+      switch fieldNumber {
+      case 1: try { try decoder.decodeSingularMessageField(value: &self._shardConfig) }()
+      case 2: try { try decoder.decodeSingularUInt32Field(value: &self.shardCount) }()
+      default: break
+      }
     }
-    try { if let v = self._keywordPirParams {
-      try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
+  }
+
+  public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
+    // The use of inline closures is to circumvent an issue where the compiler
+    // allocates stack space for every if/case branch local when no optimizations
+    // are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
+    // https://github.com/apple/swift-protobuf/issues/1182
+    try { if let v = self._shardConfig {
+      try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
     } }()
-    if self.algorithm != .aclsPir {
-      try visitor.visitSingularEnumField(value: self.algorithm, fieldNumber: 4)
-    }
-    if self.batchSize != 0 {
-      try visitor.visitSingularUInt64Field(value: self.batchSize, fieldNumber: 5)
-    }
-    if !self.evaluationKeyConfigHash.isEmpty {
-      try visitor.visitSingularBytesField(value: self.evaluationKeyConfigHash, fieldNumber: 6)
+    if self.shardCount != 0 {
+      try visitor.visitSingularUInt32Field(value: self.shardCount, fieldNumber: 2)
     }
     try unknownFields.traverse(visitor: &visitor)
   }
 
-  public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig, rhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRConfig) -> Bool {
-    if lhs._encryptionParameters != rhs._encryptionParameters {return false}
-    if lhs.shardConfigs != rhs.shardConfigs {return false}
-    if lhs._keywordPirParams != rhs._keywordPirParams {return false}
-    if lhs.algorithm != rhs.algorithm {return false}
-    if lhs.batchSize != rhs.batchSize {return false}
-    if lhs.evaluationKeyConfigHash != rhs.evaluationKeyConfigHash {return false}
+  public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig, rhs: Apple_SwiftHomomorphicEncryption_Api_Pir_V1_PIRFixedShardConfig) -> Bool {
+    if lhs._shardConfig != rhs._shardConfig {return false}
+    if lhs.shardCount != rhs.shardCount {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
diff --git a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_api.pb.swift b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_api.pb.swift
index 4f7dea8d..0602f910 100644
--- a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_api.pb.swift
+++ b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_api.pb.swift
@@ -36,7 +36,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
 }
 
 /// Request for server side configurations.
-public struct Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest: Sendable {
+public struct Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest: @unchecked Sendable {
   // SwiftProtobuf.Message conformance is added in an extension below. See the
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
   // methods supported on all messages.
@@ -45,6 +45,9 @@ public struct Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest: Sendab
   /// When set to empty array, all configs will be returned.
   public var usecases: [String] = []
 
+  /// For each usecase, the existing config id, if one exists.
+  public var existingConfigIds: [Data] = []
+
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   public init() {}
@@ -71,6 +74,9 @@ public struct Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_Config: @unchecked Se
   /// Unique identifier for the configuration.
   public var configID: Data = Data()
 
+  /// Indicator that the config is the same config as in the ConfigRequest. If set, all other fields can be unset.
+  public var reuseExistingConfig: Bool = false
+
   public var unknownFields = SwiftProtobuf.UnknownStorage()
 
   /// Configuration.
@@ -199,6 +205,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest: SwiftProto
   public static let protoMessageName: String = _protobuf_package + ".ConfigRequest"
   public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
     1: .same(proto: "usecases"),
+    2: .standard(proto: "existing_config_ids"),
   ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@@ -208,6 +215,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest: SwiftProto
       // enabled. https://github.com/apple/swift-protobuf/issues/1034
       switch fieldNumber {
       case 1: try { try decoder.decodeRepeatedStringField(value: &self.usecases) }()
+      case 2: try { try decoder.decodeRepeatedBytesField(value: &self.existingConfigIds) }()
       default: break
       }
     }
@@ -217,11 +225,15 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest: SwiftProto
     if !self.usecases.isEmpty {
       try visitor.visitRepeatedStringField(value: self.usecases, fieldNumber: 1)
     }
+    if !self.existingConfigIds.isEmpty {
+      try visitor.visitRepeatedBytesField(value: self.existingConfigIds, fieldNumber: 2)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest, rhs: Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_ConfigRequest) -> Bool {
     if lhs.usecases != rhs.usecases {return false}
+    if lhs.existingConfigIds != rhs.existingConfigIds {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
@@ -232,6 +244,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_Config: SwiftProtobuf.Mes
   public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
     2: .standard(proto: "pnns_config"),
     3: .standard(proto: "config_id"),
+    4: .standard(proto: "reuse_existing_config"),
   ]
 
   public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@@ -254,6 +267,7 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_Config: SwiftProtobuf.Mes
         }
       }()
       case 3: try { try decoder.decodeSingularBytesField(value: &self.configID) }()
+      case 4: try { try decoder.decodeSingularBoolField(value: &self.reuseExistingConfig) }()
       default: break
       }
     }
@@ -270,12 +284,16 @@ extension Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_Config: SwiftProtobuf.Mes
     if !self.configID.isEmpty {
       try visitor.visitSingularBytesField(value: self.configID, fieldNumber: 3)
     }
+    if self.reuseExistingConfig != false {
+      try visitor.visitSingularBoolField(value: self.reuseExistingConfig, fieldNumber: 4)
+    }
     try unknownFields.traverse(visitor: &visitor)
   }
 
   public static func ==(lhs: Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_Config, rhs: Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_Config) -> Bool {
     if lhs.config != rhs.config {return false}
     if lhs.configID != rhs.configID {return false}
+    if lhs.reuseExistingConfig != rhs.reuseExistingConfig {return false}
     if lhs.unknownFields != rhs.unknownFields {return false}
     return true
   }
diff --git a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_pnns.pb.swift b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_pnns.pb.swift
index 3de47f37..3935a71f 100644
--- a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_pnns.pb.swift
+++ b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_api_pnns_v1_pnns.pb.swift
@@ -69,7 +69,7 @@ public struct Apple_SwiftHomomorphicEncryption_Api_Pnns_V1_PNNSConfig: @unchecke
   /// Number of entries in each vector.
   public var vectorDimension: UInt32 = 0
 
-  /// Metric for similarity computation.
+  /// Metric for computing distances.
   public var distanceMetric: Apple_SwiftHomomorphicEncryption_Pnns_V1_DistanceMetric = .cosineSimilarity
 
   /// hash of EvaluationKeyConfig.
diff --git a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_client_config.pb.swift b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_client_config.pb.swift
index ab4e7ee3..6f993633 100644
--- a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_client_config.pb.swift
+++ b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_client_config.pb.swift
@@ -68,7 +68,7 @@ public struct Apple_SwiftHomomorphicEncryption_Pnns_V1_ClientConfig: Sendable {
   /// Number of entries in each vector.
   public var vectorDimension: UInt32 = 0
 
-  /// Galois elements required for nearest neighbors computation.
+  /// Galois elements required for nearest neighbor search.
   public var galoisElements: [UInt32] = []
 
   /// Metric for distances between vectors.
diff --git a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_database.pb.swift b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_database.pb.swift
index 2cea7596..e6d43458 100644
--- a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_database.pb.swift
+++ b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_database.pb.swift
@@ -35,7 +35,7 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
   typealias Version = _2
 }
 
-/// Row in a private nearest neighbors search database.
+/// Row in a private nearest neighbor search database.
 public struct Apple_SwiftHomomorphicEncryption_Pnns_V1_DatabaseRow: @unchecked Sendable {
   // SwiftProtobuf.Message conformance is added in an extension below. See the
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
@@ -47,7 +47,7 @@ public struct Apple_SwiftHomomorphicEncryption_Pnns_V1_DatabaseRow: @unchecked S
   /// Metadata associated with the entry.
   public var entryMetadata: Data = Data()
 
-  /// Vector for use in nearest neighbors computation.
+  /// Vector for use in nearest neighbor search.
   public var vector: [Float] = []
 
   public var unknownFields = SwiftProtobuf.UnknownStorage()
@@ -55,7 +55,7 @@ public struct Apple_SwiftHomomorphicEncryption_Pnns_V1_DatabaseRow: @unchecked S
   public init() {}
 }
 
-/// A private nearest neighbors search database.
+/// A private nearest neighbor search database.
 public struct Apple_SwiftHomomorphicEncryption_Pnns_V1_Database: Sendable {
   // SwiftProtobuf.Message conformance is added in an extension below. See the
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
diff --git a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_processed_database.pb.swift b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_processed_database.pb.swift
index 689321dd..51bf7d38 100644
--- a/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_processed_database.pb.swift
+++ b/Sources/PrivateNearestNeighborSearchProtobuf/generated/apple_swift_homomorphic_encryption_pnns_v1_pnns_processed_database.pb.swift
@@ -35,13 +35,13 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
   typealias Version = _2
 }
 
-/// Serialized pre-processed nearest neighbors database.
+/// Serialized pre-processed nearest neighbor database.
 public struct Apple_SwiftHomomorphicEncryption_Pnns_V1_SerializedProcessedDatabase: @unchecked Sendable {
   // SwiftProtobuf.Message conformance is added in an extension below. See the
   // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
   // methods supported on all messages.
 
-  /// Pre-computed values for the nearest neighbors computation, one per plaintext CRT modulus.
+  /// Pre-computed values for the nearest neighbor search, one per plaintext CRT modulus.
   public var plaintextMatrices: [Apple_SwiftHomomorphicEncryption_Pnns_V1_SerializedPlaintextMatrix] = []
 
   /// Unique identifier for each entry in the database.
diff --git a/swift-homomorphic-encryption-protobuf b/swift-homomorphic-encryption-protobuf
index e2fcb506..122bd5f9 160000
--- a/swift-homomorphic-encryption-protobuf
+++ b/swift-homomorphic-encryption-protobuf
@@ -1 +1 @@
-Subproject commit e2fcb506442719d00b11914ebe6e85779c5b5b4c
+Subproject commit 122bd5f9b9f0d23ca04a8a33d6faf6f90493dd01