Create functions
This page will help you get started with Functions. It describes how to create your function source files.
Choose your programming language:
# Prepare project
Before creating a TypeScript function, prepare your project by doing the following:
Add the
@netlify/functions
module to your project to import typings for TypeScript.npm install @netlify/functions
Set up
tsconfig.json
. We recommend that you enable the propertiesesModuleInterop
andverbatimModuleSyntax
in your TypeScript configuration file for better compatibility. During the build process, Netlify automatically loads anytsconfig.json
configuration files found in your functions directory, the repository root directory, or the base directory, if set.
# Create function file
To add a serverless function to your project, create a TypeScript file in your functions directory following the instructions below for naming and coding your function. Netlify will access the functions directory during every build, preparing and deploying each supported code file as a function.
The default functions directory is YOUR_BASE_DIRECTORY/netlify/functions
. You can optionally configure a custom functions directory.
# Name your function
You can store your function file directly under the functions directory or in a subdirectory dedicated to the function. The function’s endpoint name is case-sensitive and determined by its filename or the name of its dedicated parent directory.
For example, to create a function with an endpoint name of hello
, save the function file in one of the following ways:
netlify/functions/hello.ts
netlify/functions/hello/hello.ts
netlify/functions/hello/index.ts
These formats would deploy a synchronous function that can be called on the following endpoint, relative to the base URL of your site: /.netlify/functions/hello
.
To create a background function, append the function name with -background
. For example, to create a background function with an endpoint name of hello-background
, save the function file in one of these ways:
netlify/functions/hello-background.ts
netlify/functions/hello-background/hello-background.ts
netlify/functions/hello-background/index.ts
These formats would deploy a background function that can be called on the following endpoint, relative to the base URL of your site: /.netlify/functions/hello-background
.
Reserved names for event-driven functions
Certain function names are reserved as triggers initiated by various built-in events on your Netlify site. You can find a list of these function names and how they work on the page about event-driven functions.
# Code your function
This section covers basic syntax to help you learn how to write functions.
# Synchronous function format
To create a synchronous function, use the following general syntax in your TypeScript function file to export a handler
method:
import type { Handler, HandlerEvent, HandlerContext } from "@netlify/functions";
const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => {
// your server-side functionality
};
export { handler };
Import types before declaring the function.
- If you import the
Handler
type as demonstrated in the previous code sample, theevent
andcontext
arguments and the response are typed accordingly. - Alternatively, you can import the types
HandlerEvent
,HandlerContext
, andHandlerResponse
separately and use them to construct ahandler
function.
Netlify provides the event
and context
parameters when the function is invoked.
The
event
object received by thehandler
is similar to the following:{ "path": "Path parameter (original URL encoding)", "httpMethod": "Incoming request’s method name", "headers": {Incoming request headers}, "queryStringParameters": {Query string parameters}, "body": "A JSON string of the request payload", "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encoded" }
If you need to parse a
multipart/form-data
-encodedevent.body
, we recommend using busboy. To learn more, visit our blog article on processing multipart form data with Netlify Functions.The
context
object received by thehandler
includes information about the context in which the function was called, like certain Identity user information, for example.
Here’s a basic example function, hello.ts
:
import type { Handler, HandlerEvent, HandlerContext } from "@netlify/functions";
const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => {
return {
statusCode: 200,
body: JSON.stringify({ message: "Hello World" }),
};
};
export { handler };
- This function deploys to an endpoint at
/.netlify/functions/hello
relative to the base URL of your site. - A successful invocation returns the
200
status code and the string, “Hello, World”.
Synchronous functions can return a response object that includes the following information:
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
"body": "..."
}
- Because
async
function code returns apromise
, we recommend returning a response with at least an HTTP status code instead of allowing the function to time out. Usingasync
in your function code doesn’t automatically designate a function as a background function.
# Background function format
This feature is in BETA
and may not be available on all plans.
To create a background function, append the function name with -background
. For example, netlify/functions/hello-background.ts
or netlify/functions/hello-background/index.ts
.
Background function syntax is similar to synchronous function syntax, but you will generally pass the function result to a destination other than the originating client. Like the synchronous function format, each TypeScript file to be deployed as a background function must import types and export a handler
method. As with synchronous function invocation, Netlify provides the event
and context
parameters when a background function is invoked. Although background functions rely on asynchronous invocation, they don’t require the use of async
TypeScript syntax.
Here’s a simplified example background function that you can use to test that your function runs longer than 10 seconds, count-background.ts
:
import type { BackgroundHandler, HandlerEvent, HandlerContext} from "@netlify/functions";
export const handler: BackgroundHandler = (event: HandlerEvent, context: HandlerContext) => {
const sleep = (ms: number) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
(async () => {
for (let i = 0; i <= 60; i++) {
const date = new Date();
await sleep(1000);
console.log(date.toLocaleString(), i);
}
console.log("Done");
})();
};
This function deploys to an endpoint at
/.netlify/functions/count-background
relative to the base URL of your site.When invoked, the function returns an initial
202
success response.When successfully executed, the function logs numbers 1 through 60.
Real-time logs only
The Background Functions beta currently supports only real-time logs. You can’t use the function log date filter to explore log history.
For an extended example that demonstrates a more likely background function use case, consider this send-pdf-background.ts
function:
import { jsPDF } from "jspdf";
import mailgun from "mailgun-js";
import type { BackgroundHandler, HandlerEvent } from "@netlify/functions";
type Context = {
content: string;
destination: string;
};
const mg = mailgun({
apiKey: process.env.MAILGUN_API_KEY,
domain: process.env.MAILGUN_DOMAIN,
});
const handler: BackgroundHandler = async (event: HandlerEvent) => {
if (!event.body) {
return;
}
const { content, destination } = JSON.parse(event.body) as Context;
console.log(`Sending PDF report to ${destination}`);
const report = Buffer.from(
new jsPDF().text(content, 10, 10).output("arraybuffer")
);
const info = await mg.messages().send({
from: process.env.MAILGUN_SENDER,
to: destination,
subject: "Your report is ready!",
text: "Details in attached report PDF",
attachments: [
{
filename: `report-${new Date().toDateString()}.pdf`,
content: report,
contentType: "application/pdf",
},
],
});
console.log(`PDF report sent: %s`, info.id);
};
export { handler };
- This background function deploys to an endpoint at
/.netlify/functions/send-pdf-background
relative to the base URL of your site. - When invoked, the function returns an initial
202
success response. - When successfully executed, a PDF report is generated and emailed as an attachment.
# Environment variables
Netlify Functions have access to environment variables in the runtime environment. If you have the option to set specific scopes for your environment variables, the scope must include Functions to be available to functions during runtime.
You can also leverage build environment variables to configure how Netlify builds your functions. For example, you can use an environment variable to set the Node.js version.
Learn more about how to set and use environment variables with functions.
# Manage dependencies
To optimize build performance, specify function dependencies in the top-level package.json
file in the site’s base directory. Here’s an example of a recommended layout:
my-base-directory/
├─ package.json
├─ node_modules
└─ netlify/
└─ functions/
├─ hello.ts
└─ send-pdf-background.ts
With continuous deployment, Netlify automatically zips dependencies with your functions for deployment. To do this, Netlify’s buildbot installs your dependencies and parses each function file to note its dependencies. For each function, Netlify then pulls the required dependencies from the associated node_modules
folder and zips them with the function file for deployment. For more details about how this bundling functionality works, visit the repository for the underlying module: @netlify/zip-it-and-ship-it.
Dependencies and bundling
If you are using devDependencies
in your package.json
file, they won’t be bundled in your functions. We recommend using dependencies
instead of devDependencies
.
If you’re using a Netlify configuration file to configure custom [functions]
settings, note that the node_bundler
value for TypeScript functions always overrides to esbuild
.
# Test locally
To streamline writing and testing your functions on Netlify, run a local development environment with Netlify Dev. This feature of Netlify CLI includes tools for local function development through a simulated Netlify production environment. The netlify dev
command starts a framework server if a framework is detected and handles redirects, proxy rules, environment variables, and Netlify Functions.
To simulate Netlify Functions in a standalone server without the full overhead of Netlify Dev, serve functions locally with the netlify functions:serve
CLI command (currently in beta). Then to debug functions, inspect the functions server process.
# Type check
Because Netlify’s build system doesn’t perform type checking, we recommend that you type check locally with one of these options:
- Use your code editor to type check during local development.
- Use the official TypeScript compiler, running
tsc --noEmit
locally before committing the files.
# Next steps
Push your function source files to your Git provider for continuous deployment where Netlify’s build system automatically detects, builds, and deploys your functions. For more control over the process, learn about other workflows for deploying your functions including custom builds with continuous deployment and manual deploys with the Netlify CLI or API.
Monitor function logs to observe and help troubleshoot your deployed functions.
Did you find this doc useful?
Your feedback helps us improve our docs.