Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Choose your framework/language

Page updated Jan 8, 2025

Custom functions

AWS Amplify Gen 2 functions are AWS Lambda functions that can be used to perform tasks and customize workflows in your Amplify app. Functions can be written in Node.js, Python, Go, or any other language supported by AWS Lambda.

Note: Fullstack Git-based environments do not support Docker for functions bundling out of the box.

In this guide, you will learn how to create Python and Go functions with Amplify functions. The examples shown in this guide do not use Docker to build functions. Instead, the examples use commands that run on your host system to build, and as such require the necessary tooling for the language you are using for your functions.

Python

To get started, create a new directory and a resource file, amplify/functions/say-hello/resource.ts. Then, define the function with defineFunction:

amplify/functions/say-hello/resource.ts
import { execSync } from "node:child_process";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { defineFunction } from "@aws-amplify/backend";
import { DockerImage, Duration } from "aws-cdk-lib";
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda";
const functionDir = path.dirname(fileURLToPath(import.meta.url));
export const sayHelloFunctionHandler = defineFunction(
(scope) =>
new Function(scope, "say-hello", {
handler: "index.handler",
runtime: Runtime.PYTHON_3_9, // or any other python version
timeout: Duration.seconds(20), // default is 3 seconds
code: Code.fromAsset(functionDir, {
bundling: {
image: DockerImage.fromRegistry("dummy"),
local: {
tryBundle(outputDir: string) {
execSync(
`python3 -m pip install -r ${path.join(functionDir, "requirements.txt")} -t ${path.join(outputDir)} --platform manylinux2014_x86_64 --only-binary=:all:`
);
execSync(`rsync -rLv ${functionDir}/* ${path.join(outputDir)}`);
return true;
},
},
},
}),
})
);

Next, create the corresponding handler file at amplify/functions/say-hello/index.py. This is where your function code will go.

amplify/functions/say-hello/index.py
import json
def handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message": "Hello World",
}),
}

The handler file must export a function named "handler". This is the entry point to your function. For more information on writing functions, refer to the AWS documentation for Lambda function handlers using Python.

If you need Python packages, you can add them to a requirements.txt file in the same directory as your handler file. The bundling option in the Code.fromAsset method will install these packages for you. Create a requirements.txt file in the same directory as your handler file. This file should contain the names of the packages you want to install. For example:

amplify/functions/say-hello/requirements.txt
request==2.25.1
some-other-package>=1.0.0

You're now ready to deploy your python function. Next is the same process as the Node.js/TypeScript function. Go to Common steps for all languages to continue.

Go

To get started, Create a new directory and a resource file, amplify/functions/say-hello/resource.ts. Then, define the function with defineFunction:

amplify/functions/say-hello/resource.ts
import { execSync } from "node:child_process";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
import { defineFunction } from "@aws-amplify/backend";
import { DockerImage, Duration } from "aws-cdk-lib";
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda";
import { defineFunction } from "@aws-amplify/backend";
import { DockerImage, Duration } from "aws-cdk-lib";
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda";
export const sayHelloFunctionHandler = defineFunction(
(scope) =>
new Function(scope, "say-hello", {
handler: "bootstrap",
runtime: Runtime.PROVIDED_AL2023,
timeout: Duration.seconds(3), // default is 3 seconds
code: Code.fromAsset(functionDir, {
bundling: {
image: DockerImage.fromRegistry("dummy"),
local: {
tryBundle(outputDir: string) {
execSync(`rsync -rLv ${functionDir}/* ${path.join(outputDir)}`);
execSync(
`cd ${path.join(outputDir)} && GOARCH=amd64 GOOS=linux go build -tags lambda.norpc -o ${path.join(outputDir)}/bootstrap ${functionDir}/main.go`
);
return true;
},
},
},
}),
}),
);

Next, create the corresponding handler file at amplify/functions/say-hello/main.go. This is where your function code will go.

amplify/functions/say-hello/main.go
package main
import (
"context"
"fmt"
"github.com/aws/aws-lambda-go/lambda"
)
type Event struct {
Arguments Arguments `json:"arguments"`
}
type Arguments struct {
Title string `json:"phone"`
Msg string `json:"msg"`
}
func HandleRequest(ctx context.Context, event Event) (string, error) {
fmt.Println("Received event: ", event)
// fmt.Println("Message sent to: ", event.Arguments.Msg)
// You can use lambda arguments in your code
return "Hello World!", nil
}
func main() {
lambda.Start(HandleRequest)
}

Then you should run the following command to build the go function:

terminal
go mod init lambda

then run to install the dependencies.

terminal
go mod tidy

You're now ready to deploy your golang function. Next is the same process as the Node.js/TypeScript function.

Common steps for all languages

Regardless of the language used, your function needs to be added to your backend.

amplify/backend.ts
import { sayHelloFunctionHandler } from './functions/say-hello/resource';
defineBackend({
sayHelloFunctionHandler,
});

Now when you run npx ampx sandbox or deploy your app on Amplify, it will include your function.

To invoke your function, we recommend adding your function as a handler for a custom query with your Amplify Data resource. To get started, open your amplify/data/resource.ts file and specify a new query in your schema:

amplify/data/resource.ts
import { sayHelloFunctionHandler } from "../functions/say-hello/resource"
const schema = a.schema({
sayHello: a
.query()
.arguments({
name: a.string(),
})
.returns(a.string())
.handler(a.handler.function(sayHelloFunctionHandler)),
})
export type Schema = ClientSchema<typeof schema>
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: "iam",
},
})