All Products
Search
Document Center

Serverless App Engine:Use Terraform to manage SAE applications

Last Updated:Jun 25, 2026

Serverless App Engine (SAE) is an application-oriented Serverless PaaS platform. After you deploy applications to SAE, you do not need to manage or maintain clusters or servers. You can focus on designing and building your applications and deploy them on SAE. In addition to deploying applications by using the console, APIs, plug-ins, or CI/CD, you can also use Terraform to deploy SAE applications. This topic describes how to use Terraform to automatically create, create with custom configurations, and delete SAE applications.

Prerequisites

  • An Alibaba Cloud account has full permissions on all resources. If the credentials are leaked, your resources are at high risk. We recommend that you use a RAM user and create an AccessKey for it. For more information, see Create a RAM user and Create an AccessKey.

  • To manage the resources in this example, attach the following minimum-permission policy to the RAM user that runs the Terraform commands. For more information, see Manage RAM user permissions.

    This custom policy allows a RAM user to manage applications and services in SAE. The permissions include describing, creating, updating, deleting, deploying, starting, and stopping applications, and creating, updating, deleting, binding, and unbinding services.

    {
      "Version": "1",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "sae:DescribeApplications",
            "sae:DescribeApplication",
            "sae:DescribeInstances",
            "sae:DescribeInstance",
            "sae:DescribeServices",
            "sae:DescribeService"
          ],
          "Resource": "*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "sae:CreateApplication",
            "sae:UpdateApplication",
            "sae:DeleteApplication",
            "sae:DeployApplication",
            "sae:StartApplication",
            "sae:StopApplication"
          ],
          "Resource": "acs:sae:*:*:application/*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "sae:CreateService",
            "sae:UpdateService",
            "sae:DeleteService",
            "sae:BindService",
            "sae:UnbindService"
          ],
          "Resource": "acs:sae:*:*:service/*"
        }
      ]
    }
  • Prepare a Terraform runtime environment. Choose one of the following options:

    • ROS provides a managed service for Terraform. You can deploy Terraform templates directly on the ROS console. For more information, see Create a Terraform-based stack.

    • Use Terraform in Terraform Explorer: Alibaba Cloud provides an online environment to run Terraform. You can use Terraform online after you log on; no installation is required. This method is a quick, convenient, and free way to try and debug Terraform.

    • Use Terraform to quickly create resources: Terraform components are pre-installed in Alibaba Cloud Cloud Shell and credentials are configured. You can directly run Terraform commands in Cloud Shell. This method is suitable for quick and convenient access to Terraform at a low cost.

    • Install and configure Terraform on-premises: This method is suitable for scenarios where the network connection is poor or a custom development environment is required.

Resources used

  • alicloud_sae_application: Manages and creates Serverless App Engine (SAE) applications.

  • alicloud_vpc: Configures your VPC, including subnets, route tables, and security settings.

  • alicloud_vswitch: Creates subnets within a VPC. Each subnet can have its own IP address range and route table. You can use vSwitches to deploy different applications and services in different subnets.

  • alicloud_security_group: Manages network access control within a VPC.

Create an application

SAE supports deployments from images and code packages. Supported package types include JAR, WAR, and PHP ZIP packages. When you create an application, you can select one of the following methods to configure a VPC:

  • Automatic configuration: SAE automatically configures resources such as a namespace, VPC, vSwitch, and security group. The default namespace is used.

  • Custom configuration: You must configure resources for your application, such as a namespace, VPC, vSwitch, and security group.

Automatic configuration

This example shows how to automatically deploy an application from an image in the China (Beijing) region.

  1. Create a project folder named terraform for storing Terraform resources.
  2. Run the following command to go to the project directory:
    cd terraform
  3. Create a configuration file named main.tf and add the following content.

    provider "alicloud" {
      region = var.region
    }
    variable "region" {
      default = "cn-beijing"
    }
    variable "name" {
      default = "serverless-example"
    }
    resource "random_integer" "default" {
      max = 99999
      min = 10000
    }
    data "alicloud_regions" "default" {
      current = true
    }
    data "alicloud_zones" "default" {
      available_resource_creation = "VSwitch"
    }
    resource "alicloud_vpc" "default" {
      vpc_name   = var.name
      cidr_block = "10.4.0.0/16"
    }
    resource "alicloud_vswitch" "default" {
      vswitch_name = var.name
      cidr_block   = "10.4.0.0/24"
      vpc_id       = alicloud_vpc.default.id
      zone_id      = data.alicloud_zones.default.zones.0.id
    }
    resource "alicloud_security_group" "default" {
      vpc_id = alicloud_vpc.default.id
    }
    resource "alicloud_sae_namespace" "default" {
      namespace_id              = "${data.alicloud_regions.default.regions.0.id}:example${random_integer.default.result}"
      namespace_name            = var.name
      namespace_description     = var.name
      enable_micro_registration = false
    }
    resource "alicloud_sae_application" "default" {
      app_description   = var.name
      app_name          = "${var.name}-${random_integer.default.result}"
      namespace_id      = alicloud_sae_namespace.default.id
      image_url         = "registry-vpc.${data.alicloud_regions.default.regions.0.id}.aliyuncs.com/sae-demo-image/consumer:1.0"
      package_type      = "Image"
      security_group_id = alicloud_security_group.default.id
      vpc_id            = alicloud_vpc.default.id
      vswitch_id        = alicloud_vswitch.default.id
      timezone          = "Asia/Beijing"
      replicas          = "1"
      cpu               = "500"
      memory            = "2048"
    }

    You can log on to the Container Registry console and view the image address on the Basic Information page of the target instance repository. The address is in the following format:

    registry.<regionId>.aliyuncs.com/<namespace_name>/<image_repository_name>:<image_version_number>
  4. Run the following command to initialize the configurations:
    terraform init
  1. Expected output:

Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
  1. Run the following commands to create the SAE application.

  • Run the following command to apply the configuration file.When the command runs, enter yes at the prompt, press the Enter key, and wait for the command to complete. If the following information is displayed, the authorization is complete.

terraform apply
  1. Expected output:

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
  1. Verify the result

Terraform show command

You can run the following command to query the details of the resources created by Terraform:

terraform show
shell@Alicloud: /serverless$ terraform show
# alicloud_sae_application.default:
resource "alicloud_sae_application" "default" {
    app_description              = "serverless-xxx"
    app_name                     = "serverless-xxx"
    batch_wait_time              = 10
    command_args_v2              = []
    config_map_mount_desc        = jsonencode([])
    cpu                          = 500
    custom_host_alias            = jsonencode([])
    enable_ahas                  = "false"
    enable_grey_tag_route        = false
    envs                         = jsonencode([])
    id                           = "131976e5-7264-xxx"
    image_url                    = "registry-vpc.cn-beijing.aliyuncs.com/sae-demo-image/consumer:1.0"
    memory                       = 2048
    min_ready_instance_ratio     = -1
    min_ready_instances          = -1
    namespace_id                 = "cn-beijing:xxx"
    package_type                 = "Image"
    package_version              = "1731047094"
    replicas                     = 1
    security_group_id            = "sg-2zxxx"
    status                       = "RUNNING"
    termination_grace_period_seconds = 30
    timezone                     = "Asia/Beijing"
    vpc_id                       = "vpc-xxx"
    vswitch_id                   = "vsw-xxx"
}

SAE console

Log on to the Serverless App Engine (SAE) console and view the list of created applications.

The application list shows the automatically created application, such as serverless-xxx. An instance count of 1/1 confirms that the application is running correctly.

Note

The following sample code can be run with a single click in Terraform Explorer.

Custom configuration: Image deployment

This example shows how to deploy an application from an image with custom configurations in the China (Shenzhen) region.

  1. Create a project folder named terraform for storing Terraform resources.
  2. Run the following command to go to the project directory:
    cd terraform
  3. Create a configuration file named main.tf and add the following content.

    provider "alicloud" {
      region = var.region_id
    }
    # Region ID
    variable "region_id" {
      type    = string
      default = "cn-shenzhen"
    }
    # Application name
    variable "app_name" {
      description = "The name of the application"
      type        = string
      default     = "manual-jar-tf"
    }
    # Application description
    variable "app_description" {
      default     = "description created by Terraform"
      description = "The description of the application"
      type        = string
    }
    # Application deployment method
    variable "package_type" {
      default     = "FatJar"
      description = "The package type of the application"
      type        = string
    }
    # Instance CPU specification
    variable "cpu" {
      default     = "500"
      description = "The cpu of the application, in unit of millicore"
      type        = string
    }
    # Instance memory specification
    variable "memory" {
      default     = "1024"
      description = "The memory of the application, in unit of MB"
      type        = string
    }
    # JAR package URL
    variable "jar_url" {
      description = "The JAR url of the application, like `oss://my-bucket/my-app.jar`"
      type        = string
      default     = "https://edas-sz.oss-cn-shenzhen.aliyuncs.com/prod/demo/SPRING_CLOUD_CONSUMER.jar"
    }
    # Number of application instances
    variable "replicas" {
      default     = "1"
      description = "The replicas of the application"
      type        = string
    }
    # Namespace name
    variable "namespace_name" {
      description = "Namespace Name"
      type        = string
      default     = "tfjardemo"
    }
    # Namespace ID
    variable "namespace_id" {
      description = "Namespace ID"
      type        = string
      default     = "cn-shenzhen:tfjardemo"  # Reference an existing namespace ID
    }
    # Namespace description
    variable "namespace_description" {
      description = "Namespace Description"
      default     = "a namespace"
    }
    # VPC and security group
    variable "name" {
      default     = "tf"
      description = "The name of the security group rule"
      type        = string
    }
    variable "description" {
      default     = "The description of the security group rule"
      description = "The description of the security group rule"
      type        = string
    }
    # Port range
    variable "port_range" {
      default     = "1/65535"
      description = "The port range of the security group rule"
      type        = string
    }
    # CIDR block
    variable "cidr_ip" {
      description = "cidr blocks used to create a new security group rule"
      type        = string
      default     = "0.0.0.0/0"
    }
    # Availability zone in the region
    variable "zone_id" {
      description = "Availability Zone ID"
      type        = string
      default     = "cn-shenzhen-e"  # Select an availability zone with sufficient resources
    }
    # Collect application logs to SLS
    variable "slsConfig" {
      default     = "[{\"logDir\":\"\",\"logType\":\"stdout\"},{\"logDir\":\"/home/admin/logs/*.log\"}]"
      description = "The config of sls log collect"
      type        = string
    }
    resource "alicloud_vpc" "vpc" {
      vpc_name   = "tf-vpc"
      cidr_block = "172.16.0.0/16"
    }
    resource "alicloud_vswitch" "vswitch" {
      vpc_id       = alicloud_vpc.vpc.id
      cidr_block   = "172.16.1.0/24"
      zone_id      = var.zone_id
      vswitch_name = "tf-vswitch"
      description  = "tf-vswitch description"
    }
    resource "alicloud_sae_namespace" "default" {
      namespace_id          = var.namespace_id
      namespace_name        = var.namespace_name
      namespace_description = var.namespace_description
    }
    output "namespace_id" {
      value       = var.namespace_id
      description = "Namespace ID"
    }
    resource "alicloud_security_group" "sg" {
      name        = var.name
      description = var.description
      vpc_id      = alicloud_vpc.vpc.id
    }
    resource "alicloud_security_group_rule" "sg_rule" {
      type              = "ingress"
      ip_protocol       = "tcp"
      nic_type          = "intranet"
      policy            = "accept"
      port_range        = var.port_range
      priority          = 1
      security_group_id = alicloud_security_group.sg.id
      cidr_ip           = var.cidr_ip
    }
    resource "alicloud_sae_application" "manual" {
      app_name           = var.app_name
      app_description    = var.app_description
      deploy             = true
      package_url        = var.jar_url
      namespace_id       = alicloud_sae_namespace.default.id
      vswitch_id         = alicloud_vswitch.vswitch.id
      vpc_id             = alicloud_vpc.vpc.id
      security_group_id  = alicloud_security_group.sg.id
      package_type       = var.package_type
      jdk                = "Open JDK 8"
      timezone           = "Asia/Beijing"
      replicas           = var.replicas
      cpu                = var.cpu
      memory             = var.memory
      micro_registration = "0"
      lifecycle {
        ignore_changes = [
          micro_registration
        ]
      }
    }
    output "app_id" {
      description = "The id of the application"
      value       = alicloud_sae_application.manual.id
    }
    output "app_name" {
      description = "The name of the application"
      value       = var.app_name
    }
  4. Run the following command to initialize the configurations:
    terraform init
  5. Expected output:

    Terraform has been successfully initialized!
    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.
    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
  1. Run the following commands in sequence to create an application by using an image. During the execution, enter yes and press the Enter key when prompted. Wait for the command to complete. If the following information appears, the authorization is complete.

terraform apply
  1. Expected output:

Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
Outputs:
app_id = "72c052ba-xxx"
app_name = "manual-image-tf"
namespace_id = "cn-shenzhen:tfdemo"

If the output is as expected, the application is successfully deployed.

  1. Verify the result

Terraform show command

You can run the following command to query the details of the resources created by Terraform:

terraform show
shell@Alicloud: ~/serverless$ terraform show
# alicloud_sae_application.manual:
resource "alicloud_sae_application" "manual" {
    app_description              = "description created by Terraform"
    app_name                     = "manual-image-tf"
    batch_wait_time              = 10
    command_args_v2              = []
    config_map_mount_desc        = jsonencode([])
    cpu                          = 500
    custom_host_alias            = jsonencode([])
    deploy                       = true
    enable_ahas                  = "false"
    enable_grey_tag_route        = false
    envs                         = jsonencode([])
    id                           = "72c05xxx"
    image_url                    = "registry.cn-beijing.aliyuncs.com/sae-serverless-demo/sae-demo:microservice-java-provider-v1.0"
    memory                       = 1024
    min_ready_instance_ratio     = -1
    min_ready_instances          = -1
    namespace_id                 = "cn-shenzhen:tfdemo"
    package_type                 = "Image"
    package_version              = "1732169733"
    replicas                     = 1
    security_group_id            = "sg-wz96xxx"
    status                       = "RUNNING"
    termination_grace_period_seconds = 30
    timezone                     = "Asia/Beijing"
    vpc_id                       = "vpc-xxx"
    vswitch_id                   = "vsw-xxx"
}
# alicloud_sae_namespace.default:
resource "alicloud_sae_namespace" "default" {
    enable_micro_registration = true
    id                        = "cn-shenzhen:tfdemo"
    namespace_description     = "a namespace"
    namespace_id              = "cn-shenzhen:tfdemo"
    namespace_name            = "tfdemo"
    namespace_short_id        = "tfdemo"
}

SAE console

Log on to the Serverless App Engine (SAE) console and view the list of created applications.

In the microservice application list, you can see that the application manual-image-tf is created in the tfdemo namespace. The application has a Current Instances/Target Instances count of 1/1, which confirms that it is running correctly.

In the left-side navigation pane for the manual-image-tf application, click Change History. Confirm that the Change Type is Deploy Application and the Status is Succeeded.

Custom configuration: JAR package deployment

This example shows how to deploy an application from a JAR package with custom configurations in the China (Shenzhen) region.

  1. Create a project folder named terraform for storing Terraform resources.
  2. Run the following command to go to the project directory:
    cd terraform
  3. Create a configuration file named main.tf and add the following content.

    provider "alicloud" {
      region = var.region_id
    }
    # Region ID
    variable "region_id" {
      type    = string
      default = "cn-shenzhen"
    }
    # Application name
    variable "app_name" {
      description = "The name of the application"
      type        = string
      default     = "manual-jar-tf"
    }
    # Application description
    variable "app_description" {
      default     = "description created by Terraform"
      description = "The description of the application"
      type        = string
    }
    # Application deployment method
    variable "package_type" {
      default     = "FatJar"
      description = "The package type of the application"
      type        = string
    }
    # Instance CPU specification
    variable "cpu" {
      default     = "500"
      description = "The cpu of the application, in unit of millicore"
      type        = string
    }
    # Instance memory specification
    variable "memory" {
      default     = "1024"
      description = "The memory of the application, in unit of MB"
      type        = string
    }
    # JAR package URL
    variable "jar_url" {
      description = "The JAR url of the application, like `oss://my-bucket/my-app.jar`"
      type        = string
      default     = "https://edas-sz.oss-cn-shenzhen.aliyuncs.com/prod/demo/SPRING_CLOUD_CONSUMER.jar"
    }
    # Number of application instances
    variable "replicas" {
      default     = "1"
      description = "The replicas of the application"
      type        = string
    }
    # Namespace name
    variable "namespace_name" {
      description = "Namespace Name"
      type        = string
      default     = "tfjardemo"
    }
    # Namespace ID
    variable "namespace_id" {
      description = "Namespace ID"
      type        = string
      default     = "cn-shenzhen:tfjardemo"  # Reference an existing namespace ID
    }
    # Namespace description
    variable "namespace_description" {
      description = "Namespace Description"
      default     = "a namespace"
    }
    # VPC and security group
    variable "name" {
      default     = "tf"
      description = "The name of the security group rule"
      type        = string
    }
    variable "description" {
      default     = "The description of the security group rule"
      description = "The description of the security group rule"
      type        = string
    }
    # Port range
    variable "port_range" {
      default     = "1/65535"
      description = "The port range of the security group rule"
      type        = string
    }
    # CIDR block
    variable "cidr_ip" {
      description = "cidr blocks used to create a new security group rule"
      type        = string
      default     = "0.0.0.0/0"
    }
    # Availability zone in the region
    variable "zone_id" {
      description = "Availability Zone ID"
      type        = string
      default     = "cn-shenzhen-e"  # Select an availability zone with sufficient resources
    }
    # Collect application logs to SLS
    variable "slsConfig" {
      default     = "[{\"logDir\":\"\",\"logType\":\"stdout\"},{\"logDir\":\"/home/admin/logs/*.log\"}]"
      description = "The config of sls log collect"
      type        = string
    }
    resource "alicloud_vpc" "vpc" {
      vpc_name   = "tf-vpc"
      cidr_block = "172.16.0.0/16"
    }
    resource "alicloud_vswitch" "vswitch" {
      vpc_id       = alicloud_vpc.vpc.id
      cidr_block   = "172.16.1.0/24"
      zone_id      = var.zone_id
      vswitch_name = "tf-vswitch"
      description  = "tf-vswitch description"
    }
    resource "alicloud_sae_namespace" "default" {
      namespace_id          = var.namespace_id
      namespace_name        = var.namespace_name
      namespace_description = var.namespace_description
    }
    output "namespace_id" {
      value       = var.namespace_id
      description = "Namespace ID"
    }
    resource "alicloud_security_group" "sg" {
      name        = var.name
      description = var.description
      vpc_id      = alicloud_vpc.vpc.id
    }
    resource "alicloud_security_group_rule" "sg_rule" {
      type              = "ingress"
      ip_protocol       = "tcp"
      nic_type          = "intranet"
      policy            = "accept"
      port_range        = var.port_range
      priority          = 1
      security_group_id = alicloud_security_group.sg.id
      cidr_ip           = var.cidr_ip
    }
    resource "alicloud_sae_application" "manual" {
      app_name           = var.app_name
      app_description    = var.app_description
      deploy             = true
      package_url        = var.jar_url
      namespace_id       = alicloud_sae_namespace.default.id
      vswitch_id         = alicloud_vswitch.vswitch.id
      vpc_id             = alicloud_vpc.vpc.id
      security_group_id  = alicloud_security_group.sg.id
      package_type       = var.package_type
      jdk                = "Open JDK 8"
      timezone           = "Asia/Beijing"
      replicas           = var.replicas
      cpu                = var.cpu
      memory             = var.memory
      micro_registration = "0"
      lifecycle {
        ignore_changes = [
          micro_registration
        ]
      }
    }
    output "app_id" {
      description = "The id of the application"
      value       = alicloud_sae_application.manual.id
    }
    output "app_name" {
      description = "The name of the application"
      value       = var.app_name
    }
  4. Run the following command to initialize the configuration.

    terraform init
  5. Run the following commands to create an application from a JAR package.

    1. Run the following command to deploy the application.When prompted, enter yes and press Enter. The authorization is complete if the following message is displayed after the command finishes running.

      terraform apply

      Expected output:

      Apply complete! Resources: 6 added, 0 changed, 4 destroyed.
      Outputs:
      app_id = "aad70a1a-xxx"
      app_name = "manual-jar-tf"
      namespace_id = "cn-shenzhen:tfjardemo"

    If the output is as expected, the application is successfully deployed from the JAR package.

  6. Verify the result:

Terraform show command

You can run the following command to query the details of the resources created by Terraform:

terraform show
shell1@Alicloud:~/serverless$ terraform show
# alicloud_sae_application.manual:
resource "alicloud_sae_application" "manual" {
    app_description             = "description created by Terraform"
    app_name                    = "manual-jar-tf"
    batch_wait_time             = 10
    command_args_v2             = []
    config_map_mount_desc       = jsonencode([])
    cpu                         = 500
    custom_host_alias           = jsonencode([])
    deploy                      = true
    enable_ahas                 = "false"
    enable_grey_tag_route       = false
    envs                        = jsonencode([])
    id                          = "6acbf6fc-6b1xxx"
    jdk                         = "Open JDK 8"
    memory                      = 1024
    micro_registration          = "0"
    min_ready_instance_ratio    = -1
    min_ready_instances         = -1
    namespace_id                = "cn-shenzhen:tfjardemo"
    package_type                = "FatJar"
    package_url                 = "https://edas-sz.oss-cn-shenzhen.aliyuncs.com/prod/demo/SPRING_CLOUD_CONSUMER.jar"
    package_version             = "1732241446"
}
    programming_language        = "java"
    replicas                    = 1
    security_group_id           = "sg-wz9j10xxx"
    status                      = "RUNNING"
    termination_grace_period_seconds = 30
    timezone                    = "Asia/Beijing"
    vpc_id                      = "vpc-wz9sjxxx"
    vswitch_id                  = "vsw-wz9e1xxx"
}

SAE console

Log on to the Serverless App Engine (SAE) console to view the created namespace.

In the left-side navigation pane, click Microservices Application. In the application list, confirm that the manual-jar-tf application is created in the tfjardemo namespace. The instance count is 1/1 and the specification is 0.5 Cores 1 GB.

Delete an application

To delete the resources you created, run the terraform destroy command.

  1. In the project directory, run the following command.

    terraform destroy

    Expected output:

    module.vpc.alicloud_vswitch.vswitches: Destroying...  [id=vsw-wz9bdsgvhit7jv2hb4li]
    module.vpc.alicloud_security_group_rule.sg_rule: Destroying...  [id=sg-wz9ba3de0fxxriu5c0m5:i]
    alicloud_security_group_rule.sg_rule: Destruction complete after 1s
    alicloud_security_group.sg: Destroying...  [id=sg-wz9ba3de0fxxriu5c0m5]
    alicloud_security_group.sg: Destruction complete after 0s
    module.vpc.alicloud_vswitch.vswitches: Destruction complete after 4s
    module.vpc.alicloud_vpc.vpc[0]: Destroying...  [id=vpc-wz9cg2ifzghh2pt948zcj]
    module.vpc.alicloud_vpc.vpc[0]: Destruction complete after 6s
    Destroy complete! Resources: 4 destroyed.

References