Template pre-warming

Updated at:

Template pre-warming (Template Cache) prepares the image data of a built template in advance. Pre-warming reduces the cold start time caused by image pulls when you create a sandbox for the first time.

Overview

The pre-warming policies and billing rules for each template type are as follows:

  • Official templates: Pre-warmed automatically by the platform. No manual intervention is required, and no pre-warming fees are charged.

  • Custom templates: Must be pre-warmed by calling API operations. You are charged based on the actual storage size of the pre-warmed data. Pre-warm custom templates as needed before the templates are published or sandboxes are created in batches.

Prerequisites

Procedure

Step 1: Initialize the SDK client

Install the Go software development kit (SDK) and its dependencies.

go get github.com/alibabacloud-go/sandbox-20260820/client
go get github.com/alibabacloud-go/darabonba-openapi/v2/utils
go get github.com/alibabacloud-go/tea/dara

Set the access credentials:

export ALIBABA_CLOUD_ACCESS_KEY_ID="<YOUR-ACCESS-KEY-ID>"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="<YOUR-ACCESS-KEY-SECRET>"
# If you use STS temporary credentials, also set the following variable:
# export ALIBABA_CLOUD_SECURITY_TOKEN="<YOUR-SECURITY-TOKEN>"

The following examples are based on OpenAPI version 2026-08-20. Subsequent steps reuse this client initialization code, so the import statements are not listed again.

package main

import (
    "fmt"
    "os"
    "time"

    openapiutil "github.com/alibabacloud-go/darabonba-openapi/v2/utils"
    sandbox "github.com/alibabacloud-go/sandbox-20260820/client"
    "github.com/alibabacloud-go/tea/dara"
)

func newClient(region string) (*sandbox.Client, error) {
    return sandbox.NewClient(&openapiutil.Config{
        AccessKeyId:     dara.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
        AccessKeySecret: dara.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
        SecurityToken:   dara.String(os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN")),
        Endpoint:        dara.String("sandbox." + region + ".aliyuncs.com"),
        Protocol:        dara.String("https"),
    })
}
A long-term AccessKey does not require ALIBABA_CLOUD_SECURITY_TOKEN. Set ALIBABA_CLOUD_SECURITY_TOKEN when you use STS temporary credentials.

Step 2: Create a pre-warming task and poll until the task is ready

Call CreateTemplateCache to submit the pre-warming task, and then call DescribeTemplateCache to poll the task until status changes to ready. A successful request indicates that the platform has accepted the task, and the pre-warming runs asynchronously in the background. Acceptance does not indicate that the pre-warming is complete. The example polls every 15 seconds and waits for at most 20 minutes. If the wait times out, continue to query the task status instead of creating the task again. If the build status (status.state ) of the template is not ready, CreateTemplateCache returns 409 TemplateNotReady, and no pre-warming task is created.

func createAndWait(client *sandbox.Client, teamID, templateID string) error {
    resp, err := client.CreateTemplateCache(&sandbox.CreateTemplateCacheRequest{
        Body: &sandbox.CreateTemplateCacheInput{
            TeamID:     dara.String(teamID),
            TemplateID: dara.String(templateID),
        },
    })
    if err != nil {
        return fmt.Errorf("CreateTemplateCache: %w", err)
    }

    cache := resp.Body.TemplateCache
    fmt.Printf("accepted: status=%s requestId=%s\n",
        dara.StringValue(cache.Status), dara.StringValue(resp.Body.RequestId))

    deadline := time.Now().Add(20 * time.Minute)
    for time.Now().Before(deadline) {
        got, err := client.DescribeTemplateCache(
            dara.String(templateID),
            &sandbox.DescribeTemplateCacheRequest{TeamID: dara.String(teamID)},
        )
        if err != nil {
            return fmt.Errorf("DescribeTemplateCache: %w", err)
        }

        cache = got.Body.TemplateCache
        status := dara.StringValue(cache.Status)
        fmt.Printf("status=%s progress=%d reason=%q sizeMB=%d requestId=%s\n",
            status,
            dara.Int32Value(cache.Progress),
            dara.StringValue(cache.StatusReason),
            dara.Int32Value(cache.ImageSizeMB),
            dara.StringValue(got.Body.RequestId),
        )

        switch status {
        case "ready":
            return nil
        case "failed", "evicted":
            return fmt.Errorf("template cache is %s: %s", status, dara.StringValue(cache.StatusReason))
        }
        time.Sleep(15 * time.Second)
    }
    return fmt.Errorf("timed out waiting for template cache")
}

Pre-warming is complete only when status is ready. progress is for display only. It takes only the values 0 (not ready) and 100 (ready), does not advance gradually as a percentage, and is not used to determine readiness.

Step 3: Create a sandbox from a pre-warmed template

After status is ready, use the template to create a sandbox so that the pre-warming speedup takes effect. If you create a sandbox before the pre-warming is complete, the only impact is that the speedup is usually unavailable. If the accelerated image data is still being prepared, a 400 accelerated image not ready error may be returned. Try again after the data is ready. For more information, see Create a Sandbox.

More operations

Query the pre-warming status

Call DescribeTemplateCache with the template ID and the Team ID, and determine the task status from the returned status:

  • creating: The task is accepted and may be queuing, waiting for capacity, waiting for a concurrency slot, or pre-warming. Continue to query the task instead of creating it again.

  • ready: The pre-warming is complete. Use the template to create a sandbox.

  • failed: Pre-warming failed. Check statusReason to identify the cause, and then delete the task and create it again.

  • evicted: The platform has reclaimed the pre-warmed data, so the task no longer provides the pre-warming speedup. Delete the task, wait until a query returns 404, and then create it again. Also delete the other evicted tasks of the same image (imageDigest) in the same region. Otherwise, the new task may immediately return to evicted.

Query pre-warming tasks with pagination

Call ListTemplateCache to paginate through the pre-warming tasks of the current Team. Filter the results by templateID and status. maxResults defaults to 20. Valid values range from 1 to 100. If the value is out of the range, the boundary value is used and no error is returned. Pagination ends when nextToken is empty. Do not determine the end of pagination from the number of entries on the current page.

Delete a pre-warming task

When pre-warming is no longer needed, call DeleteTemplateCache to delete the task.

func deleteCache(client *sandbox.Client, teamID, templateID string) error {
    resp, err := client.DeleteTemplateCache(
        dara.String(templateID),
        &sandbox.DeleteTemplateCacheRequest{TeamID: dara.String(teamID)},
    )
    if err != nil {
        return fmt.Errorf("DeleteTemplateCache: %w", err)
    }
    fmt.Printf("delete accepted: requestId=%s\n", dara.StringValue(resp.Body.RequestId))
    return nil
}

After DeleteTemplateCache returns success, continue to call DescribeTemplateCache until the call returns 404 TemplateCacheNotFound. The logical deletion of the pre-warming task is complete only after this error is returned. A successful response only indicates that the delete request is accepted. Once no live instance references the image, the platform safely and asynchronously cleans up the underlying image data. A repeated delete request returns 404.

To pre-warm a task again after its status becomes failed or evicted, delete the task first and then call CreateTemplateCache.

For more information about the request parameters, authorization information, and response fields of each operation, see Alibaba Cloud SDK and API guide.

Limits

  • Pre-warming is isolated by region, so a pre-warming task created in one region is not automatically synchronized to other regions.

  • By default, each account has a 10 GiB pre-warming capacity quota in each region. The usage is calculated by summing the imageSizeMB (in MiB) of the pre-warmed data of different images in the region. If the same image is pre-warmed by multiple templates, it consumes the quota only once.

    To increase the capacity quota, submit a ticket.
  • If the used capacity plus the requested capacity exceeds the quota of the current region, the task is still accepted and remains in the creating state until capacity becomes available. The create request returns 429 TemplateCacheLimitExceeded only when too many new tasks are queued. The capacity quota check applies to the total usage of the account, so 429 TemplateCacheLimitExceeded can occur even if a single task does not exceed the quota.

  • If a single task is within the quota but the remaining capacity is temporarily insufficient, the task may stay in the creating state. The platform evicts eligible older tasks and then continues to process the task.

  • A task is retained for at least 30 minutes after it is created, and can be evicted for capacity reasons only after this period. The platform reclaims tasks based on capacity usage and the least recently used (LRU) policy. An evicted task retains its metadata, and its status is reported as evicted.

  • Within the same Team, a template can have only one visible pre-warming task. A repeated create request does not overwrite the existing task, but returns 409 TemplateCacheAlreadyExists. The object of an evicted task still exists, and calling CreateTemplateCache again without deleting the task first returns the same error.

  • Delete the corresponding pre-warming task before you delete the template, and wait until DescribeTemplateCache returns 404. If an active pre-warming task exists, deleting the template may return 409 TemplateHasActiveCache.

    Warning

    After a template is deleted, it cannot be used to create new sandbox instances. To use the template again, rebuild it. Before you delete the template, make sure that your workloads no longer depend on it.

  • Creation, deletion, and status changes are eventually consistent. If an SDK call times out or returns 500, call DescribeTemplateCache first to confirm the result, and then decide whether to retry. This prevents duplicate operations.

Troubleshooting

Error code

Meaning and recommended action

TemplateNotReady

The template has not finished building. Wait until GetTemplate returns ready, and then retry.

TemplateCacheAlreadyExists

The pre-warming task already exists. Query the existing task instead. If the status is evicted or failed, delete the task and then create it again.

TemplateCacheLimitExceeded

Too many new tasks are queued. The error message indicates Too many images are waiting to be prewarmed. Delete the pre-warming tasks that are no longer used (including evicted tasks) or submit a ticket to increase the quota, and then retry with exponential backoff and random jitter.

TemplateCacheDeleting

The pre-warming task is being deleted. Wait until a query returns 404, and then create the task again.

TemplateCacheNotFound

The pre-warming task does not exist, or the deletion is complete.

InvalidParameter

The request parameters are invalid: teamID is missing, the template is a built-in template of the platform, or the template is a second-generation template that uses an official public image. Such templates are pre-warmed by the platform and do not support manual pre-warming.

TemplateNotFound

The template ID does not exist, or the template does not belong to the Team. An invalid teamID also returns this error code.

TemplateHasActiveCache

A pre-warming task still exists when you delete the template. Delete the pre-warming task before you delete the template.

AccessDenied

The caller is not authorized to access the Team or the template. Check the caller identity and resource ownership. If the Team or template ownership is invalid, the platform returns 404 TemplateNotFound. Check the resource ownership before you troubleshoot Resource Access Management (RAM) permissions.

InternalError

An internal error occurred on the platform. Query the task first to confirm whether the creation or deletion has taken effect, and then decide whether to retry.

If a task remains in the creating state for an extended period, continue to query the task instead of submitting the task again. If the task still does not complete, submit a ticket. Handle errors in your business logic based on stable error codes, and do not match error messages.

When you submit a ticket, retain the requestId in each response, and provide the region, Team ID, template ID, API operation name, request time, and the error code or statusReason.

References