Build serverless functions with JavaScript

To add a serverless Lambda function to your project, create a JavaScript file in your configured functions directory. The file can be stored directly under the functions directory or in a subdirectory dedicated to the function. The function endpoint is determined by its filename or the name of its dedicated parent directory.

For example, with a configured functions directory of my_functions and a target function endpoint name of hello, you could save the function file in one of the following ways:

  • my_functions/hello.js
  • my_functions/hello/hello.js
  • my_functions/hello/index.js

Any of the above formats would deploy a synchronous serverless function that can be called on the following endpoint, relative to the base URL of your site: /.netlify/functions/hello.

For a background function, the function file name must end with -background, or the sub-directory that contains the background function file must end with -background.

With an example configured functions directory of my_functions and a target function endpoint name of hello-background, you could save a background function file in one of these ways:

  • my_functions/hello-background.js
  • my_functions/hello-background/hello-background.js
  • my_functions/hello-background/index.js

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.

Synchronous function format

Each JavaScript file to be deployed as a synchronous serverless Lambda function must export a handler method with the following general syntax:

exports.handler = async function(event, context) {
    // your server-side functionality
}

Netlify provides the event and context parameters when the serverless function is invoked. When you call a serverless function’s endpoint, the handler receives an event object similar to what you would receive from the AWS API Gateway:

{
    "path": "Path parameter",
    "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-encode"
}

The context parameter includes information about the context in which the serverless function was called, like certain Identity user information, for example.

Although Netlify Functions still support callback syntax, async is more versatile. Because async functions return a promise, we recommend returning a response with at least an HTTP status code instead of allowing the function to time out. Using async in your serverless function code doesn't automatically designate a serverless function as a background function.

Here’s a simple example serverless function, hello.js:

exports.handler = async function(event, context) {
    return {
        statusCode: 200,
        body: JSON.stringify({message: "Hello World"})
    };
}

This serverless function would be called from your site at /.netlify/functions/hello, and on success, would return the 200 status code and the message, “Hello, World”.

Synchronous serverless functions can return a response object that includes the following information:

{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}

Background function format

This feature is in BETA and may not be available on all plans.

Background function syntax is similar to synchronous serverless function syntax, but you will generally pass the function result to a destination other than the originating client. Each JavaScript file to be deployed as a background function must export a handler method. Like the synchronous serverless function format, Netlify provides the event and context parameters for background function execution. Although background functions rely on asynchronous invocation, they don't require the use of async JavaScript syntax.

Here's an example of a background function, send-pdf-background.js:

const { jsPDF } = require('jspdf');
const nodemailer = require('nodemailer');
const mg = require('nodemailer-mailgun-transport');

const transporter = nodemailer.createTransport(
  mg({
    auth: {
      api_key: process.env.MAILGUN_API_KEY,
      domain: process.env.MAILGUN_DOMAIN,
    },
  }),
);

exports.handler = async function (event) {
  const { content, destination } = JSON.parse(event.body);
  console.log(`Sending PDF report to ${destination}`);

  const report = Buffer.from(
    new jsPDF().text(content, 10, 10).output('arraybuffer'),
  );
  const info = await transporter.sendMail({
    from: process.env.MAILGUN_SENDER,
    to: destination,
    subject: 'Your report is ready!',
    text: 'See attached report PDF',
    attachments: [
      {
        filename: `report-${new Date().toDateString()}.pdf`,
        content: report,
        contentType: 'application/pdf',
      },
    ],
  });

  console.log(`PDF report sent: ${info.messageId}`);
};

This background function would be called from your site at /.netlify/functions/send-pdf-background. When called, the function is added to a queue with a 202 success response and awaits execution. When successfully executed, a PDF report is generated and emailed as an attachment.

Runtime settings

For all sites created on or after December 4, 2019, Netlify uses Node.js 12 as the default runtime for serverless functions written in JavaScript.

You can specify a different runtime version with an environment variable in the Netlify UI. For example, to use Node.js 10 for all future serverless functions deployed, set the variable AWS_LAMBDA_JS_RUNTIME with the value nodejs10.x.

This variable accepts any valid AWS Lambda runtime name for JavaScript.

Deploy to apply changes

Environment variables and runtime settings are applied to functions at deploy time. Always re-deploy your functions to apply new settings.

Deprecation notice

Sites created before December 4, 2019 use the Node.js 8 function runtime by default.

Node.js 8 reached end of life on December 31, 2019, and AWS Lambda discontinued support for new functions using Node.js 8 on January 6, 2020. Sites not explicitly set to Node.js 10 or above will use the default Node.js 12 version for all deploys of new or updated functions. Previously deployed functions will continue to operate with the runtime set at the time of deployment.

Unbundled JavaScript function deploys

You can use continuous deployment or the Netlify CLI to prepare unbundled JavaScript functions for deployment to AWS. Netlify's build bot looks through a function file to note dependencies. The bot then pulls the required dependencies from the associated node_modules folder and zips them with the function file for deployment.

An unbundled JavaScript function's package.json does not have to be in the same folder as the function file. To optimize build performance, we recommend specifying 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
└─ my-serverless-functions
   └─ hello.js
   └─ send-pdf-background.js

For more details about how this functionality works, visit the repository for the underlying module: @netlify/zip-it-and-ship-it.

Tools

We’ve made a couple of tools to help with writing, testing, and deploying your serverless JavaScript functions on Netlify:

  • Netlify Dev – Netlify CLI includes tools for local function development and streamlined deployment.
  • netlify-lambda – We provide an optional build tool for Netlify Functions that is no longer recommended for new projects or common use cases. The repository README includes a comparison between Netlify Dev and netlify-lambda.