diff --git a/firestore/CMakeLists.txt b/firestore/CMakeLists.txt
index 0cea8d1435..6142de43dd 100644
--- a/firestore/CMakeLists.txt
+++ b/firestore/CMakeLists.txt
@@ -41,6 +41,7 @@ set(common_SRCS
     src/common/hard_assert_common.h
     src/common/listener_registration.cc
     src/common/load_bundle_task_progress.cc
+    src/common/local_cache_settings.cc
     src/common/macros.h
     src/common/query.cc
     src/common/query_snapshot.cc
diff --git a/firestore/integration_test_internal/src/bundle_test.cc b/firestore/integration_test_internal/src/bundle_test.cc
index 3ac9760a9f..486a5e3058 100644
--- a/firestore/integration_test_internal/src/bundle_test.cc
+++ b/firestore/integration_test_internal/src/bundle_test.cc
@@ -19,6 +19,7 @@
 #include <vector>
 
 #include "firebase/firestore.h"
+#include "firebase/firestore/local_cache_settings.h"
 #include "firebase_test_framework.h"
 #include "firestore_integration_test.h"
 #include "gmock/gmock.h"
@@ -327,7 +328,7 @@ TEST_F(BundleTest, LoadedDocumentsShouldNotBeGarbageCollectedRightAway) {
   // This test really only makes sense with memory persistence, as disk
   // persistence only ever lazily deletes data.
   auto new_settings = db->settings();
-  new_settings.set_persistence_enabled(false);
+  new_settings.set_local_cache_settings(MemoryCacheSettings::Create());
   db->set_settings(new_settings);
 
   auto bundle = CreateTestBundle(db);
diff --git a/firestore/integration_test_internal/src/firestore_test.cc b/firestore/integration_test_internal/src/firestore_test.cc
index 70d5974ef8..c10bb2a314 100644
--- a/firestore/integration_test_internal/src/firestore_test.cc
+++ b/firestore/integration_test_internal/src/firestore_test.cc
@@ -20,6 +20,11 @@
 #include <future>
 #include <memory>
 #include <stdexcept>
+#include "firebase/firestore/document_snapshot.h"
+#include "firebase/firestore/field_value.h"
+#include "firebase/firestore/local_cache_settings.h"
+#include "firebase/firestore/map_field_value.h"
+#include "firebase/firestore/source.h"
 
 #if defined(__ANDROID__)
 #include "android/firestore_integration_test_android.h"
@@ -42,6 +47,7 @@
 #include "util/future_test_util.h"
 #if !defined(__ANDROID__)
 #include "Firestore/core/src/util/autoid.h"
+#include "Firestore/core/src/util/warnings.h"
 #include "firestore/src/main/converter_main.h"
 #include "firestore/src/main/firestore_main.h"
 #else
@@ -1757,6 +1763,119 @@ TEST_F(FirestoreTest, ClearPersistenceWhileRunningFails) {
   EXPECT_EQ(await_clear_persistence.error(), Error::kErrorFailedPrecondition);
 }
 
+class FirestoreCacheConfigTest : public FirestoreIntegrationTest {
+ protected:
+  void VerifyCachedDocumentDeletedImmediately(Firestore* db) {
+    Await(db->Document("rooms/eros")
+              .Set(MapFieldValue{{"desc", FieldValue::String("eros")}}));
+
+    auto get_future = db->Document("rooms/eros").Get(Source::kCache);
+    const DocumentSnapshot* snapshot = Await(get_future);
+    ASSERT_NE(snapshot, nullptr);
+    ASSERT_FALSE(snapshot->is_valid());
+  }
+
+  void VerifyCachedDocumentStaysAround(Firestore* db) {
+    Await(db->Document("rooms/eros")
+              .Set(MapFieldValue{{"desc", FieldValue::String("eros")}}));
+
+    auto get_future = db->Document("rooms/eros").Get(Source::kCache);
+    const DocumentSnapshot* snapshot = Await(get_future);
+    ASSERT_NE(snapshot, nullptr);
+    ASSERT_TRUE(snapshot->is_valid());
+    ASSERT_THAT(
+        snapshot->GetData(),
+        ContainerEq(MapFieldValue{{"desc", FieldValue::String("eros")}}));
+  }
+};
+
+TEST_F(FirestoreCacheConfigTest, LegacyCacheConfigForMemoryCacheWorks) {
+  auto* db = TestFirestore("legacy_memory_cache");
+  auto settings = db->settings();
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
+  settings.set_persistence_enabled(false);
+  SUPPRESS_END();
+  db->set_settings(std::move(settings));
+
+  VerifyCachedDocumentDeletedImmediately(db);
+}
+
+TEST_F(FirestoreCacheConfigTest, LegacyCacheConfigForPersistenceCacheWorks) {
+  auto* db = TestFirestore("legacy_persistent_cache");
+  auto settings = db->settings();
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
+  settings.set_persistence_enabled(true);
+  SUPPRESS_END();
+  db->set_settings(std::move(settings));
+
+  VerifyCachedDocumentStaysAround(db);
+}
+
+TEST_F(FirestoreCacheConfigTest, NewCacheConfigForMemoryCacheWorks) {
+  auto* db = TestFirestore("new_memory_cache");
+  auto settings = db->settings();
+  settings.set_local_cache_settings(MemoryCacheSettings::Create());
+  db->set_settings(std::move(settings));
+
+  VerifyCachedDocumentDeletedImmediately(db);
+}
+
+TEST_F(FirestoreCacheConfigTest, NewCacheConfigForPersistenceCacheWorks) {
+  auto* db = TestFirestore("new_persistent_cache");
+  auto settings = db->settings();
+  settings.set_local_cache_settings(
+      PersistentCacheSettings::Create().WithSizeBytes(50 * 1024 * 1024));
+  db->set_settings(std::move(settings));
+
+  VerifyCachedDocumentStaysAround(db);
+}
+
+TEST_F(FirestoreCacheConfigTest, CannotMixNewAndLegacyCacheConfig) {
+  {
+    auto* db = TestFirestore("mixing_1");
+    auto settings = db->settings();
+    settings.set_local_cache_settings(
+        PersistentCacheSettings::Create().WithSizeBytes(50 * 1024 * 1024));
+
+    SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
+    EXPECT_THROW(settings.set_cache_size_bytes(0), std::logic_error);
+    SUPPRESS_END();
+  }
+
+  {
+    auto* db = TestFirestore("mixing_2");
+    auto settings = db->settings();
+    SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
+    settings.set_persistence_enabled(false);
+    SUPPRESS_END();
+    EXPECT_THROW(
+        settings.set_local_cache_settings(MemoryCacheSettings::Create()),
+        std::logic_error);
+  }
+}
+
+TEST_F(FirestoreCacheConfigTest, CanGetDocumentFromCacheWithMemoryLruGC) {
+  auto* db = TestFirestore("new_persistent_cache");
+  auto settings = db->settings();
+  settings.set_local_cache_settings(
+      MemoryCacheSettings::Create().WithGarbageCollectorSettings(
+          MemoryLruGCSettings::Create()));
+  db->set_settings(std::move(settings));
+
+  VerifyCachedDocumentStaysAround(db);
+}
+
+TEST_F(FirestoreCacheConfigTest, CannotGetDocumentFromCacheFromMemoryEagerGC) {
+  auto* db = TestFirestore("new_persistent_cache");
+  auto settings = db->settings();
+  settings.set_local_cache_settings(
+      MemoryCacheSettings::Create().WithGarbageCollectorSettings(
+          MemoryEagerGCSettings::Create()));
+  db->set_settings(std::move(settings));
+
+  VerifyCachedDocumentDeletedImmediately(db);
+}
+
 // Note: this test only exists in C++.
 TEST_F(FirestoreTest, DomainObjectsReferToSameFirestoreInstance) {
   EXPECT_EQ(TestFirestore(), TestFirestore()->Document("foo/bar").firestore());
diff --git a/firestore/integration_test_internal/src/settings_test.cc b/firestore/integration_test_internal/src/settings_test.cc
index ca62e2a74e..19e52269ca 100644
--- a/firestore/integration_test_internal/src/settings_test.cc
+++ b/firestore/integration_test_internal/src/settings_test.cc
@@ -16,7 +16,10 @@
 
 #include <stdint.h>
 
+#include "Firestore/core/src/util/warnings.h"
 #include "firebase/firestore.h"
+#include "firebase/firestore/local_cache_settings.h"
+#include "firebase_test_framework.h"
 
 #include "gtest/gtest.h"
 
@@ -31,39 +34,51 @@ TEST(SettingsTest, Equality) {
   Settings settings1;
   settings1.set_host("foo");
   settings1.set_ssl_enabled(true);
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
   settings1.set_persistence_enabled(true);
   settings1.set_cache_size_bytes(kFiveMb);
+  SUPPRESS_END();
 
   Settings settings2;
   settings2.set_host("bar");
   settings2.set_ssl_enabled(true);
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
   settings2.set_persistence_enabled(true);
   settings2.set_cache_size_bytes(kFiveMb);
+  SUPPRESS_END();
 
   Settings settings3;
   settings3.set_host("foo");
   settings3.set_ssl_enabled(false);
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
   settings3.set_persistence_enabled(true);
   settings3.set_cache_size_bytes(kFiveMb);
+  SUPPRESS_END();
 
   Settings settings4;
   settings4.set_host("foo");
   settings4.set_ssl_enabled(true);
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
   settings4.set_persistence_enabled(false);
   settings4.set_cache_size_bytes(kFiveMb);
+  SUPPRESS_END();
 
   Settings settings5;
   settings5.set_host("foo");
   settings5.set_ssl_enabled(true);
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
   settings5.set_persistence_enabled(true);
   settings5.set_cache_size_bytes(kSixMb);
+  SUPPRESS_END();
 
   // This is the same as settings4.
   Settings settings6;
   settings6.set_host("foo");
   settings6.set_ssl_enabled(true);
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN();
   settings6.set_persistence_enabled(false);
   settings6.set_cache_size_bytes(kFiveMb);
+  SUPPRESS_END();
 
   EXPECT_TRUE(settings1 == settings1);
   EXPECT_TRUE(settings6 == settings4);
@@ -94,6 +109,103 @@ TEST(SettingsTest, Equality) {
   EXPECT_TRUE(settings4 != settings5);
 }
 
+TEST(SettingsTest, EqualityWithLocalCacheSettings) {
+  constexpr int64_t kFiveMb = 5 * 1024 * 1024;
+  constexpr int64_t kSixMb = 6 * 1024 * 1024;
+
+  Settings settings1;
+  settings1.set_host("foo");
+  settings1.set_ssl_enabled(true);
+  settings1.set_local_cache_settings(
+      PersistentCacheSettings::Create().WithSizeBytes(kFiveMb));
+
+  Settings settings2;
+  settings2.set_host("bar");
+  settings2.set_ssl_enabled(true);
+  settings2.set_local_cache_settings(
+      PersistentCacheSettings::Create().WithSizeBytes(kFiveMb));
+
+  Settings settings3;
+  settings3.set_host("foo");
+  settings3.set_ssl_enabled(false);
+  settings3.set_local_cache_settings(
+      PersistentCacheSettings::Create().WithSizeBytes(kFiveMb));
+
+  Settings settings4;
+  settings4.set_host("foo");
+  settings4.set_ssl_enabled(true);
+  settings4.set_local_cache_settings(MemoryCacheSettings::Create());
+
+  Settings settings5;
+  settings5.set_host("foo");
+  settings5.set_ssl_enabled(true);
+  settings5.set_local_cache_settings(
+      PersistentCacheSettings::Create().WithSizeBytes(kSixMb));
+
+  Settings settings6;
+  settings6.set_host("foo");
+  settings6.set_ssl_enabled(true);
+  settings6.set_local_cache_settings(
+      MemoryCacheSettings::Create().WithGarbageCollectorSettings(
+          MemoryEagerGCSettings::Create()));
+
+  Settings settings7;
+  settings7.set_host("foo");
+  settings7.set_ssl_enabled(true);
+  settings7.set_local_cache_settings(
+      MemoryCacheSettings::Create().WithGarbageCollectorSettings(
+          MemoryLruGCSettings::Create().WithSizeBytes(kFiveMb)));
+
+  Settings settings8;
+  settings8.set_host("foo");
+  settings8.set_ssl_enabled(true);
+  settings8.set_local_cache_settings(
+      MemoryCacheSettings::Create().WithGarbageCollectorSettings(
+          MemoryLruGCSettings::Create().WithSizeBytes(kSixMb)));
+
+  // Same as settings7
+  Settings settings9;
+  settings9.set_host("foo");
+  settings9.set_ssl_enabled(true);
+  settings9.set_local_cache_settings(
+      MemoryCacheSettings::Create().WithGarbageCollectorSettings(
+          MemoryLruGCSettings::Create().WithSizeBytes(kFiveMb)));
+
+  EXPECT_TRUE(settings1 == settings1);
+  EXPECT_TRUE(settings6 == settings4);
+  EXPECT_TRUE(settings7 == settings9);
+
+  EXPECT_FALSE(settings1 == settings2);
+  EXPECT_FALSE(settings1 == settings3);
+  EXPECT_FALSE(settings1 == settings4);
+  EXPECT_FALSE(settings1 == settings5);
+  EXPECT_FALSE(settings2 == settings3);
+  EXPECT_FALSE(settings2 == settings4);
+  EXPECT_FALSE(settings2 == settings5);
+  EXPECT_FALSE(settings3 == settings4);
+  EXPECT_FALSE(settings3 == settings5);
+  EXPECT_FALSE(settings4 == settings5);
+  EXPECT_FALSE(settings6 == settings7);
+  EXPECT_FALSE(settings7 == settings8);
+
+  EXPECT_FALSE(settings1 != settings1);
+  EXPECT_FALSE(settings6 != settings4);
+  EXPECT_FALSE(settings7 != settings9);
+
+  EXPECT_TRUE(settings1 != settings2);
+  EXPECT_TRUE(settings1 != settings3);
+  EXPECT_TRUE(settings1 != settings4);
+  EXPECT_TRUE(settings1 != settings5);
+  EXPECT_TRUE(settings2 != settings3);
+  EXPECT_TRUE(settings2 != settings4);
+  EXPECT_TRUE(settings2 != settings5);
+  EXPECT_TRUE(settings3 != settings4);
+  EXPECT_TRUE(settings3 != settings5);
+  EXPECT_TRUE(settings4 != settings5);
+  EXPECT_TRUE(settings6 != settings7);
+  EXPECT_TRUE(settings7 != settings8);
+}
+
 }  // namespace
 }  // namespace firestore
 }  // namespace firebase
diff --git a/firestore/src/common/local_cache_settings.cc b/firestore/src/common/local_cache_settings.cc
new file mode 100644
index 0000000000..b5ea995ed1
--- /dev/null
+++ b/firestore/src/common/local_cache_settings.cc
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#include "firestore/src/include/firebase/firestore/local_cache_settings.h"
+#include <memory>
+
+#include "firestore/src/common/hard_assert_common.h"
+#if defined(__ANDROID__)
+#else
+#include "firestore/src/main/local_cache_settings_main.h"
+#endif  // defined(__ANDROID__)
+
+namespace firebase {
+namespace firestore {
+
+PersistentCacheSettings PersistentCacheSettings::Create() { return {}; }
+
+PersistentCacheSettings::PersistentCacheSettings() {
+  settings_internal_ = std::make_shared<PersistentCacheSettingsInternal>();
+}
+
+PersistentCacheSettings PersistentCacheSettings::WithSizeBytes(
+    int64_t size) const {
+  PersistentCacheSettings new_settings;
+  new_settings.settings_internal_ =
+      std::make_shared<PersistentCacheSettingsInternal>(
+          this->settings_internal_->WithSizeBytes(size));
+  return new_settings;
+}
+
+int64_t PersistentCacheSettings::size_bytes() const {
+  return settings_internal_->size_bytes();
+}
+
+const LocalCacheSettingsInternal& PersistentCacheSettings::internal() const {
+  return *settings_internal_;
+}
+
+MemoryEagerGCSettings MemoryEagerGCSettings::Create() { return {}; }
+
+MemoryEagerGCSettings::MemoryEagerGCSettings() {
+  settings_internal_ = std::make_shared<MemoryEagerGCSettingsInternal>();
+}
+
+const MemoryGarbageCollectorSettingsInternal& MemoryEagerGCSettings::internal()
+    const {
+  return *settings_internal_;
+}
+
+MemoryLruGCSettings MemoryLruGCSettings::Create() { return {}; }
+
+MemoryLruGCSettings::MemoryLruGCSettings() {
+  settings_internal_ = std::make_shared<MemoryLruGCSettingsInternal>();
+}
+
+MemoryLruGCSettings::MemoryLruGCSettings(
+    const MemoryLruGCSettingsInternal& other) {
+  settings_internal_ = std::make_shared<MemoryLruGCSettingsInternal>(other);
+}
+
+MemoryLruGCSettings MemoryLruGCSettings::WithSizeBytes(int64_t size) {
+  MemoryLruGCSettings result;
+  result.settings_internal_ = std::make_shared<MemoryLruGCSettingsInternal>(
+      this->settings_internal_->WithSizeBytes(size));
+  return result;
+}
+
+int64_t MemoryLruGCSettings::size_bytes() const {
+  return settings_internal_->size_bytes();
+}
+
+const MemoryGarbageCollectorSettingsInternal& MemoryLruGCSettings::internal()
+    const {
+  return *settings_internal_;
+}
+
+MemoryCacheSettings MemoryCacheSettings::Create() { return {}; }
+
+MemoryCacheSettings::MemoryCacheSettings() {
+  settings_internal_ = std::make_shared<MemoryCacheSettingsInternal>();
+}
+
+MemoryCacheSettings MemoryCacheSettings::WithGarbageCollectorSettings(
+    const MemoryGarbageCollectorSettings& settings) const {
+  MemoryCacheSettings result;
+  result.settings_internal_ = std::make_shared<MemoryCacheSettingsInternal>(
+      this->settings_internal_->WithGarbageCollectorSettings(settings));
+  return result;
+}
+
+const LocalCacheSettingsInternal& MemoryCacheSettings::internal() const {
+  return *settings_internal_;
+}
+
+bool operator==(const LocalCacheSettings& lhs, const LocalCacheSettings& rhs) {
+  return lhs.kind() == rhs.kind() && lhs.internal() == rhs.internal();
+}
+
+bool operator==(const MemoryCacheSettings& lhs,
+                const MemoryCacheSettings& rhs) {
+  return &lhs == &rhs || (*lhs.settings_internal_ == *rhs.settings_internal_);
+}
+
+bool operator==(const PersistentCacheSettings& lhs,
+                const PersistentCacheSettings& rhs) {
+  return &lhs == &rhs || (*lhs.settings_internal_ == *rhs.settings_internal_);
+}
+
+bool operator==(const MemoryGarbageCollectorSettings& lhs,
+                const MemoryGarbageCollectorSettings& rhs) {
+  return lhs.internal() == rhs.internal();
+}
+
+bool operator==(const MemoryEagerGCSettings& lhs,
+                const MemoryEagerGCSettings& rhs) {
+  return &lhs == &rhs || (*lhs.settings_internal_ == *rhs.settings_internal_);
+}
+
+bool operator==(const MemoryLruGCSettings& lhs,
+                const MemoryLruGCSettings& rhs) {
+  return &lhs == &rhs || (*lhs.settings_internal_ == *rhs.settings_internal_);
+}
+
+}  // namespace firestore
+}  // namespace firebase
diff --git a/firestore/src/common/settings.cc b/firestore/src/common/settings.cc
index 5f2eb56a26..3be7d0c9a1 100644
--- a/firestore/src/common/settings.cc
+++ b/firestore/src/common/settings.cc
@@ -16,11 +16,14 @@
 
 #include "firestore/src/include/firebase/firestore/settings.h"
 
+#include <memory>
 #include <ostream>
 #include <sstream>
-
 #include <utility>
 
+#include "firebase/firestore/local_cache_settings.h"
+#include "firestore/src/common/exception_common.h"
+
 #if !defined(__ANDROID__)
 #include "Firestore/core/src/util/executor.h"
 #endif
@@ -44,18 +47,66 @@ std::string ToStr(int64_t v) {
 }  // namespace
 
 #if !defined(__APPLE__)
-Settings::Settings() : host_(kDefaultHost) {}
+Settings::Settings()
+    : host_(kDefaultHost),
+      local_cache_settings_(std::make_shared<PersistentCacheSettings>(
+          PersistentCacheSettings::Create())) {}
 #endif
 
 void Settings::set_host(std::string host) { host_ = std::move(host); }
 
 void Settings::set_ssl_enabled(bool enabled) { ssl_enabled_ = enabled; }
 
+const LocalCacheSettings& Settings::local_cache_settings() {
+  if (cache_settings_source_ == CacheSettingsSource::kOld) {
+    if (is_persistence_enabled()) {
+      local_cache_settings_ = std::make_shared<PersistentCacheSettings>(
+          PersistentCacheSettings::Create().WithSizeBytes(cache_size_bytes()));
+    } else {
+      local_cache_settings_ =
+          std::make_shared<MemoryCacheSettings>(MemoryCacheSettings::Create());
+    }
+  }
+
+  return *local_cache_settings_;
+}
+
+void Settings::set_local_cache_settings(const LocalCacheSettings& cache) {
+  if (cache_settings_source_ == CacheSettingsSource::kOld) {
+    SimpleThrowIllegalState(
+        "Cannot mix set_local_cache_settings() with legacy cache api like "
+        "set_persistence_enabled() or set_cache_size_bytes()");
+  }
+
+  cache_settings_source_ = CacheSettingsSource::kNew;
+  if (cache.kind() == LocalCacheSettings::Kind::kPersistent) {
+    local_cache_settings_ = std::make_shared<PersistentCacheSettings>(
+        static_cast<const PersistentCacheSettings&>(cache));
+  } else {
+    local_cache_settings_ = std::make_shared<MemoryCacheSettings>(
+        static_cast<const MemoryCacheSettings&>(cache));
+  }
+}
+
 void Settings::set_persistence_enabled(bool enabled) {
+  if (cache_settings_source_ == CacheSettingsSource::kNew) {
+    SimpleThrowIllegalState(
+        "Cannot mix legacy cache api set_persistence_enabled() with new cache "
+        "api set_local_cache_settings()");
+  }
+
+  cache_settings_source_ = CacheSettingsSource::kOld;
   persistence_enabled_ = enabled;
 }
 
 void Settings::set_cache_size_bytes(int64_t value) {
+  if (cache_settings_source_ == CacheSettingsSource::kNew) {
+    SimpleThrowIllegalState(
+        "Cannot mix legacy cache api set_cache_size_bytes() with new cache api "
+        "set_local_cache_settings()");
+  }
+
+  cache_settings_source_ = CacheSettingsSource::kOld;
   cache_size_bytes_ = value;
 }
 
@@ -70,6 +121,40 @@ std::ostream& operator<<(std::ostream& out, const Settings& settings) {
   return out << settings.ToString();
 }
 
+bool operator==(const Settings& lhs, const Settings& rhs) {
+  if (lhs.host() != rhs.host()) {
+    return false;
+  }
+
+  if (lhs.is_ssl_enabled() != rhs.is_ssl_enabled()) {
+    return false;
+  }
+
+  if (lhs.cache_settings_source_ != rhs.cache_settings_source_) {
+    return false;
+  }
+
+  if (*lhs.local_cache_settings_ != *rhs.local_cache_settings_) {
+    return false;
+  }
+
+  if (lhs.is_persistence_enabled() != rhs.is_persistence_enabled()) {
+    return false;
+  }
+
+  if (lhs.cache_size_bytes() != rhs.cache_size_bytes()) {
+    return false;
+  }
+
+#if defined(__OBJC__)
+  if (lhs.dispatch_queue() != rhs.dispatch_queue()) {
+    return false;
+  }
+#endif  // defined(__OBJC__)
+
+  return true;
+}
+
 // Apple uses a different mechanism, defined in `settings_apple.mm`.
 #if !defined(__APPLE__) && !defined(__ANDROID__)
 std::unique_ptr<util::Executor> Settings::CreateExecutor() const {
diff --git a/firestore/src/common/settings_apple.mm b/firestore/src/common/settings_apple.mm
index 5ff4b325df..eba499a857 100644
--- a/firestore/src/common/settings_apple.mm
+++ b/firestore/src/common/settings_apple.mm
@@ -20,6 +20,7 @@
 #include <memory>
 
 #include "Firestore/core/src/util/executor_libdispatch.h"
+#include "firebase/firestore/local_cache_settings.h"
 
 namespace firebase {
 namespace firestore {
@@ -36,7 +37,9 @@
 Settings::Settings()
     : host_(kDefaultHost),
       executor_(
-          Executor::CreateSerial("com.google.firebase.firestore.callback")) {}
+          Executor::CreateSerial("com.google.firebase.firestore.callback")),
+      local_cache_settings_(std::make_unique<PersistentCacheSettings>(
+          PersistentCacheSettings::Create())) {}
 
 std::unique_ptr<Executor> Settings::CreateExecutor() const {
   return std::make_unique<ExecutorLibdispatch>(dispatch_queue());
diff --git a/firestore/src/include/firebase/firestore/local_cache_settings.h b/firestore/src/include/firebase/firestore/local_cache_settings.h
new file mode 100644
index 0000000000..b7d4a5eaa8
--- /dev/null
+++ b/firestore/src/include/firebase/firestore/local_cache_settings.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_LOCAL_CACHE_SETTINGS_H_
+#define FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_LOCAL_CACHE_SETTINGS_H_
+
+#include <cstdint>
+#include <memory>
+
+#include "firestore/src/include/firebase/firestore/settings.h"
+
+namespace firebase {
+namespace firestore {
+
+class LocalCacheSettingsInternal;
+class PersistentCacheSettingsInternal;
+class MemoryCacheSettingsInternal;
+class MemoryLruGCSettingsInternal;
+class MemoryEagerGCSettingsInternal;
+class MemoryGarbageCollectorSettingsInternal;
+
+/**
+ * Abstract class implemented by all supported cache settings.
+ *
+ * `PersistentCacheSettings` and `MemoryCacheSettings` are the only cache types
+ * supported by the SDK. Custom implementation is not supported.
+ */
+class LocalCacheSettings {
+ public:
+  enum class Kind { kMemory, kPersistent };
+
+  virtual ~LocalCacheSettings() = default;
+
+  virtual Kind kind() const = 0;
+
+  /** Equality function. */
+  friend bool operator==(const LocalCacheSettings& lhs,
+                         const LocalCacheSettings& rhs);
+
+ private:
+  friend class FirestoreInternal;
+  friend class Settings;
+  friend class PersistentCacheSettings;
+  friend class MemoryCacheSettings;
+
+  LocalCacheSettings() = default;
+
+  virtual const LocalCacheSettingsInternal& internal() const = 0;
+};
+
+/**
+ * Configures the SDK to use a persistent cache. Firestore documents and
+ * mutations are persisted across App restart.
+ *
+ * This is the default cache type unless explicitly specified otherwise.
+ *
+ * To use, create an instance using `PersistentCacheSettings::Create`, then
+ * pass it to an instance of `Settings` via `set_local_cache_settings()`, and
+ * use the `Settings` instance to configure the Firestore SDK.
+ */
+class PersistentCacheSettings final : public LocalCacheSettings {
+ public:
+  /** Create a default instance `PersistenceCacheSettings`. */
+  static PersistentCacheSettings Create();
+
+  /** Equality function. */
+  friend bool operator==(const PersistentCacheSettings& lhs,
+                         const PersistentCacheSettings& rhs);
+
+  /**
+   * Copies this settings instance, with the approximate cache size threshold
+   * for the on-disk data set to the given number in term of number of bytes,
+   * and return the new setting instance.
+   *
+   * If the cache grows beyond this size, Firestore SDK will start removing data
+   * that hasn't been recently used. The SDK does not guarantee that the cache
+   * will stay below that size, only that if the cache exceeds the given size,
+   * cleanup will be attempted.
+   *
+   * By default, persistence cache is enabled with a cache size of 100 MB. The
+   * minimum value is 1 MB (1 * 1024 * 1024 bytes).
+   */
+  PersistentCacheSettings WithSizeBytes(int64_t size) const;
+
+  /**
+   * Returns the approximate cache size threshold configured. Garbage collection
+   * kicks in once the cache size exceeds this threshold.
+   */
+  int64_t size_bytes() const;
+
+ private:
+  friend class Settings;
+  friend class FirestoreInternal;
+
+  PersistentCacheSettings();
+
+  LocalCacheSettings::Kind kind() const override {
+    return LocalCacheSettings::Kind::kPersistent;
+  }
+
+  // Get the corresponding settings object from the core sdk.
+  const LocalCacheSettingsInternal& internal() const override;
+
+  std::shared_ptr<PersistentCacheSettingsInternal> settings_internal_;
+};
+
+class MemoryGarbageCollectorSettings;
+
+/**
+ * Configures the SDK to use a memory cache. Firestore documents and mutations
+ * are NOT persisted across App restart.
+ *
+ * To use, create an instance using `MemoryCacheSettings::Create`, then
+ * pass it to an instance of `Settings` via `set_local_cache_settings()`, and
+ * use the `Settings` instance to configure the Firestore SDK.
+ */
+class MemoryCacheSettings final : public LocalCacheSettings {
+ public:
+  /** Create a default instance `MemoryCacheSettings`. */
+  static MemoryCacheSettings Create();
+
+  /** Equality function. */
+  friend bool operator==(const MemoryCacheSettings& lhs,
+                         const MemoryCacheSettings& rhs);
+
+  /**
+   * Copies this settings instance, with its `MemoryGarbageCollectorSettins` set
+   * the the given parameter, and returns the new settings instance.
+   */
+  MemoryCacheSettings WithGarbageCollectorSettings(
+      const MemoryGarbageCollectorSettings& settings) const;
+
+ private:
+  friend class Settings;
+  friend class FirestoreInternal;
+
+  MemoryCacheSettings();
+
+  LocalCacheSettings::Kind kind() const override {
+    return LocalCacheSettings::Kind::kMemory;
+  }
+
+  const LocalCacheSettingsInternal& internal() const override;
+
+  std::shared_ptr<MemoryCacheSettingsInternal> settings_internal_;
+};
+
+/**
+ * Abstract class implemented by all supported memory garbage collector.
+ *
+ * `MemoryEagerGCSettings` and `MemoryLruGCSettings` are the only memory
+ * garbage collectors supported by the SDK. Custom implementation is not
+ * supported.
+ */
+class MemoryGarbageCollectorSettings {
+ public:
+  virtual ~MemoryGarbageCollectorSettings() = default;
+  /** Equality function. */
+  friend bool operator==(const MemoryGarbageCollectorSettings& lhs,
+                         const MemoryGarbageCollectorSettings& rhs);
+
+ private:
+  friend class MemoryCacheSettings;
+  friend class MemoryEagerGCSettings;
+  friend class MemoryLruGCSettings;
+  friend class MemoryCacheSettingsInternal;
+
+  MemoryGarbageCollectorSettings() = default;
+
+  virtual const MemoryGarbageCollectorSettingsInternal& internal() const = 0;
+};
+
+/**
+ * Configures the memory cache to use a garbage collector with an eager
+ * strategy.
+ *
+ * An eager garbage collector deletes documents whenever they are not part of
+ * any active queries, and have no local mutations attached to them.
+ *
+ * This collector tries to ensure lowest memory footprints from the SDK,
+ * at the risk of documents not being cached for offline queries or for
+ * direct queries to the cache.
+ *
+ * To use, pass an instance of `MemoryEagerGCSettings` to
+ * `MemoryCacheSettings::WithGarbageCollectorSettings()` to get a new instance
+ * of `MemoryCacheSettings`, which can be used to configure the SDK.
+ */
+class MemoryEagerGCSettings final : public MemoryGarbageCollectorSettings {
+ public:
+  /** Create a default instance `MemoryEagerGCSettings`. */
+  static MemoryEagerGCSettings Create();
+
+  /** Equality function. */
+  friend bool operator==(const MemoryEagerGCSettings& lhs,
+                         const MemoryEagerGCSettings& rhs);
+
+ private:
+  friend class MemoryCacheSettings;
+  MemoryEagerGCSettings();
+  const MemoryGarbageCollectorSettingsInternal& internal() const override;
+
+  std::shared_ptr<MemoryEagerGCSettingsInternal> settings_internal_;
+};
+
+/**
+ * Configures the memory cache to use a garbage collector with an
+ * least-recently-used strategy.
+ *
+ * A LRU garbage collector deletes Least-Recently-Used documents in multiple
+ * batches.
+ *
+ * This collector is configured with a target size, and will only perform
+ * collection when the cached documents exceed the target size. It avoids
+ * querying backend repeated for the same query or document, at the risk
+ * of having a larger memory footprint.
+ *
+ * To use, pass an instance of `MemoryLRUGCSettings` to
+ * `MemoryCacheSettings::WithGarbageCollectorSettings()` to get a new instance
+ * of `MemoryCacheSettings`, which can be used to configure the SDK.
+ */
+class MemoryLruGCSettings final : public MemoryGarbageCollectorSettings {
+ public:
+  /** Create a default instance `MemoryLruGCSettings`. */
+  static MemoryLruGCSettings Create();
+
+  /** Equality function. */
+  friend bool operator==(const MemoryLruGCSettings& lhs,
+                         const MemoryLruGCSettings& rhs);
+
+  /**
+   * Copies this settings instance, with the approximate cache size threshold
+   * for the memory data set to the given number in term of number of bytes, and
+   * return the new setting instance.
+   *
+   * If the cache grows beyond this size, Firestore SDK will start removing data
+   * that hasn't been recently used. The SDK does not guarantee that the cache
+   * will stay below that size, only that if the cache exceeds the given size,
+   * cleanup will be attempted.
+   *
+   * By default, memory LRU cache is enabled with a cache size of 100 MB. The
+   * minimum value is 1 MB (1 * 1024 * 1024 bytes).
+   */
+  MemoryLruGCSettings WithSizeBytes(int64_t size);
+
+  /**
+   * Returns the approximate cache size threshold configured. Garbage collection
+   * kicks in once the cache size exceeds this threshold.
+   */
+  int64_t size_bytes() const;
+
+ private:
+  friend class MemoryCacheSettings;
+  MemoryLruGCSettings();
+  MemoryLruGCSettings(const MemoryLruGCSettingsInternal& other);
+
+  const MemoryGarbageCollectorSettingsInternal& internal() const override;
+
+  std::shared_ptr<MemoryLruGCSettingsInternal> settings_internal_;
+};
+
+/** Inequality function. */
+inline bool operator!=(const LocalCacheSettings& lhs,
+                       const LocalCacheSettings& rhs) {
+  return !(lhs == rhs);
+}
+
+/** Inequality function. */
+inline bool operator!=(const MemoryCacheSettings& lhs,
+                       const MemoryCacheSettings& rhs) {
+  return !(lhs == rhs);
+}
+
+/** Inequality function. */
+inline bool operator!=(const PersistentCacheSettings& lhs,
+                       const PersistentCacheSettings& rhs) {
+  return !(lhs == rhs);
+}
+
+/** Inequality function. */
+inline bool operator!=(const MemoryGarbageCollectorSettings& lhs,
+                       const MemoryGarbageCollectorSettings& rhs) {
+  return !(lhs == rhs);
+}
+
+/** Inequality function. */
+inline bool operator!=(const MemoryEagerGCSettings& lhs,
+                       const MemoryEagerGCSettings& rhs) {
+  return !(lhs == rhs);
+}
+
+/** Inequality function. */
+inline bool operator!=(const MemoryLruGCSettings& lhs,
+                       const MemoryLruGCSettings& rhs) {
+  return !(lhs == rhs);
+}
+
+}  // namespace firestore
+}  // namespace firebase
+
+#endif  // FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_LOCAL_CACHE_SETTINGS_H_
diff --git a/firestore/src/include/firebase/firestore/settings.h b/firestore/src/include/firebase/firestore/settings.h
index 8169d9f594..c83b2409d7 100644
--- a/firestore/src/include/firebase/firestore/settings.h
+++ b/firestore/src/include/firebase/firestore/settings.h
@@ -17,6 +17,7 @@
 #ifndef FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_SETTINGS_H_
 #define FIREBASE_FIRESTORE_SRC_INCLUDE_FIREBASE_FIRESTORE_SETTINGS_H_
 
+#include "firebase/internal/common.h"
 #if defined(__OBJC__)
 #include <dispatch/dispatch.h>
 #endif
@@ -47,6 +48,7 @@ class Executor;
 #endif
 
 class FirestoreInternal;
+class LocalCacheSettings;
 
 /** Settings used to configure a Firestore instance. */
 class Settings final {
@@ -137,13 +139,37 @@ class Settings final {
   void set_ssl_enabled(bool enabled);
 
   /**
+   * Returns a reference to the `LocalCacheSettings` instance
+   * used to configure this SDK.
+   */
+  const LocalCacheSettings& local_cache_settings();
+
+  /**
+   * Configures the SDK with the given `LocalCacheSettings` instance.
+   *
+   * By default, persistence cache is enabled, with a cache size of 100 MB.
+   *
+   * See documentation of `PersistentCacheSettings` to under the default
+   * settings.
+   *
+   * @param cache_settings Settings object to configue this SDK.
+   */
+  void set_local_cache_settings(const LocalCacheSettings& cache_settings);
+
+  /**
+   * NOTE: This method is deprecated in favor of `set_local_cache_settings()`.
+   * It will be deleted in a future major release.
+   *
    * Enables or disables local persistent storage.
    *
    * @param enabled Set true to enable local persistent storage.
    */
-  void set_persistence_enabled(bool enabled);
+  FIREBASE_DEPRECATED void set_persistence_enabled(bool enabled);
 
   /**
+   * NOTE: This method is deprecated in favor of `set_local_cache_settings()`.
+   * It will be deleted in a future major release.
+   *
    * Sets an approximate cache size threshold for the on-disk data. If the cache
    * grows beyond this size, Cloud Firestore will start removing data that
    * hasn't been recently used. The size is not a guarantee that the cache will
@@ -153,7 +179,7 @@ class Settings final {
    * By default, collection is enabled with a cache size of 100 MB. The minimum
    * value is 1 MB.
    */
-  void set_cache_size_bytes(int64_t value);
+  FIREBASE_DEPRECATED void set_cache_size_bytes(int64_t value);
 
 #if defined(__OBJC__) || defined(DOXYGEN)
   /**
@@ -208,11 +234,19 @@ class Settings final {
    */
   friend std::ostream& operator<<(std::ostream& out, const Settings& settings);
 
+  /** Checks `lhs` and `rhs` for equality. */
+  friend bool operator==(const Settings& lhs, const Settings& rhs);
+
  private:
   static constexpr int64_t kDefaultCacheSizeBytes = 100 * 1024 * 1024;
+  enum class CacheSettingsSource { kNone, kNew, kOld };
 
   std::string host_;
   bool ssl_enabled_ = true;
+
+  CacheSettingsSource cache_settings_source_{CacheSettingsSource::kNone};
+
+  std::shared_ptr<LocalCacheSettings> local_cache_settings_;
   bool persistence_enabled_ = true;
   int64_t cache_size_bytes_ = kDefaultCacheSizeBytes;
 
@@ -228,14 +262,6 @@ class Settings final {
 #endif
 };
 
-/** Checks `lhs` and `rhs` for equality. */
-inline bool operator==(const Settings& lhs, const Settings& rhs) {
-  return lhs.host() == rhs.host() &&
-         lhs.is_ssl_enabled() == rhs.is_ssl_enabled() &&
-         lhs.is_persistence_enabled() == rhs.is_persistence_enabled() &&
-         lhs.cache_size_bytes() == rhs.cache_size_bytes();
-}
-
 /** Checks `lhs` and `rhs` for inequality. */
 inline bool operator!=(const Settings& lhs, const Settings& rhs) {
   return !(lhs == rhs);
diff --git a/firestore/src/main/firestore_main.cc b/firestore/src/main/firestore_main.cc
index 8a512a49e5..d40469e9e6 100644
--- a/firestore/src/main/firestore_main.cc
+++ b/firestore/src/main/firestore_main.cc
@@ -23,6 +23,7 @@
 
 #include "Firestore/core/src/api/document_reference.h"
 #include "Firestore/core/src/api/query_core.h"
+#include "Firestore/core/src/api/settings.h"
 #include "Firestore/core/src/credentials/empty_credentials_provider.h"
 #include "Firestore/core/src/model/database_id.h"
 #include "Firestore/core/src/model/resource_path.h"
@@ -32,16 +33,19 @@
 #include "Firestore/core/src/util/executor.h"
 #include "Firestore/core/src/util/log.h"
 #include "Firestore/core/src/util/status.h"
+#include "Firestore/core/src/util/warnings.h"
 #include "absl/memory/memory.h"
 #include "absl/types/any.h"
 #include "app/src/include/firebase/future.h"
 #include "app/src/reference_counted_future_impl.h"
 #include "firebase/firestore/firestore_version.h"
+#include "firebase/firestore/settings.h"
 #include "firestore/src/common/exception_common.h"
 #include "firestore/src/common/hard_assert_common.h"
 #include "firestore/src/common/macros.h"
 #include "firestore/src/common/util.h"
 #include "firestore/src/include/firebase/firestore.h"
+#include "firestore/src/include/firebase/firestore/local_cache_settings.h"
 #include "firestore/src/main/converter_main.h"
 #include "firestore/src/main/create_app_check_credentials_provider.h"
 #include "firestore/src/main/create_credentials_provider.h"
@@ -49,6 +53,7 @@
 #include "firestore/src/main/document_reference_main.h"
 #include "firestore/src/main/document_snapshot_main.h"
 #include "firestore/src/main/listener_main.h"
+#include "firestore/src/main/local_cache_settings_main.h"
 
 namespace firebase {
 namespace firestore {
@@ -193,8 +198,16 @@ Settings FirestoreInternal::settings() const {
   const api::Settings& from = firestore_core_->settings();
   result.set_host(from.host());
   result.set_ssl_enabled(from.ssl_enabled());
+
+  // TODO(wuandy): We use the deprecated API for default settings, but mark
+  // `cache_settings_source_` as `kNew` such that new settings API is not
+  // rejected by runtime checks. This should be removed when legacy API is
+  // removed.
+  SUPPRESS_DEPRECATED_DECLARATIONS_BEGIN()
   result.set_persistence_enabled(from.persistence_enabled());
   result.set_cache_size_bytes(from.cache_size_bytes());
+  SUPPRESS_END()
+  result.cache_settings_source_ = Settings::CacheSettingsSource::kNone;
 
   return result;
 }
@@ -203,8 +216,16 @@ void FirestoreInternal::set_settings(Settings from) {
   api::Settings settings;
   settings.set_host(std::move(from.host()));
   settings.set_ssl_enabled(from.is_ssl_enabled());
-  settings.set_persistence_enabled(from.is_persistence_enabled());
-  settings.set_cache_size_bytes(from.cache_size_bytes());
+  // TODO(wuandy): Checking `from.local_cache_settings_` is required, because
+  // FirestoreInternal::settings() overrides used_legacy_cache_settings_. All
+  // this special logic should go away when legacy cache config is removed.
+  if (from.cache_settings_source_ == Settings::CacheSettingsSource::kNew) {
+    settings.set_local_cache_settings(
+        from.local_cache_settings().internal().core_settings());
+  } else {
+    settings.set_persistence_enabled(from.is_persistence_enabled());
+    settings.set_cache_size_bytes(from.cache_size_bytes());
+  }
   firestore_core_->set_settings(settings);
 
   std::unique_ptr<Executor> user_executor = from.CreateExecutor();
diff --git a/firestore/src/main/firestore_main.h b/firestore/src/main/firestore_main.h
index 7920eccc4f..a9a2739b36 100644
--- a/firestore/src/main/firestore_main.h
+++ b/firestore/src/main/firestore_main.h
@@ -48,6 +48,7 @@ class Firestore;
 class ListenerRegistrationInternal;
 class Transaction;
 class WriteBatch;
+class Settings;
 
 namespace util {
 class Executor;
diff --git a/firestore/src/main/local_cache_settings_main.h b/firestore/src/main/local_cache_settings_main.h
new file mode 100644
index 0000000000..7d23ad5068
--- /dev/null
+++ b/firestore/src/main/local_cache_settings_main.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed 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.
+ */
+
+#ifndef FIREBASE_FIRESTORE_SRC_MAIN_LOCAL_CACHE_SETTINGS_MAIN_H_
+#define FIREBASE_FIRESTORE_SRC_MAIN_LOCAL_CACHE_SETTINGS_MAIN_H_
+
+#include <cstdint>
+#include <utility>
+
+#include "Firestore/core/src/api/settings.h"
+#include "firebase/firestore/local_cache_settings.h"
+
+namespace firebase {
+namespace firestore {
+
+class LocalCacheSettingsInternal {
+ public:
+  friend bool operator==(const LocalCacheSettingsInternal& lhs,
+                         const LocalCacheSettingsInternal& rhs) {
+    return &lhs == &rhs || lhs.core_settings() == rhs.core_settings();
+  }
+
+  virtual const api::LocalCacheSettings& core_settings() const = 0;
+};
+
+class PersistentCacheSettingsInternal final
+    : public LocalCacheSettingsInternal {
+ public:
+  explicit PersistentCacheSettingsInternal() = default;
+
+  friend bool operator==(const PersistentCacheSettingsInternal& lhs,
+                         const PersistentCacheSettingsInternal& rhs) {
+    return &lhs == &rhs || lhs.settings_ == rhs.settings_;
+  }
+
+  PersistentCacheSettingsInternal WithSizeBytes(int64_t size) {
+    PersistentCacheSettingsInternal result;
+    result.set_core_settings(this->core_settings().WithSizeBytes(size));
+    return result;
+  }
+
+  int64_t size_bytes() const { return settings_.size_bytes(); }
+
+  const api::PersistentCacheSettings& core_settings() const override {
+    return settings_;
+  }
+  void set_core_settings(const api::PersistentCacheSettings& settings) {
+    settings_ = settings;
+  }
+
+ private:
+  api::PersistentCacheSettings settings_;
+};
+
+class MemoryGarbageCollectorSettingsInternal {
+ public:
+  friend bool operator==(const MemoryGarbageCollectorSettingsInternal& lhs,
+                         const MemoryGarbageCollectorSettingsInternal& rhs) {
+    return &lhs == &rhs || lhs.core_settings() == rhs.core_settings();
+  }
+
+  virtual const api::MemoryGargabeCollectorSettings& core_settings() const = 0;
+};
+
+class MemoryEagerGCSettingsInternal final
+    : public MemoryGarbageCollectorSettingsInternal {
+ public:
+  explicit MemoryEagerGCSettingsInternal() = default;
+
+  friend bool operator==(const MemoryEagerGCSettingsInternal& lhs,
+                         const MemoryEagerGCSettingsInternal& rhs) {
+    return &lhs == &rhs || lhs.settings_ == rhs.settings_;
+  }
+
+  const api::MemoryEagerGcSettings& core_settings() const override {
+    return settings_;
+  }
+  void set_core_settings(const api::MemoryEagerGcSettings& settings) {
+    settings_ = settings;
+  }
+
+ private:
+  api::MemoryEagerGcSettings settings_;
+};
+
+class MemoryLruGCSettingsInternal final
+    : public MemoryGarbageCollectorSettingsInternal {
+ public:
+  explicit MemoryLruGCSettingsInternal() = default;
+
+  friend bool operator==(const MemoryLruGCSettingsInternal& lhs,
+                         const MemoryLruGCSettingsInternal& rhs) {
+    return &lhs == &rhs || lhs.settings_ == rhs.settings_;
+  }
+
+  MemoryLruGCSettingsInternal WithSizeBytes(int64_t size) {
+    MemoryLruGCSettingsInternal result;
+    result.set_core_settings(this->core_settings().WithSizeBytes(size));
+    return result;
+  }
+
+  int64_t size_bytes() const { return settings_.size_bytes(); }
+
+  const api::MemoryLruGcSettings& core_settings() const override {
+    return settings_;
+  }
+  void set_core_settings(const api::MemoryLruGcSettings& settings) {
+    settings_ = settings;
+  }
+
+ private:
+  api::MemoryLruGcSettings settings_;
+};
+
+class MemoryCacheSettingsInternal final : public LocalCacheSettingsInternal {
+ public:
+  explicit MemoryCacheSettingsInternal() = default;
+
+  friend bool operator==(const MemoryCacheSettingsInternal& lhs,
+                         const MemoryCacheSettingsInternal& rhs) {
+    return &lhs == &rhs || lhs.settings_ == rhs.settings_;
+  }
+
+  MemoryCacheSettingsInternal WithGarbageCollectorSettings(
+      const MemoryGarbageCollectorSettings& gc_settings) {
+    return MemoryCacheSettingsInternal(
+        api::MemoryCacheSettings().WithMemoryGarbageCollectorSettings(
+            gc_settings.internal().core_settings()));
+  }
+
+  const api::MemoryCacheSettings& core_settings() const override {
+    return settings_;
+  }
+
+ private:
+  explicit MemoryCacheSettingsInternal(const api::MemoryCacheSettings& settings)
+      : settings_(settings) {}
+  api::MemoryCacheSettings settings_;
+};
+
+inline bool operator!=(const MemoryCacheSettingsInternal& lhs,
+                       const MemoryCacheSettingsInternal& rhs) {
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(const MemoryLruGCSettingsInternal& lhs,
+                       const MemoryLruGCSettingsInternal& rhs) {
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(const MemoryEagerGCSettingsInternal& lhs,
+                       const MemoryEagerGCSettingsInternal& rhs) {
+  return !(lhs == rhs);
+}
+
+inline bool operator!=(const PersistentCacheSettingsInternal& lhs,
+                       const PersistentCacheSettingsInternal& rhs) {
+  return !(lhs == rhs);
+}
+
+}  // namespace firestore
+}  // namespace firebase
+
+#endif  // FIREBASE_FIRESTORE_SRC_MAIN_LOCAL_CACHE_SETTINGS_MAIN_H_