> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.getunleash.io/guides/how-to-schedule-feature-releases/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getunleash.io/_mcp/server. # Schedule feature releases > Learn how to schedule feature releases in Unleash using strategy constraints for product launches, contests, and limited-time events. v4.16 There's a whole host of reasons why you may want to schedule the release of a feature, such as: * **to release a feature at a specific date and time** (for a product launch, for instance) * **to make a feature available only up until a specific moment** (for a contest cutoff, for instance) * **to make a feature available during a limited period** (for a 24 hour flash sale, for instance) In this guide we'll schedule a feature for release at some point in time. The exact same logic applies if you want to make a feature available until some point in the future. Finally, if you want to only make a feature available during a limited time period, you can easily combine the two options. ## Prerequisites This guide assumes that you've got the following: * some basic experience with Unleash * a running instance of Unleash and connected clients (where applicable) * an existing feature flag that you want to schedule the release for ## Schedule feature releases with strategy constraints [Strategy constraints](/concepts/activation-strategies#date-and-time-operators) are the easiest way to schedule feature releases ([as long as your SDKs are up to date](/concepts/activation-strategies#client-side-implementation)). You can use this approach with *any* strategy you want. The strategies will work just as they normally do, they just won't become active until the specified time. For example: with the standard strategy, the feature would become available to all your users at the specified time; with a gradual rollout, the rollout would start at the specified time. ### Step 1: Add an activation strategy with a date-based constraint #### Scheduling a release via the UI To schedule a feature release via the UI: 1. Add the desired activation strategy to the feature 2. Open the constraint creator by using the "Add constraint" button 3. Add a date-based constraint by selecting the `currentTime` context field (step 1 in the below image), choosing the `DATE_AFTER` operator (step 2), and setting the point in time where you want the feature to be available from (step 3) ![A strategy constraint specifying that the activation strategy should be enabled at 12:00 AM, November 25th 2022. There are visual call-outs pointing to the relevant settings mentioned above.](/_fern-img/9c2b97b82d9050fc048b31de7e4835a2eeebc60e0e6aa8f4f28c617d9bbe46e9.webp) #### Scheduling a release via the API To add an activation strategy via the Admin API, use the feature's `strategies` endpoint to add a new strategy (see the API documentation for adding strategies to feature flags for more details): ### Request POST [https://app.unleash-instance.example.com/api/admin/projects/\{projectId}/features/\{featureName}/environments/\{environment}/strategies](https://app.unleash-instance.example.com/api/admin/projects/\{projectId}/features/\{featureName}/environments/\{environment}/strategies) ```curl curl -X POST https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies \ -H "Authorization: " \ -H "Content-Type: application/json" \ -d '{ "name": "flexibleRollout" }' ``` ```python import requests url = "https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies" payload = { "name": "flexibleRollout" } headers = { "Authorization": "", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies'; const options = { method: 'POST', headers: {Authorization: '', 'Content-Type': 'application/json'}, body: '{"name":"flexibleRollout"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies" payload := strings.NewReader("{\n \"name\": \"flexibleRollout\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Authorization"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"flexibleRollout\"\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies") .header("Authorization", "") .header("Content-Type", "application/json") .body("{\n \"name\": \"flexibleRollout\"\n}") .asString(); ``` ```php request('POST', 'https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies', [ 'body' => '{ "name": "flexibleRollout" }', 'headers' => [ 'Authorization' => '', 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies"); var request = new RestRequest(Method.POST); request.AddHeader("Authorization", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"name\": \"flexibleRollout\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "Authorization": "", "Content-Type": "application/json" ] let parameters = ["name": "flexibleRollout"] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://app.unleash-instance.example.com/api/admin/projects/projectId/features/featureName/environments/environment/strategies")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` The payload's `"name"` property should contain the name of the strategy to apply (see [activation strategies reference documentation](/concepts/activation-strategies) for all built-in strategies' *modeling names*). The `"constraint"` object should have the same format as described in the code sample below. The activation date must be in an [RFC 3339-compatible format](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8), e.g. `"1990-12-31T23:59:60Z"`. **`Add a feature activation strategy with a scheduled activation time`** ```http title="Add a feature activation strategy with a scheduled activation time" POST api/admin/projects//features/environments//strategies { "name": "default", "constraints": [ { "value": "", "operator": "DATE_AFTER", "contextName": "currentTime" } ] } ``` The `"operator"` property in the code sample can be replaced with [any of the other date and time-based operators](/concepts/activation-strategies#date-and-time-operators) according to your needs. ## Limitations and alternatives Date and time constraints define one-time windows. Unleash evaluates them against the `currentTime` [context field](/concepts/unleash-context), which holds a complete timestamp and defaults to the time of evaluation. For example, you can: * Release a feature at a specific date and time with a `DATE_AFTER` constraint. * Make a feature available during one limited period by combining a `DATE_AFTER` and a `DATE_BEFORE` constraint in the same strategy. * Cover several distinct periods by adding one strategy per period, each with its own pair of date constraints; the flag activates if any strategy matches. Recurring schedules cannot be expressed with date constraints, because the date and time operators compare complete timestamps rather than parts of them. This includes rules such as every day between 09:00 and 17:00, on weekdays only, or during the same week every year. To implement a recurring schedule, use an external scheduler that updates the flag through the Admin API, or define a [custom context field](/concepts/unleash-context#custom-context-fields), such as `hourOfDay` or `dayOfWeek`, that your application sets and your strategy constrains on. As an alternative to date constraints, you can use [scheduled change requests](/concepts/change-requests#scheduled-change-requests) to apply any flag change at a specific point in time. For multi-phase releases, [release templates](/concepts/release-templates) let you predefine each phase of a rollout as a milestone and move through the phases without reconfiguring strategies by hand. ## Frequently asked questions #### Can I schedule a recurring release? Date constraints define one-time windows. To implement a recurring schedule, such as making a feature available every day between 09:00 and 17:00 or only on weekdays, use an external scheduler that updates the flag through the Admin API, or a [custom context field](/concepts/unleash-context#custom-context-fields), such as `hourOfDay` or `dayOfWeek`, that your application sets and your strategy constrains on. See [Limitations and alternatives](#limitations-and-alternatives). #### What time zone do date constraints use? Date constraint values are absolute points in time, stored in [RFC 3339 format](https://datatracker.ietf.org/doc/html/rfc3339#section-5.8) with a time zone offset. Unleash compares the value against the `currentTime` context field as absolute times, so the result does not depend on the time zone of the Unleash server or of the application evaluating the flag. #### Can I schedule a feature to turn off? Yes. Use a `DATE_BEFORE` constraint to keep a strategy active only until a specific time, or use a [scheduled change request](/concepts/change-requests#scheduled-change-requests) to disable the flag at a specific time. #### Can I schedule changes other than enabling a feature? Yes. [Scheduled change requests](/concepts/change-requests#scheduled-change-requests) can apply any flag configuration change at a scheduled time, such as updating a strategy or archiving a flag. > Learn how to schedule feature releases in Unleash using strategy constraints for product launches, contests, and limited-time events.