Deploy feature flags
This quickstart shows you how to create, rollout and use feature flags with App Lifecycle Manager.
In this quickstart, you'll learn how to install and configure a flag provider, and perform basic feature flagging using App Lifecycle Manager feature flags.
Before you begin
-
Sign in to your Google Account.
If you don't already have one, sign up for a new account.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the App Lifecycle Manager, Artifact Registry, Infrastructure Manager, Developer Connect, Cloud Build, Cloud Storage, Cloud Run and SaaS Config APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.-
Create a service account:
-
Ensure that you have the Create Service Accounts IAM role
(
roles/iam.serviceAccountCreator) and the Project IAM Admin role (roles/resourcemanager.projectIamAdmin). Learn how to grant roles. -
In the Google Cloud console, go to the Create service account page.
Go to Create service account - Select your project.
-
In the Service account name field, enter a name. The Google Cloud console fills in the Service account ID field based on this name.
In the Service account description field, enter a description. For example,
Service account for quickstart. - Click Create and continue.
-
Grant the Project > Owner role to the service account.
To grant the role, find the Select a role list, then select Project > Owner.
- Click Continue.
-
Click Done to finish creating the service account.
-
Ensure that you have the Create Service Accounts IAM role
(
-
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init -
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the App Lifecycle Manager, Artifact Registry, Infrastructure Manager, Developer Connect, Cloud Build, Cloud Storage, Cloud Run and SaaS Config APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.-
Create a service account:
-
Ensure that you have the Create Service Accounts IAM role
(
roles/iam.serviceAccountCreator) and the Project IAM Admin role (roles/resourcemanager.projectIamAdmin). Learn how to grant roles. -
In the Google Cloud console, go to the Create service account page.
Go to Create service account - Select your project.
-
In the Service account name field, enter a name. The Google Cloud console fills in the Service account ID field based on this name.
In the Service account description field, enter a description. For example,
Service account for quickstart. - Click Create and continue.
-
Grant the Project > Owner role to the service account.
To grant the role, find the Select a role list, then select Project > Owner.
- Click Continue.
-
Click Done to finish creating the service account.
-
Ensure that you have the Create Service Accounts IAM role
(
-
Install the Google Cloud CLI.
-
If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.
-
To initialize the gcloud CLI, run the following command:
gcloud init - Create a SaaS offering. You need a SaaS offering to complete this quickstart. For more information about how to create a SaaS offering, see Create a SaaS offering.
Grant permissions to App Lifecycle Manager service account
When you enable the App Lifecycle Manager API, App Lifecycle Manager creates a service
account. This service account is called
service-PROJECT-NUMBER@gcp-sa-saasservicemgmt.iam.gserviceaccount.com,
where PROJECT-NUMBER is your project number.
Grant this service account required permissions by running the following command:
gcloud projects add-iam-policy-binding `PROJECT_ID` \
--member="serviceAccount:service-<var>`PROJECT_NUMBER`</var>@gcp-sa-saasservicemgmt.iam.gserviceaccount.com" \
--role="roles/saasservicemgmt.serviceAgent"
Replace:
- PROJECT_ID: A string identifier representing your project ID.
- PROJECT_NUMBER: Your project number.
Locating reference documentation
This service account acts on your behalf for various tasks like provisioning units.
Create a repository in Artifact Registry
To use App Lifecycle Manager, you need a repository in Artifact Registry. To create this repository, run the following command in your terminal:
gcloud artifacts repositories create flags-quickstart \
--repository-format=docker \
--location=us-central1
This repository will contain a blueprint (packaged Terraform files) describing how to provision your units.
Create a feature flagging application blueprint
Create a Python script that reads a feature flag and use it to build and push a Docker image:
Create a directory named
alm_dockerfor your Docker build context.In the
alm_dockerdirectory, create the fileflags.pywith the this snippet:import google.auth.transport.grpc import google.auth.transport.requests import grpc import logging import time import os import sys from flask import Flask, jsonify from openfeature import api from openfeature.provider import ProviderEvent, ProviderStatus from openfeature.contrib.provider.flagd import FlagdProvider from openfeature.contrib.provider.flagd.config import ResolverType # --- Flask App Setup --- app = Flask(__name__) # --- Logging Setup --- logging.basicConfig(stream=sys.stdout) # Log to stdout for Cloud Run log = logging.getLogger(__name__) log.setLevel(logging.INFO) # Use INFO or DEBUG as needed # --- OpenFeature/Flagd Setup --- FLAG_KEY = "quickstart-flag" DEFAULT_FLAG_VALUE = False # Check for necessary environment variable provider_id = os.environ.get("FLAGD_SOURCE_PROVIDER_ID") if not provider_id: log.critical("FATAL: FLAGD_SOURCE_PROVIDER_ID environment variable not set.") sys.exit("FLAGD_SOURCE_PROVIDER_ID not set") # Exit if critical config is missing log.info(f"Initializing OpenFeature provider for ID: {provider_id}") def add_x_goog_request_params_header(config_name): return lambda context, callback: callback([("x-goog-request-params", f'name={config_name}')], None) try: # Configure gRPC credentials for Google Cloud service configservice_credentials = grpc.composite_channel_credentials( grpc.ssl_channel_credentials(), grpc.metadata_call_credentials( google.auth.transport.grpc.AuthMetadataPlugin( google.auth.default()[0], # Get just the credentials from the tuple google.auth.transport.requests.Request() ) ), grpc.metadata_call_credentials( add_x_goog_request_params_header(provider_id) ) ) # Set up the Flagd provider to connect to SaaS Config service # Using IN_PROCESS resolver type as recommended for direct gRPC connection provider = FlagdProvider( resolver_type=ResolverType.IN_PROCESS, host="saasconfig.googleapis.com", port=443, sync_metadata_disabled=True, # Important when using IN_PROCESS with direct service provider_id=provider_id, channel_credentials=configservice_credentials ) api.set_provider(provider) client = api.get_client() initial_flag_value = client.get_boolean_value(FLAG_KEY, DEFAULT_FLAG_VALUE) log.info(f"***** STARTUP FLAG CHECK ***** Flag '{FLAG_KEY}' evaluated to: {initial_flag_value}") except Exception as e: log.critical(f"FATAL: Failed to initialize OpenFeature provider: {e}", exc_info=True) # Depending on the desired behavior, you might exit or let Flask start # but log the critical failure. Exiting might be safer in production. sys.exit(f"Provider initialization failed: {e}") # --- Flask Routes --- @app.route('/') def home(): """Endpoint to check the feature flag's value.""" log.info(f"Request received for flag: {FLAG_KEY}") try: # Get the flag value. Use the client initialized earlier. # The default value (DEFAULT_FLAG_VALUE) is returned if the flag isn't found # or if the provider isn't ready/errors occur during evaluation. flag_value = client.get_boolean_value(FLAG_KEY, DEFAULT_FLAG_VALUE) log.info(f"Evaluated flag '{FLAG_KEY}': {flag_value}") return jsonify({ "flag_key": FLAG_KEY, "value": flag_value, }) except Exception as e: log.error(f"Error evaluating flag '{FLAG_KEY}': {e}", exc_info=True) # Return an error response but keep the server running return jsonify({ "error": f"Failed to evaluate flag {FLAG_KEY}", "details": str(e), }), 500 if __name__ == '__main__': port = int(os.environ.get('PORT', 8080)) log.info(f"Starting Flask server on port {port}") app.run(host='0.0.0.0', port=port)This Python script demonstrates how to access feature flags within your application running as a Docker image on an App Lifecycle Manager unit. It uses standard OpenFeature principles to integrate with the App Lifecycle Manager feature flag config service (
saasconfig.googleapis.com).Create a text file named
requirements.txtin thealm_dockerdirectory that contains this snippet:google-auth grpcio>=1.49.1,<2.0.0dev openfeature-sdk==0.8.0 openfeature-provider-flagd==0.2.2 requests typing_extensions Flask>=2.0Append the
Dockerfilein thealm_dockerdirectory with:FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY flags.py . CMD ["python", "flags.py"]Run this command in your local environment to build and push the Docker image:
export DOCKER_REGISTRY="us-central1-docker.pkg.dev/PROJECT_ID/flags-quickstart" export FULL_IMAGE_PATH="${DOCKER_REGISTRY}/flags-quickstart:latest" docker build -t "${FULL_IMAGE_PATH}" . docker push "${FULL_IMAGE_PATH}"Replace:
- PROJECT_ID: A string identifier representing your project ID.
In your Docker environment, create an
alm_terraformdirectory.In
alm_terraform, create these files:main.tflocals { config_path = "projects/${var.system_unit_project}/locations/${var.system_unit_location}/featureFlagsConfigs/${var.system_unit_name}" docker_image_path = "${var.system_unit_location}-docker.pkg.dev/${var.system_unit_project}/${var.docker_repo_name}/${var.docker_tag}" } provider "google" { project = var.system_unit_project region = var.system_unit_location } resource "google_cloud_run_service" "flags_quickstart_service" { name = var.cloud_run_service_name location = var.system_unit_location project = var.system_unit_project template { spec { containers { image = local.docker_image_path env { name = "FLAGD_SOURCE_PROVIDER_ID" value = local.config_path } } service_account_name = var.actuation_sa } } }variables.tfvariable "actuation_sa" { description = "Actuation SA" type = string } variable "system_unit_project" { description = "Project id - variable set by App Lifecycle Manager" type = string } variable "system_unit_location" { description = "Location - variable set by App Lifecycle Manager" type = string } variable "system_unit_name" { description = "Unit name- variable set by App Lifecycle Manager" type = string } variable "docker_repo_name" { description = "The name of the Artifact Registry repository where the Docker image is stored." type = string default = "flags-quickstart" } variable "docker_tag" { description = "The tag of the Docker image to deploy." type = string default = "flags-quickstart:latest" } variable "cloud_run_service_name" { description = "Name for the Cloud Run service to be created." type = string default = "saas-flags-quickstart-svc" }In the
alm_terraformdirectory, run this command to package the Terraform blueprint files:zip terraform-files.zip main.tf variables.tf
Use the application blueprint to create a unit
After you've created an application blueprint that utilizes feature flags, you
need to create a App Lifecycle Manager unit kind (flags-unit-kind),
and then create a unit of this kind (flags-quickstart-unit).
For more information about units and unit kinds, see Model and package units of a deployment.
To use the application blueprint to create a unit, follow these gcloud CLI steps:
To package your Terraform configuration as an OCI image (blueprint), create a file named
Dockerfilein your Terraform directory:# syntax=docker/dockerfile:1-labs FROM scratch COPY --exclude=Dockerfile --exclude=.git --exclude=.gitignore . /Build and push
Dockerfileto your Artifact Registry repository:IMAGE_NAME="us-central1-docker.pkg.dev/PROJECT_ID/flags-quickstart/flags-quickstart-blueprint:latest" ENGINE_TYPE=inframanager ENGINE_VERSION=1.5.7 docker buildx build -t $IMAGE_NAME \ --push \ --annotation "com.easysaas.engine.type=$ENGINE_TYPE" \ --annotation "com.easysaas.engine.version=$ENGINE_VERSION" \ --provenance=false .Replace:
- PROJECT_ID: A string identifier representing your project ID.
Create
flags-unit-kindandflags-releaseresource:# Create unit kind gcloud beta app-lifecycle-manager unit-kinds create flags-unit-kind \ --project=PROJECT_ID \ --location=global \ --saas=flags-quickstart-saas-offering # Create release referencing the Blueprint image gcloud beta app-lifecycle-manager releases create flags-release \ --project=PROJECT_ID \ --location=global \ --unit-kind=flags-unit-kind \ --blueprint-package=$IMAGE_NAMEReplace:
- PROJECT_ID: A string identifier representing your project ID.
Create the
flags-quickstart-unitunit:gcloud beta app-lifecycle-manager units create flags-quickstart-unit \ --project=PROJECT_ID \ --location=us-central1 \ --unit-kind=flags-unit-kind \ --management-mode=userReplace:
- PROJECT_ID: A string identifier representing your project ID.
Create and provision a feature flag
Before a App Lifecycle Manager feature flag can be utilized by your provisioned unit, you must create the feature flag resource and initiate a rollout to propagate the configuration to the unit.
Run the commands to create and provision the quickstart-flag feature flag:
In your environment, define these variables:
export FLAG_ID="quickstart-flag" export FLAG_KEY="quickstart-flag" export SAAS_OFFERING_ID="flags-quickstart-saas-offering" export UNIT_KIND_ID="flags-unit-kind" export UNIT_ID="flags-quickstart-unit" export ROLLOUT_KIND_ID="flags-quickstart-rollout-kind" export ROLLOUT_ID="flags-quickstart-rollout"Create the feature flag resource:
gcloud beta app-lifecycle-manager flags create ${FLAG_ID} \ --project=${PROJECT_ID} \ --key=${FLAG_KEY} \ --flag-value-type=BOOL \ --location=global \ --unit-kind=${UNIT_KIND_ID}Create a revision:
export FLAG_REVISION_ID="${FLAG_ID}-rev1" gcloud beta app-lifecycle-manager flags revisions create ${FLAG_REVISION_ID} \ --project=${PROJECT_ID} \ --flag=${FLAG_ID} \ --location=globalCreate a release:
export FLAG_RELEASE_ID="${FLAG_ID}-rel1" gcloud beta app-lifecycle-manager flags releases create ${FLAG_RELEASE_ID} \ --project=${PROJECT_ID} \ --flag-revisions=${FLAG_REVISION_ID} \ --unit-kind=${UNIT_KIND_ID} \ --location=globalCreate a rollout kind:
gcloud beta app-lifecycle-manager rollout-kinds create ${ROLLOUT_KIND_ID} \ --project=${PROJECT_ID} \ --unit-kind=${UNIT_KIND_ID} \ --rollout-orchestration-strategy=Google.Cloud.Simple.AllAtOnce \ --location=globalCreate the rollout:
gcloud beta app-lifecycle-manager rollouts create ${ROLLOUT_ID} \ --project=${PROJECT_ID} \ --flag-release=${FLAG_RELEASE_ID} \ --rollout-kind=${ROLLOUT_KIND_ID} \ --location=global
You can monitor the rollout status with:
gcloud beta app-lifecycle-manager rollouts describe ${ROLLOUT_ID} --project=${PROJECT_ID} --location=global
View the flag value in your running service
After your App Lifecycle Manager unit has successfully provisioned the Cloud Run service, you can verify that your application is running and correctly evaluating the feature flag:
In Google Cloud console, go to Cloud Run:
Find the service named
saas-flags-quickstart-svcin theus-central1region. A checkmark next tosaas-flags-quickstart-svcindicates that it's running successfully.Click
saas-flags-quickstart-svcto view its details.Select the Logs tab.
In the log entries, look for a message similar to the following:
INFO:__main__:***** STARTUP FLAG CHECK ***** Flag 'quickstart-flag' evaluated to: falseThis confirms that the application started, connected to the SaaS Config service, and evaluated the
quickstart-flag.
To access the public endpoint, click the Networking tab.
- Find the public URL listed under the Endpoints section.
- Click the URL to open it in your browser, or use a tool like
curlto access it from your terminal (curl YOUR_SERVICE_URL, for example). Each time you access the URL, the service evaluates the feature flag and returns its current value in JSON format. For example:
{ "flag_key": "quickstart-flag", "value": false }
You have successfully deployed a Google Cloud service that reads a App Lifecycle Manager managed feature flag. You can experiment with changing the flag's value and creating a new rollout to see your application pick up the change.
Clean up
To avoid incurring charges to your Google Cloud account for the resources used on this page, follow these steps.
Optional: Delete the project
If you deployed the solution in a new Google Cloud project, and if you no longer the project, then delete it by completing the following steps:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- At the prompt, type the project ID, and then click Shut down.
What's next
- Try the Deploy feature flags standalone quickstart to use flags independently of App Lifecycle Manager managed deployments.
- Explore the language-specific integration guides (Python, Java, Go).
- Review the App Lifecycle Manager overview to learn more about App Lifecycle Manager.