diff --git a/optimizely/decision_service.py b/optimizely/decision_service.py index 28275ef..fcbf131 100644 --- a/optimizely/decision_service.py +++ b/optimizely/decision_service.py @@ -457,7 +457,13 @@ def get_variation( } # Check to see if user has a decision available for the given experiment - if user_profile_tracker is not None and not ignore_user_profile: + # CMAB experiments are excluded from UPS because CMAB's dynamic nature + # is incompatible with sticky bucketing (UPS doesn't consider TTL or user attributes). + if experiment.cmab: + message = f'Skipping user profile service for CMAB experiment "{experiment.key}".' + self.logger.info(message) + decide_reasons.append(message) + elif user_profile_tracker is not None and not ignore_user_profile: variation = self.get_stored_variation(project_config, experiment, user_profile_tracker.get_user_profile()) if variation: message = f'Returning previously activated variation ID "{variation}" of experiment ' \ @@ -529,7 +535,8 @@ def get_variation( self.logger.info(message) decide_reasons.append(message) # Store this new decision and return the variation for the user - if user_profile_tracker is not None and not ignore_user_profile: + # CMAB experiments are excluded from UPS to preserve dynamic bucketing behavior. + if user_profile_tracker is not None and not ignore_user_profile and not experiment.cmab: try: user_profile_tracker.update_user_profile(experiment, variation) except: