Flagsmith / Flagsmith/flagsmith
Expose upcoming scheduled changes in the environment document, so local-evaluation SDKs can flip flags exactly at live_from
- Dominant language
- Python
- Stars
- 6.6k
- Forks
- 567
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 124
Description
### Is your feature request related to a problem?
When a change is scheduled via a future `live_from`, Flagsmith's server correctly promotes it to the "live" value once that time passes — but SDKs running in **local evaluation mode** (fetch the environment document once, cache it, evaluate flags in-process for low latency) only see that promotion on their *next document poll strictly after* `live_from`. With the default/typical refresh intervals many teams configure (often well beyond the default 60s to reduce API load), this means the actual observed flip time is `live_from + up to one full refresh interval`, and there's no way for the SDK to know in advance that a change is coming. The only current workarounds are polling much more frequently around the scheduled time (which the SDK can't do, since it doesn't know a schedule exists) or falling back to remote evaluation for that flag (which defeats the purpose of local evaluation).
### Describe the solution you'd like
Add an opt-in query parameter (e.g. `include_scheduled=true`) to the environment document endpoint that, when present, attaches the *single nearest* not-yet-live future value to each affected feature state: `scheduled_change: { live_from, enabled, feature_state_value }`. Local-evaluation SDKs can then cheaply compare `now()` against the cached `live_from` on every flag-resolution call and start serving the scheduled value once it's reached — without waiting for or requiring a new document fetch. The field is omitted entirely when not requested, so existing SDKs and cached documents stay byte-for-byte unaffected (fully backward compatible, opt-in only).
We've prototyped this end-to-end: a server-side mapper change that merges scheduling information from both direct future `FeatureState`/version rows and pending scheduled change-sets (with an "earliest wins" rule when more than one candidate exists), plus a client-side implementation in `flagsmith-java-client` (a small model class with an `isLive()` check, applied at every flag-resolution entry point) and a corresponding option in the OpenFeature Java provider. In testing, a flag scheduled ~45s in the future correctly stayed at its old value right up to `live_from`, then flipped at `live_from` on an already-running client with zero new document fetches (refresh interval set far longer than the test window to isolate this from ordinary polling).
**A notable side benefit**: because every instance in a fleet independently prefetches the *same* `scheduled_change` (via its normal, already-staggered polling), and each one resolves maturity locally from its own clock rather than from *when it happened to poll*, all instances flip to the new value at essentially the same moment — bounded only by clock skew across the fleet, not by how staggered their poll timings are. Without this mechanism, instances that poll on independent/staggered schedules would pick up a promoted value at different times (each up to one refresh interval after `live_from`, and out of sync with each other by up to that same interval). This gives multi-instance deployments millisecond-level synchronized flag flips "for free," without needing a dedicated distributed-coordination mechanism (leader election, distributed lock, message bus, etc.) just to make a scheduled change take effect consistently across a fleet at the same instant.
### Describe alternatives you've considered
- *Poll more frequently as the scheduled time approaches* — requires the SDK to already know a change is coming, which is the problem being solved, and increases load if applied broadly rather than narrowly.
- *Push-based invalidation (webhook/SSE telling clients to refetch)* — heavier infrastructure requirement, and most server-side SDKs in local-evaluation mode don't have an inbound channel to receive it; also doesn't remove the "refetch round trip" latency itself.
- *Rely on remote evaluation for anything scheduled* — works, but forces giving up local evaluation's low-latency, no-per-request-round-trip benefit specifically for flags that use scheduling.
### Additional context
Known simplification in the prototype: only the single nearest upcoming change per feature state is exposed, not a full list of all pending future changes — intentional, since in Flagsmith's version-chain model only one transition is ever actionable at a time (the next one becomes visible on the following poll once the current one matures). Willing to share more implementation detail or open a draft PR to `flagsmith-java-client` (and discuss the OpenFeature provider separately) once maintainers confirm interest in the server-side API shape.
Contributor guide
Research direction
Start at the environment document endpoint and trace the server-side mapper that assembles feature states. Read how direct future FeatureState/version rows and pending scheduled change-sets are represented, then inspect related endpoint tests if present. Done means the opt-in response exposes only the nearest future change per affected feature state while preserving the existing response when the parameter is absent.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100