diff --git a/src/main/java/io/split/android/client/AlwaysReturnControlSplitClient.java b/src/main/java/io/split/android/client/AlwaysReturnControlSplitClient.java
index 59a8ddca4..2275622fb 100644
--- a/src/main/java/io/split/android/client/AlwaysReturnControlSplitClient.java
+++ b/src/main/java/io/split/android/client/AlwaysReturnControlSplitClient.java
@@ -17,7 +17,7 @@
  * Useful for testing
  *
  */
-public class AlwaysReturnControlSplitClient implements io.split.android.client.SplitClient {
+public class AlwaysReturnControlSplitClient implements SplitClient {
 
     @Override
     public String getTreatment(String featureFlagName) {
@@ -62,22 +62,22 @@ public SplitResult getTreatmentWithConfig(String featureFlagName, Map<String, Ob
 
     @Override
     public Map<String, String> getTreatmentsByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes) {
-        return Collections.emptyMap(); //TODO
+        return Collections.emptyMap();
     }
 
     @Override
     public Map<String, String> getTreatmentsByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes) {
-        return Collections.emptyMap(); //TODO
+        return Collections.emptyMap();
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes) {
-        return Collections.emptyMap(); //TODO
+        return Collections.emptyMap();
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes) {
-        return Collections.emptyMap(); //TODO
+        return Collections.emptyMap();
     }
 
     @Override
diff --git a/src/main/java/io/split/android/client/SplitClientImpl.java b/src/main/java/io/split/android/client/SplitClientImpl.java
index 08bbabd76..9ab93ad7c 100644
--- a/src/main/java/io/split/android/client/SplitClientImpl.java
+++ b/src/main/java/io/split/android/client/SplitClientImpl.java
@@ -190,38 +190,22 @@ public Map<String, SplitResult> getTreatmentsWithConfig(List<String> featureFlag
 
     @Override
     public Map<String, String> getTreatmentsByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes) {
-        try {
-            return Collections.emptyMap(); //TODO
-        } catch (Exception exception) {
-            return null;
-        }
+        return mTreatmentManager.getTreatmentsByFlagSet(flagSet, attributes, mIsClientDestroyed);
     }
 
     @Override
     public Map<String, String> getTreatmentsByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes) {
-        try {
-            return Collections.emptyMap(); //TODO
-        } catch (Exception exception) {
-            return null;
-        }
+        return mTreatmentManager.getTreatmentsByFlagSets(flagSets, attributes, mIsClientDestroyed);
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes) {
-        try {
-            return Collections.emptyMap(); //TODO
-        } catch (Exception exception) {
-            return null;
-        }
+        return mTreatmentManager.getTreatmentsWithConfigByFlagSet(flagSet, attributes, mIsClientDestroyed);
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes) {
-        try {
-            return Collections.emptyMap(); //TODO
-        } catch (Exception exception) {
-            return null;
-        }
+        return mTreatmentManager.getTreatmentsWithConfigByFlagSets(flagSets, attributes, mIsClientDestroyed);
     }
 
     public void on(SplitEvent event, SplitEventTask task) {
diff --git a/src/main/java/io/split/android/client/localhost/LocalhostSplitClient.java b/src/main/java/io/split/android/client/localhost/LocalhostSplitClient.java
index eeb8627d7..e82e33f16 100644
--- a/src/main/java/io/split/android/client/localhost/LocalhostSplitClient.java
+++ b/src/main/java/io/split/android/client/localhost/LocalhostSplitClient.java
@@ -6,6 +6,7 @@
 import androidx.annotation.Nullable;
 
 import java.lang.ref.WeakReference;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -46,9 +47,9 @@ public final class LocalhostSplitClient implements SplitClient {
     private final WeakReference<SplitClientContainer> mClientContainer;
     private final Key mKey;
     private final SplitEventsManager mEventsManager;
-    private final Evaluator mEvaluator;
     private final TreatmentManager mTreatmentManager;
     private boolean mIsClientDestroyed = false;
+    private final SplitsStorage mSplitsStorage;
 
     public LocalhostSplitClient(@NonNull LocalhostSplitFactory container,
                                 @NonNull SplitClientContainer clientContainer,
@@ -66,9 +67,9 @@ public LocalhostSplitClient(@NonNull LocalhostSplitFactory container,
         mClientContainer = new WeakReference<>(checkNotNull(clientContainer));
         mKey = checkNotNull(key);
         mEventsManager = checkNotNull(eventsManager);
-        mEvaluator = new EvaluatorImpl(splitsStorage, splitParser);
+        mSplitsStorage = splitsStorage;
         mTreatmentManager = new TreatmentManagerImpl(mKey.matchingKey(), mKey.bucketingKey(),
-                mEvaluator, new KeyValidatorImpl(),
+                new EvaluatorImpl(splitsStorage, splitParser), new KeyValidatorImpl(),
                 new SplitValidatorImpl(), getImpressionsListener(splitClientConfig),
                 splitClientConfig.labelsEnabled(), eventsManager, attributesManager, attributesMerger,
                 telemetryStorageProducer, configuredFlagSets, splitsStorage);
@@ -143,22 +144,70 @@ public Map<String, SplitResult> getTreatmentsWithConfig(List<String> featureFlag
 
     @Override
     public Map<String, String> getTreatmentsByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes) {
-        return null;
+        try {
+            return mTreatmentManager.getTreatmentsByFlagSet(flagSet, attributes, mIsClientDestroyed);
+        } catch (Exception exception) {
+            Logger.e(exception);
+
+            Map<String, String> result = new HashMap<>();
+            Set<String> namesByFlagSets = mSplitsStorage.getNamesByFlagSets(Collections.singletonList(flagSet));
+            for (String featureFlagName : namesByFlagSets) {
+                result.put(featureFlagName, Treatments.CONTROL);
+            }
+
+            return result;
+        }
     }
 
     @Override
     public Map<String, String> getTreatmentsByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes) {
-        return null;
+        try {
+            return mTreatmentManager.getTreatmentsByFlagSets(flagSets, attributes, mIsClientDestroyed);
+        } catch (Exception exception) {
+            Logger.e(exception);
+
+            Map<String, String> result = new HashMap<>();
+            Set<String> namesByFlagSets = mSplitsStorage.getNamesByFlagSets(flagSets);
+            for (String featureFlagName : namesByFlagSets) {
+                result.put(featureFlagName, Treatments.CONTROL);
+            }
+
+            return result;
+        }
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes) {
-        return null;
+        try {
+            return mTreatmentManager.getTreatmentsWithConfigByFlagSet(flagSet, attributes, mIsClientDestroyed);
+        } catch (Exception exception) {
+            Logger.e(exception);
+
+            Map<String, SplitResult> result = new HashMap<>();
+            Set<String> namesByFlagSets = mSplitsStorage.getNamesByFlagSets(Collections.singletonList(flagSet));
+            for (String featureFlagName : namesByFlagSets) {
+                result.put(featureFlagName, new SplitResult(Treatments.CONTROL));
+            }
+
+            return result;
+        }
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes) {
-        return null;
+        try {
+            return mTreatmentManager.getTreatmentsWithConfigByFlagSets(flagSets, attributes, mIsClientDestroyed);
+        } catch (Exception exception) {
+            Logger.e(exception);
+
+            Map<String, SplitResult> result = new HashMap<>();
+            Set<String> namesByFlagSets = mSplitsStorage.getNamesByFlagSets(flagSets);
+            for (String featureFlagName : namesByFlagSets) {
+                result.put(featureFlagName, new SplitResult(Treatments.CONTROL));
+            }
+
+            return result;
+        }
     }
 
     @Override
diff --git a/src/main/java/io/split/android/client/validators/TreatmentManagerImpl.java b/src/main/java/io/split/android/client/validators/TreatmentManagerImpl.java
index 8aa242ebd..c45f553d5 100644
--- a/src/main/java/io/split/android/client/validators/TreatmentManagerImpl.java
+++ b/src/main/java/io/split/android/client/validators/TreatmentManagerImpl.java
@@ -183,68 +183,100 @@ public Map<String, SplitResult> getTreatmentsWithConfig(List<String> splits, Map
     @Override
     public Map<String, String> getTreatmentsByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes, boolean isClientDestroyed) {
         String validationTag = ValidationTag.GET_TREATMENTS_BY_FLAG_SET;
-        Set<String> names = getNamesFromSet(validationTag, Collections.singletonList(flagSet));
-        if (isClientDestroyed) {
-            mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
-            return controlTreatmentsForSplits(new ArrayList<>(names), validationTag);
-        }
-
-        long start = System.currentTimeMillis();
+        Set<String> names = new HashSet<>();
         try {
-            return evaluateFeatures(names, attributes, validationTag, SplitResult::treatment);
-        } finally {
-            recordLatency(Method.TREATMENTS_BY_FLAG_SET, start);
+            names = getNamesFromSet(validationTag, Collections.singletonList(flagSet));
+            if (isClientDestroyed) {
+                mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
+                return controlTreatmentsForSplits(new ArrayList<>(names), validationTag);
+            }
+
+            long start = System.currentTimeMillis();
+            try {
+                return evaluateFeatures(names, attributes, validationTag, SplitResult::treatment);
+            } finally {
+                recordLatency(Method.TREATMENTS_BY_FLAG_SET, start);
+            }
+        } catch (Exception exception) {
+            Logger.e("Client getTreatmentsByFlagSet exception", exception);
+            mTelemetryStorageProducer.recordException(Method.TREATMENTS_BY_FLAG_SET);
+
+            return controlTreatmentsForSplits(new ArrayList<>(names), validationTag);
         }
     }
 
     @Override
     public Map<String, String> getTreatmentsByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes, boolean isClientDestroyed) {
         String validationTag = ValidationTag.GET_TREATMENTS_BY_FLAG_SETS;
-        Set<String> names = getNamesFromSet(validationTag, flagSets);
-        if (isClientDestroyed) {
-            mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
-            return controlTreatmentsForSplits(new ArrayList<>(names), validationTag);
-        }
-
-        long start = System.currentTimeMillis();
+        Set<String> names = new HashSet<>();
         try {
-            return evaluateFeatures(names, attributes, validationTag, SplitResult::treatment);
-        } finally {
-            recordLatency(Method.TREATMENTS_BY_FLAG_SETS, start);
+            names = getNamesFromSet(validationTag, flagSets);
+            if (isClientDestroyed) {
+                mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
+                return controlTreatmentsForSplits(new ArrayList<>(names), validationTag);
+            }
+
+            long start = System.currentTimeMillis();
+            try {
+                return evaluateFeatures(names, attributes, validationTag, SplitResult::treatment);
+            } finally {
+                recordLatency(Method.TREATMENTS_BY_FLAG_SETS, start);
+            }
+        } catch (Exception exception) {
+            Logger.e("Client getTreatmentsByFlagSets exception", exception);
+            mTelemetryStorageProducer.recordException(Method.TREATMENTS_BY_FLAG_SETS);
+
+            return controlTreatmentsForSplits(new ArrayList<>(names), validationTag);
         }
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSet(@NonNull String flagSet, @Nullable Map<String, Object> attributes, boolean isClientDestroyed) {
         String validationTag = ValidationTag.GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SET;
-        Set<String> names = getNamesFromSet(validationTag, Collections.singletonList(flagSet));
-        if (isClientDestroyed) {
-            mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
-            return controlTreatmentsForSplitsWithConfig(new ArrayList<>(names), validationTag);
-        }
-
-        long start = System.currentTimeMillis();
+        Set<String> names = new HashSet<>();
         try {
-            return evaluateFeatures(names, attributes, validationTag, ResultTransformer::identity);
-        } finally {
-            recordLatency(Method.TREATMENTS_WITH_CONFIG_BY_FLAG_SET, start);
+            names = getNamesFromSet(validationTag, Collections.singletonList(flagSet));
+            if (isClientDestroyed) {
+                mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
+                return controlTreatmentsForSplitsWithConfig(new ArrayList<>(names), validationTag);
+            }
+
+            long start = System.currentTimeMillis();
+            try {
+                return evaluateFeatures(names, attributes, validationTag, ResultTransformer::identity);
+            } finally {
+                recordLatency(Method.TREATMENTS_WITH_CONFIG_BY_FLAG_SET, start);
+            }
+        } catch (Exception exception) {
+            Logger.e("Client getTreatmentsWithConfigByFlagSet exception", exception);
+            mTelemetryStorageProducer.recordException(Method.TREATMENTS_WITH_CONFIG_BY_FLAG_SET);
+
+            return controlTreatmentsForSplitsWithConfig(new ArrayList<>(names), validationTag);
         }
     }
 
     @Override
     public Map<String, SplitResult> getTreatmentsWithConfigByFlagSets(@NonNull List<String> flagSets, @Nullable Map<String, Object> attributes, boolean isClientDestroyed) {
         String validationTag = ValidationTag.GET_TREATMENTS_WITH_CONFIG_BY_FLAG_SETS;
-        Set<String> names = getNamesFromSet(validationTag, flagSets);
-        if (isClientDestroyed) {
-            mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
-            return controlTreatmentsForSplitsWithConfig(new ArrayList<>(names), validationTag);
-        }
-
-        long start = System.currentTimeMillis();
+        Set<String> names = new HashSet<>();
         try {
-            return evaluateFeatures(names, attributes, validationTag, ResultTransformer::identity);
-        } finally {
-            recordLatency(Method.TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, start);
+            names = getNamesFromSet(validationTag, flagSets);
+            if (isClientDestroyed) {
+                mValidationLogger.e(CLIENT_DESTROYED_MESSAGE, validationTag);
+                return controlTreatmentsForSplitsWithConfig(new ArrayList<>(names), validationTag);
+            }
+
+            long start = System.currentTimeMillis();
+            try {
+                return evaluateFeatures(names, attributes, validationTag, ResultTransformer::identity);
+            } finally {
+                recordLatency(Method.TREATMENTS_WITH_CONFIG_BY_FLAG_SETS, start);
+            }
+        } catch (Exception exception) {
+            Logger.e("Client getTreatmentsWithConfigByFlagSets exception", exception);
+            mTelemetryStorageProducer.recordException(Method.TREATMENTS_WITH_CONFIG_BY_FLAG_SETS);
+
+            return controlTreatmentsForSplitsWithConfig(new ArrayList<>(names), validationTag);
         }
     }