The aws:lambda/invocation:Invocation resource, part of the Pulumi AWS provider, invokes a Lambda function synchronously during Pulumi operations, optionally re-invoking when inputs change or during lifecycle transitions. This guide focuses on three capabilities: one-time initialization invocations, trigger-based re-invocation, and lifecycle event handling.
Invocations require existing Lambda functions with appropriate IAM permissions. The examples are intentionally small. Combine them with your own Lambda functions and error handling logic.
Invoke a function once during stack creation
Many deployments run initialization logic exactly once when infrastructure is first created, such as seeding databases or validating connectivity.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
// Lambda function to invoke
const example = new aws.lambda.Function("example", {
code: new pulumi.asset.FileArchive("function.zip"),
name: "data_processor",
role: lambdaRole.arn,
handler: "index.handler",
runtime: aws.lambda.Runtime.Python3d12,
});
// Invoke the function once during resource creation
const exampleInvocation = new aws.lambda.Invocation("example", {
functionName: example.name,
input: JSON.stringify({
operation: "initialize",
config: {
environment: "production",
debug: false,
},
}),
});
export const initializationResult = std.jsondecodeOutput({
input: exampleInvocation.result,
}).apply(invoke => invoke.result?.status);
import pulumi
import json
import pulumi_aws as aws
import pulumi_std as std
# Lambda function to invoke
example = aws.lambda_.Function("example",
code=pulumi.FileArchive("function.zip"),
name="data_processor",
role=lambda_role["arn"],
handler="index.handler",
runtime=aws.lambda_.Runtime.PYTHON3D12)
# Invoke the function once during resource creation
example_invocation = aws.lambda_.Invocation("example",
function_name=example.name,
input=json.dumps({
"operation": "initialize",
"config": {
"environment": "production",
"debug": False,
},
}))
pulumi.export("initializationResult", std.jsondecode_output(input=example_invocation.result).apply(lambda invoke: invoke.result["status"]))
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Lambda function to invoke
example, err := lambda.NewFunction(ctx, "example", &lambda.FunctionArgs{
Code: pulumi.NewFileArchive("function.zip"),
Name: pulumi.String("data_processor"),
Role: pulumi.Any(lambdaRole.Arn),
Handler: pulumi.String("index.handler"),
Runtime: pulumi.String(lambda.RuntimePython3d12),
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"operation": "initialize",
"config": map[string]interface{}{
"environment": "production",
"debug": false,
},
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
// Invoke the function once during resource creation
exampleInvocation, err := lambda.NewInvocation(ctx, "example", &lambda.InvocationArgs{
FunctionName: example.Name,
Input: pulumi.String(json0),
})
if err != nil {
return err
}
ctx.Export("initializationResult", std.JsondecodeOutput(ctx, std.JsondecodeOutputArgs{
Input: exampleInvocation.Result,
}, nil).ApplyT(func(invoke std.JsondecodeResult) (*interface{}, error) {
return invoke.Result.Status, nil
}).(pulumi.Interface{}PtrOutput))
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
// Lambda function to invoke
var example = new Aws.Lambda.Function("example", new()
{
Code = new FileArchive("function.zip"),
Name = "data_processor",
Role = lambdaRole.Arn,
Handler = "index.handler",
Runtime = Aws.Lambda.Runtime.Python3d12,
});
// Invoke the function once during resource creation
var exampleInvocation = new Aws.Lambda.Invocation("example", new()
{
FunctionName = example.Name,
Input = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["operation"] = "initialize",
["config"] = new Dictionary<string, object?>
{
["environment"] = "production",
["debug"] = false,
},
}),
});
return new Dictionary<string, object?>
{
["initializationResult"] = Std.Jsondecode.Invoke(new()
{
Input = exampleInvocation.Result,
}).Apply(invoke => invoke.Result?.Status),
};
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.Function;
import com.pulumi.aws.lambda.FunctionArgs;
import com.pulumi.aws.lambda.Invocation;
import com.pulumi.aws.lambda.InvocationArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.JsondecodeArgs;
import com.pulumi.asset.FileArchive;
import static com.pulumi.codegen.internal.Serialization.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
// Lambda function to invoke
var example = new Function("example", FunctionArgs.builder()
.code(new FileArchive("function.zip"))
.name("data_processor")
.role(lambdaRole.arn())
.handler("index.handler")
.runtime("python3.12")
.build());
// Invoke the function once during resource creation
var exampleInvocation = new Invocation("exampleInvocation", InvocationArgs.builder()
.functionName(example.name())
.input(serializeJson(
jsonObject(
jsonProperty("operation", "initialize"),
jsonProperty("config", jsonObject(
jsonProperty("environment", "production"),
jsonProperty("debug", false)
))
)))
.build());
ctx.export("initializationResult", StdFunctions.jsondecode(JsondecodeArgs.builder()
.input(exampleInvocation.result())
.build()).applyValue(_invoke -> _invoke.result().status()));
}
}
resources:
# Lambda function to invoke
example:
type: aws:lambda:Function
properties:
code:
fn::FileArchive: function.zip
name: data_processor
role: ${lambdaRole.arn}
handler: index.handler
runtime: python3.12
# Invoke the function once during resource creation
exampleInvocation:
type: aws:lambda:Invocation
name: example
properties:
functionName: ${example.name}
input:
fn::toJSON:
operation: initialize
config:
environment: production
debug: false
outputs:
# Use the result in other resources
initializationResult:
fn::invoke:
function: std:jsondecode
arguments:
input: ${exampleInvocation.result}
return: result.status
The functionName property identifies which Lambda to invoke. The input property contains the JSON payload sent to the function. By default, the function runs only during resource creation; subsequent applies don’t re-invoke unless the resource is replaced. The result property captures the function’s return value, which you can parse and export.
Re-invoke when configuration or dependencies change
Some workflows need to re-run Lambda logic whenever upstream configuration changes, such as processing new data batches or responding to environment updates.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";
const example = new aws.lambda.Invocation("example", {
functionName: exampleAwsLambdaFunction.functionName,
triggers: {
function_version: exampleAwsLambdaFunction.version,
config_hash: std.sha256Output({
input: JSON.stringify({
environment: environment,
timestamp: std.timestamp({}).then(invoke => invoke.result),
}),
}).apply(invoke => invoke.result),
},
input: JSON.stringify({
operation: "process_data",
environment: environment,
batch_id: batchId.result,
}),
});
import pulumi
import json
import pulumi_aws as aws
import pulumi_std as std
example = aws.lambda_.Invocation("example",
function_name=example_aws_lambda_function["functionName"],
triggers={
"function_version": example_aws_lambda_function["version"],
"config_hash": std.sha256_output(input=json.dumps({
"environment": environment,
"timestamp": std.timestamp().result,
})).apply(lambda invoke: invoke.result),
},
input=json.dumps({
"operation": "process_data",
"environment": environment,
"batch_id": batch_id["result"],
}))
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
"github.com/pulumi/pulumi-std/sdk/go/std"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
tmpJSON0, err := json.Marshal(map[string]interface{}{
"environment": environment,
"timestamp": std.Timestamp(ctx, &std.TimestampArgs{}, nil).Result,
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
tmpJSON1, err := json.Marshal(map[string]interface{}{
"operation": "process_data",
"environment": environment,
"batch_id": batchId.Result,
})
if err != nil {
return err
}
json1 := string(tmpJSON1)
_, err = lambda.NewInvocation(ctx, "example", &lambda.InvocationArgs{
FunctionName: pulumi.Any(exampleAwsLambdaFunction.FunctionName),
Triggers: pulumi.StringMap{
"function_version": pulumi.Any(exampleAwsLambdaFunction.Version),
"config_hash": pulumi.String(std.Sha256Output(ctx, std.Sha256OutputArgs{
Input: pulumi.String(json0),
}, nil).ApplyT(func(invoke std.Sha256Result) (*string, error) {
return invoke.Result, nil
}).(pulumi.StringPtrOutput)),
},
Input: pulumi.String(json1),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Lambda.Invocation("example", new()
{
FunctionName = exampleAwsLambdaFunction.FunctionName,
Triggers =
{
{ "function_version", exampleAwsLambdaFunction.Version },
{ "config_hash", Std.Sha256.Invoke(new()
{
Input = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["environment"] = environment,
["timestamp"] = Std.Timestamp.Invoke().Apply(invoke => invoke.Result),
}),
}).Apply(invoke => invoke.Result) },
},
Input = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["operation"] = "process_data",
["environment"] = environment,
["batch_id"] = batchId.Result,
}),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.Invocation;
import com.pulumi.aws.lambda.InvocationArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.TimestampArgs;
import com.pulumi.std.inputs.Sha256Args;
import static com.pulumi.codegen.internal.Serialization.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Invocation("example", InvocationArgs.builder()
.functionName(exampleAwsLambdaFunction.functionName())
.triggers(Map.ofEntries(
Map.entry("function_version", exampleAwsLambdaFunction.version()),
Map.entry("config_hash", StdFunctions.sha256(Sha256Args.builder()
.input(serializeJson(
jsonObject(
jsonProperty("environment", environment),
jsonProperty("timestamp", StdFunctions.timestamp(TimestampArgs.builder()
.build()).result())
)))
.build()).applyValue(_invoke -> _invoke.result()))
))
.input(serializeJson(
jsonObject(
jsonProperty("operation", "process_data"),
jsonProperty("environment", environment),
jsonProperty("batch_id", batchId.result())
)))
.build());
}
}
resources:
example:
type: aws:lambda:Invocation
properties:
functionName: ${exampleAwsLambdaFunction.functionName}
triggers:
function_version: ${exampleAwsLambdaFunction.version}
config_hash:
fn::invoke:
function: std:sha256
arguments:
input:
fn::toJSON:
environment: ${environment}
timestamp:
fn::invoke:
function: std:timestamp
arguments: {}
return: result
return: result
input:
fn::toJSON:
operation: process_data
environment: ${environment}
batch_id: ${batchId.result}
The triggers property accepts a map of arbitrary keys and values. When any trigger value changes, Pulumi re-invokes the function with the updated input. This example uses function version and a config hash as triggers, ensuring the function runs whenever either changes. The input payload can reference dynamic values that vary between invocations.
Handle create, update, and delete lifecycle events
Infrastructure provisioning often requires coordination with external systems that need notification during resource creation, updates, and cleanup.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.lambda.Invocation("example", {
functionName: exampleAwsLambdaFunction.functionName,
input: JSON.stringify({
resource_name: "database_setup",
database_url: exampleAwsDbInstance.endpoint,
credentials: {
username: dbUsername,
password: dbPassword,
},
}),
lifecycleScope: "CRUD",
});
import pulumi
import json
import pulumi_aws as aws
example = aws.lambda_.Invocation("example",
function_name=example_aws_lambda_function["functionName"],
input=json.dumps({
"resource_name": "database_setup",
"database_url": example_aws_db_instance["endpoint"],
"credentials": {
"username": db_username,
"password": db_password,
},
}),
lifecycle_scope="CRUD")
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/lambda"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
tmpJSON0, err := json.Marshal(map[string]interface{}{
"resource_name": "database_setup",
"database_url": exampleAwsDbInstance.Endpoint,
"credentials": map[string]interface{}{
"username": dbUsername,
"password": dbPassword,
},
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = lambda.NewInvocation(ctx, "example", &lambda.InvocationArgs{
FunctionName: pulumi.Any(exampleAwsLambdaFunction.FunctionName),
Input: pulumi.String(json0),
LifecycleScope: pulumi.String("CRUD"),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.Lambda.Invocation("example", new()
{
FunctionName = exampleAwsLambdaFunction.FunctionName,
Input = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["resource_name"] = "database_setup",
["database_url"] = exampleAwsDbInstance.Endpoint,
["credentials"] = new Dictionary<string, object?>
{
["username"] = dbUsername,
["password"] = dbPassword,
},
}),
LifecycleScope = "CRUD",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.lambda.Invocation;
import com.pulumi.aws.lambda.InvocationArgs;
import static com.pulumi.codegen.internal.Serialization.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Invocation("example", InvocationArgs.builder()
.functionName(exampleAwsLambdaFunction.functionName())
.input(serializeJson(
jsonObject(
jsonProperty("resource_name", "database_setup"),
jsonProperty("database_url", exampleAwsDbInstance.endpoint()),
jsonProperty("credentials", jsonObject(
jsonProperty("username", dbUsername),
jsonProperty("password", dbPassword)
))
)))
.lifecycleScope("CRUD")
.build());
}
}
resources:
example:
type: aws:lambda:Invocation
properties:
functionName: ${exampleAwsLambdaFunction.functionName}
input:
fn::toJSON:
resource_name: database_setup
database_url: ${exampleAwsDbInstance.endpoint}
credentials:
username: ${dbUsername}
password: ${dbPassword}
lifecycleScope: CRUD
Setting lifecycleScope to “CRUD” causes Pulumi to invoke the function during all lifecycle transitions. Pulumi injects a “tf” key into the input JSON with two subkeys: “action” (create, update, or delete) and “prev_input” (the previous invocation’s payload). Your Lambda function can inspect these values to handle each lifecycle event appropriately. During updates, prev_input contains the old configuration; during deletes, it contains the final configuration before removal.
Beyond these examples
These snippets focus on specific invocation features: one-time and trigger-based invocation, and lifecycle event handling. They’re intentionally minimal rather than full orchestration solutions.
The examples assume pre-existing infrastructure such as Lambda functions with appropriate IAM execution roles, and IAM permissions to invoke Lambda functions. They focus on configuring the invocation rather than provisioning the Lambda functions themselves.
To keep things focused, common invocation patterns are omitted, including:
- Function versioning and aliases (qualifier)
- Error handling and retry logic
- Asynchronous invocation patterns
- Custom lifecycle key naming (terraformKey)
These omissions are intentional: the goal is to illustrate how each invocation feature is wired, not provide drop-in orchestration modules. See the Lambda Invocation resource reference for all available configuration options.
Let's invoke AWS Lambda Functions
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Invocation Behavior & Triggers
triggers property with values that change when you want the function to run (like a timestamp or configuration hash).triggers property with a map of keys and values. When any trigger value changes, the function is re-invoked. For example, set function_version or a hash of your configuration as trigger values.CRUD Lifecycle Management
CREATE_ONLY (default) invokes your Lambda function only during resource creation or replacement. CRUD invokes the function on every lifecycle event: create, update, and delete. With CRUD, your function receives additional lifecycle information in the input payload.lifecycleScope is set to CRUD, a tf key is automatically injected into your input JSON. It contains action (create/update/delete) and prev_input (the previous invocation payload). If you need to use tf for your own data, override the key name with the terraformKey argument.lifecycleScope to CRUD. Your function will receive a tf.action field with values create, update, or delete. For updates and deletes, tf.prev_input contains the previous invocation’s input payload.Common Errors & Troubleshooting
Using a different cloud?
Explore serverless guides for other cloud providers: