Sandbox deep hibernation (pause and resume sessions)

Updated at:

Sandbox deep hibernation saves the state of a session instance (including memory, file system, and processes) to a snapshot and then destroys the instance by using the PauseSession and ResumeSession APIs. The instance can be restored from the snapshot when needed. No CPU and memory costs are incurred while a session is paused, making this feature ideal for scenarios that require long-term state retention but not continuous execution.

Overview

Sandbox deep hibernation builds on the session capabilities of Function Compute. When you call the PauseSession API, the system saves the complete running state of the instance associated with the session to a snapshot and then destroys the instance. When you call the ResumeSession API, the system restores the instance to a new execution environment from the snapshot, returning it to its pre-paused state.

Cost impact: After an instance is paused, it is destroyed, and no CPU or memory costs are incurred. Unlike light sleep, where instances in the Idle state still incur memory costs, deep hibernation reduces the long-term cost of maintaining Sandbox instances.

Typical use cases:

  • AI Sandbox development environment: After installing dependencies and tools in a Sandbox, you can use deep hibernation to save the environment's state. When you need it again, you can quickly restore it without re-initialization.

  • Long-running tasks that start and stop on demand: Retain the working state for a long time without continuous execution, such as for data processing tasks that can be interrupted and resumed.

Prerequisites

Important

Sandbox deep hibernation is currently an allowlist feature and is not enabled by default. To use this feature, submit a ticket to request access.

Your function must meet the following requirements:

Parameter

Requirement

Description

Session affinity

Must be enabled

Supports HeaderField affinity or Cookie affinity. MCP affinity is not supported.

Instance isolation

Must enable session isolation

Ensures one session corresponds to one independent instance (Sandbox mode).

Runtime type

Custom Container

built-in runtimes and Custom Runtimes are not supported.

Instance type

Only CPU instances are supported

GPU instances are not supported.

CPU/Memory specification

No specific limitations

Select as needed

For information about configuring session affinity and session isolation, see General limitations and principles of session affinity and Configure HeaderField affinity.

Limitations

Pause and resume behavior

Phase

Description

After pause

The instance is destroyed, and no CPU or memory costs are incurred. The session does not accept function invocation requests. You can query for sessions in the Paused status using GetSession or ListSessions, but you cannot find the destroyed instance using ListInstances.

After resume

The session TTL is not reset and continues to count from the original creation time. The behavior after resuming is as follows:

  • The TTL continues to count down during the pause period. For example, if a session has a 24-hour TTL, runs for 6 hours, is paused for 2 hours, and then resumed, its remaining TTL is 16 hours (24 - 6 - 2 = 16).

  • The session can accept function invocations again.

  • Network connections that existed before the pause (such as WebSocket or gRPC long-lived connections) are not restored and you must re-establish them.

  • You can pause and resume a session repeatedly.

Operation and status constraints

Actions

Allowed status

Description

PauseSession

Active

Only sessions in the Active status can be paused.

ResumeSession

Paused

Only sessions in the Paused status can be resumed.

UpdateSession

Not allowed

Sessions cannot be updated while Pausing, Paused, or Resuming.

DeleteSession

Only allowed for Paused status

Sessions cannot be deleted while Pausing or Resuming.

InvokeFunction

Not allowed

New requests are not accepted while the session is Pausing, Paused, or Resuming.

Function version limitations

  • Non-LATEST versions: The function version associated with the session must have session affinity and session isolation enabled. Otherwise, PauseSession and ResumeSession are not supported.

  • LATEST version:

    • Session affinity and session isolation must be enabled.

    • PauseSession limitation: You cannot call PauseSession if other sessions exist on the same instance.

    • ResumeSession limitation: If the function configuration for the LATEST version changes after you pause the session but before you resume it (indicated by a change in metadata version), you cannot call ResumeSession.

Procedure

Install SDK dependencies

Install the Go SDK dependencies:

go get github.com/alibabacloud-go/darabonba-openapi/v2/client
go get github.com/alibabacloud-go/fc-20230330/client
go get github.com/alibabacloud-go/tea/dara
go get github.com/alibabacloud-go/tea/tea

Initialize the FC client

Initialize the Function Compute client. Replace the RegionId and Endpoint with your actual values. The AccessKey is read from environment variables.

package main

import (
    "fmt"
    "os"

    openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
    fc "github.com/alibabacloud-go/fc-20230330/client"
    "github.com/alibabacloud-go/tea/dara"
    "github.com/alibabacloud-go/tea/tea"
)

func createClient() (*fc.Client, error) {
    return fc.NewClient(&openapi.Config{
        RegionId:        tea.String("cn-shanghai"),          // Replace with your actual region.
        AccessKeyId:     tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
        AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
        Endpoint:        tea.String("<Account ID>.cn-shanghai.fc.aliyuncs.com"), // Replace with your actual Endpoint.
    })
}

Pause a session (PauseSession)

Pause an Active session. This saves a snapshot of the instance and then destroys the instance.

API request syntax

PUT /2023-03-30/functions/{functionName}/sessions/{sessionId}/pause

Go SDK example

func pauseSession(client *fc.Client, functionName, sessionId *string) (*fc.PauseSessionResponse, error) {
    return client.PauseSessionWithOptions(
        functionName,
        sessionId,
        &fc.PauseSessionRequest{},
        nil,
        &dara.RuntimeOptions{},
    )
}

// Example call
func main() {
    client, err := createClient()
    if err != nil {
        panic(err)
    }

    functionName := tea.String("my-sandbox-function")
    sessionId := tea.String("my-session-id")

    resp, err := pauseSession(client, functionName, sessionId)
    if err != nil {
        fmt.Printf("PauseSession failed: %v\n", err)
        return
    }
    fmt.Printf("PauseSession successful, Session status: %s\n", tea.StringValue(resp.Body.SessionStatus))
}
Note

After a successful call, the session status transitions from ActivePausingPaused. You can call GetSession to check the current status and confirm that the session has entered the Paused state.

If the session is associated with a function alias or a specific version, specify it using the Qualifier parameter:

resp, err := client.PauseSessionWithOptions(
    functionName,
    sessionId,
    &fc.PauseSessionRequest{
        Qualifier: tea.String("my-alias"),
    },
    nil,
    &dara.RuntimeOptions{},
)

For detailed parameter descriptions, see the PauseSession API reference.

Resume a session (ResumeSession)

Resume a Paused session. This restores the instance to a new execution environment from its snapshot.

API request syntax

PUT /2023-03-30/functions/{functionName}/sessions/{sessionId}/resume

Go SDK example

func resumeSession(client *fc.Client, functionName, sessionId *string) (*fc.ResumeSessionResponse, error) {
    return client.ResumeSessionWithOptions(
        functionName,
        sessionId,
        &fc.ResumeSessionRequest{},
        nil,
        &dara.RuntimeOptions{},
    )
}

// Example call
func main() {
    client, err := createClient()
    if err != nil {
        panic(err)
    }

    functionName := tea.String("my-sandbox-function")
    sessionId := tea.String("my-session-id")

    resp, err := resumeSession(client, functionName, sessionId)
    if err != nil {
        fmt.Printf("ResumeSession failed: %v\n", err)
        return
    }
    fmt.Printf("ResumeSession successful, Session status: %s\n", tea.StringValue(resp.Body.SessionStatus))
}
Note

After a successful call, the session status transitions from PausedResumingActive. You can call GetSession to check the current status and confirm that the session has returned to Active. After resuming, any long-lived network connections (such as WebSocket or gRPC) that existed before the pause are not automatically restored. Your client must re-establish these connections.

For detailed parameter descriptions, see the ResumeSession API reference.

Check session status

Use GetSession to check a session's current status:

func getSession(client *fc.Client, functionName, sessionId *string) (*fc.GetSessionResponse, error) {
    return client.GetSession(functionName, sessionId, &fc.GetSessionRequest{})
}

End-to-end workflow example

This Go SDK example demonstrates the end-to-end workflow for creating, pausing, resuming, and deleting a session:

package main

import (
    "fmt"
    "os"

    openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
    fc "github.com/alibabacloud-go/fc-20230330/client"
    "github.com/alibabacloud-go/tea/dara"
    "github.com/alibabacloud-go/tea/tea"
)

func main() {
    // 1. Initialize the client.
    client, err := fc.NewClient(&openapi.Config{
        RegionId:        tea.String("cn-shanghai"),
        AccessKeyId:     tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
        AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
        Endpoint:        tea.String("<Account ID>.cn-shanghai.fc.aliyuncs.com"),
    })
    if err != nil {
        panic(err)
    }

    functionName := tea.String("my-sandbox-function")
    headerKey := "x-session-id"

    // 2. Invoke the function for the first time to automatically create a session.
    invokeResp, err := client.InvokeFunctionWithOptions(
        functionName,
        &fc.InvokeFunctionRequest{},
        &fc.InvokeFunctionHeaders{},
        &dara.RuntimeOptions{},
    )
    if err != nil {
        panic(err)
    }
    // Get the session ID from the response header.
    sessionId := invokeResp.Headers[headerKey]
    fmt.Printf("Session created. Session ID: %s\n", tea.StringValue(sessionId))

    // 3. Invoke the function by using the session (executes operations in the Sandbox).
    _, err = client.InvokeFunctionWithOptions(
        functionName,
        &fc.InvokeFunctionRequest{},
        &fc.InvokeFunctionHeaders{
            CommonHeaders: map[string]*string{
                headerKey: sessionId,
            },
        },
        &dara.RuntimeOptions{},
    )
    if err != nil {
        panic(err)
    }
    fmt.Println("Function invoked successfully.")

    // 4. Pause the session (saves a snapshot, destroys the instance).
    pauseResp, err := client.PauseSessionWithOptions(
        functionName,
        sessionId,
        &fc.PauseSessionRequest{},
        nil,
        &dara.RuntimeOptions{},
    )
    if err != nil {
        panic(err)
    }
    fmt.Printf("PauseSession successful. Status: %s\n", tea.StringValue(pauseResp.Body.SessionStatus))

    // 5. After some time, resume the session.
    resumeResp, err := client.ResumeSessionWithOptions(
        functionName,
        sessionId,
        &fc.ResumeSessionRequest{},
        nil,
        &dara.RuntimeOptions{},
    )
    if err != nil {
        panic(err)
    }
    fmt.Printf("ResumeSession successful. Status: %s\n", tea.StringValue(resumeResp.Body.SessionStatus))

    // 6. Continue to invoke the function by using the session.
    _, err = client.InvokeFunctionWithOptions(
        functionName,
        &fc.InvokeFunctionRequest{},
        &fc.InvokeFunctionHeaders{
            CommonHeaders: map[string]*string{
                headerKey: sessionId,
            },
        },
        &dara.RuntimeOptions{},
    )
    if err != nil {
        panic(err)
    }
    fmt.Println("Function invoked successfully after resuming. The environment state is consistent with the pre-pause state.")

    // 7. When finished, delete the session.
    _, err = client.DeleteSessionWithOptions(
        functionName,
        sessionId,
        &fc.DeleteSessionRequest{},
        nil,
        &dara.RuntimeOptions{},
    )
    if err != nil {
        panic(err)
    }
    fmt.Println("Session deleted.")
}

Session state transitions

When deep hibernation is enabled, the session lifecycle includes three additional statuses: Pausing, Paused, and Resuming.

Current status

Trigger

Target status

(Initial)

CreateSession or InvokeFunction

Active

Active

PauseSession

Pausing

Pausing

Snapshot creation completes and the instance is destroyed.

Paused

Paused

ResumeSession

Resuming

Resuming

Instance restoration is complete.

Active

Active

TTL timeout or Idle timeout

Expired

Active

DeleteSession

Deleted

Paused

DeleteSession

Deleted

Status

Description

Billed

Active

The session is active and the instance is ready to process requests.

Yes (billed for instance runtime)

Pausing

A snapshot is being saved, and the instance's CPU is frozen.

Yes (billing continues during the snapshot process)

Paused

The snapshot has been saved and the instance has been destroyed.

No (no CPU or memory costs are incurred)

Resuming

The instance is being restored from the snapshot.

Yes (billing starts during the restoration process)

Expired

The session has expired due to a TTL or Idle timeout.

No

Deleted

The user deleted the session.

No

FAQ

Does a paused session expire automatically?

Yes. The session TTL continues to count down while the session is paused. If the TTL limit is reached while in the Paused state, the session expires automatically. We recommend confirming that the remaining TTL is sufficient before pausing a session.

How is the session TTL calculated after resuming?

The TTL is not reset by calling ResumeSession. It is always calculated from the session's creation time. For example, if a session with a 24-hour TTL runs for 6 hours, is paused for 2 hours, and then resumed, the remaining TTL is 16 hours (24 - 6 - 2 = 16).

Can a session be paused and resumed multiple times?

Yes. You can call PauseSession on an Active session and ResumeSession on a Paused session repeatedly.

Can a session resume after modifying the LATEST version?

No. If you modify the configuration of the LATEST function version after calling PauseSession but before calling ResumeSession (which changes its metadata version), the system will reject the ResumeSession call and return an error.

Even if you resume the session first and then modify the configuration, the restored instance continues to use the old configuration from before it was paused. To use the latest configuration, you must delete the current session and create a new one.

What happens to in-flight requests during a pause?

When PauseSession is called, the system immediately freezes the instance's CPU. Any requests being processed will time out and fail. We recommend ensuring there are no in-flight requests on the instance before pausing it.

What does GetSession return for a paused session?

You can retrieve the complete configuration information for the session, including its ID, function name, and status. Because the instance has been destroyed, you cannot find it using ListInstances.