Skip to content

Race condition in FeatureSegment priority assignment allows duplicate priorities #6858

@khvn26

Description

@khvn26

Concurrent POST /environments/{env_key}/features/{feature_id}/create-segment-override/ requests for the same feature+environment can produce FeatureSegment rows with duplicate priority values.

Root cause

FeatureSegment inherits from ordered_model.OrderedModelBase. On save(), if priority is None, it calls get_next_order() which does max(priority) + 1 scoped to (feature, environment, environment_feature_version).

This read-then-write is not atomic — when two requests arrive concurrently, both can read the same max(priority) and assign the same value.

Impact

Duplicate priorities break the contract that segment override priority is a total order. Downstream consumers (e.g. the flag engine evaluator) use strict < to pick the winning segment override when priorities tie, making the result depend on iteration order rather than intentional priority.

Reproduction

Call create-segment-override concurrently for 3 different segments on the same feature+environment (e.g. with 32 parallel workers). Observe that two or more FeatureSegment rows end up with priority=0.

Suggested fix

Either:

  1. Use select_for_update() / row-level locking around the get_next_order() + save() sequence, or
  2. Add a unique constraint on (feature, environment, environment_feature_version, priority) and retry on conflict.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiIssue related to the REST API

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions