Function Compute calls lifecycle hooks when specific instance events occur, letting you run setup and teardown code outside your handler. The C# runtime supports two hooks: Initializer and PreStop. For background on instance lifecycle management, see Configure instance lifecycles.
Lifecycle hooks are billed the same way as standard function invocations. Hook execution logs appear in Function Logs, Real-time Logs, and Advanced Logs, but not in the invocation request list.
How Initializer and PreStop work
Initializer
The Initializer hook runs after a function instance starts and before the first handler invocation. Function Compute guarantees it runs exactly once per instance lifetime.
If the Initializer hook fails, the invocation returns an error. On the next invocation, Function Compute creates a new instance and retries the Initializer hook.
Use the Initializer hook for one-time setup — for example, initializing SDK clients or database connections. Because Function Compute reuses warm instances across invocations, setup code in the Initializer hook runs once and its results are available to every subsequent handler call on that instance.
PreStop
The PreStop hook runs before a function instance is destroyed. Use it to flush buffers, close connections, or release resources before the instance shuts down.
Method signature
Both Initializer and PreStop hooks use the same method signature: one IFcContext input parameter and no return value.
Instance method:
public void FunctionName(IFcContext context);Static method:
public static void FunctionName(IFcContext context);Example
The following example shows a class that implements both hooks alongside a stream handler.
using System;
using System.IO;
using System.Threading.Tasks;
using Aliyun.Serverless.Core;
using Microsoft.Extensions.Logging;
namespace Example
{
public class Hello
{
public void Initialize(IFcContext context)
{
IFcLogger logger = context.Logger;
logger.LogInformation("Initialize start");
logger.LogInformation("Handle initializer: {0}", context.RequestId);
logger.LogInformation("Initialize end");
}
public void PreStop(IFcContext context)
{
IFcLogger logger = context.Logger;
logger.LogInformation("PreStop start");
logger.LogInformation("Handle PreStop: {0}", context.RequestId);
logger.LogInformation("PreStop end");
}
public async Task<Stream> StreamHandler(Stream input, IFcContext context)
{
IFcLogger logger = context.Logger;
logger.LogInformation("Handle request: {0}", context.RequestId);
MemoryStream copy = new MemoryStream();
await input.CopyToAsync(copy);
copy.Seek(0, SeekOrigin.Begin);
return copy;
}
static void Main(string[] args){}
}
}Configure lifecycle hooks
Use the Function Compute console
In the Function Compute console, configure hooks using the same format as a handler: Assembly name::Namespace.Class name::Method name. For details, see Configure instance lifecycles and Handlers.
Based on the example class above:
Initializer:
HelloFcApp::Example.Hello::InitializePreStop:
HelloFcApp::Example.Hello::PreStop
Use Serverless Devs
Add instanceLifecycleConfig to the function block in your s.yaml file. Each hook requires a handler and a timeout field.
edition: 3.0.0
name: hello-world-app
access: "default"
vars:
region: "cn-hangzhou"
resources:
hello_world:
component: fc3
actions:
pre-${regex('deploy|local')}:
- run: dotnet publish -c Release -o ./target
path: ./HelloWorldApp
props:
region: ${vars.region}
functionName: "start-dotnetcore-p6jp"
description: 'hello world by serverless devs'
runtime: "dotnetcore3.1"
code: ./HelloWorldApp/target/
handler: HelloWorldApp::Example.Hello::StreamHandler
memorySize: 128
timeout: 10
instanceLifecycleConfig:
initializer:
handler: HelloFcApp::Example.Hello::Initialize
timeout: 60
preStop:
handler: HelloFcApp::Example.Hello::PreStop
timeout: 60For YAML syntax details, see Common commands of Serverless Devs.
View lifecycle hook logs
Log on to the Function Compute console. In the left-side navigation pane, click Functions.
In the top navigation bar, select a region. On the Functions page, click the function you want to inspect.
On the function details page, click the Test Function tab, click Test Function, and then choose Logs > Function Logs.
The Logs tab shows both invocation logs and Initializer logs:
2024-03-04 17:57:28 FC Initialize Start RequestId: 1-65e59b07-1520da26-bf73bbb91b69
2024-03-04 17:57:28 2024-03-04 09:57:28.192 1-65e59b07-1520da26-bf73bbb91b69 [info] initializer
2024-03-04 17:57:28 FC Initialize End RequestId: 1-65e59b07-1520da26-bf73bbb91b69
2024-03-04 17:57:28 FC Invoke Start RequestId: 1-65e59b07-1520da26-bf73bbb91b69
2024-03-04 17:57:28 FC Invoke End RequestId: 1-65e59b07-1520da26-bf73bbb91b69Function instances are cached after invocation and not immediately destroyed, so PreStop logs do not appear right away. To trigger a PreStop hook immediately, update the function configuration or code — this forces existing instances to be replaced. After the update, PreStop logs appear in Function Logs:
2024-03-04 18:33:26 FC PreStop Start RequestId: 93c93603-9fbe-4576-9458-193c8b213031
2024-03-04 18:33:26 2024-03-04 10:33:26.077 93c93603-9fbe-4576-9458-193c8b213031 [info] preStop
2024-03-04 18:33:26 FC PreStop End RequestId: 93c93603-9fbe-4576-9458-193c8b213031