News & Announcements

Introducing Netlify Functions 2.0

When we first introduced Netlify Functions over five years ago, we pioneered a workflow in which developers write backend code that is version-controlled, built, and deployed alongside their frontend application — without having to ever worry about scaling or managing servers.

We’ve iterated on this initial proposition over time by introducing Background Functions, Scheduled Functions, support for response streaming, and Edge Functions. These have made functions an essential building block for developers and frameworks on Netlify.

As part of a renewed commitment to expand our core platform primitives, we are excited to announce the biggest leap we’ve ever taken in the developer experience for Netlify Functions.

Every one of these changes has the clear goal of empowering developers to create complex applications by simply using the platform, leveraging industry standards, without getting locked in to any specific framework or tooling.

New functions API

The first iteration of Netlify Functions exposed the API surface of the underlying compute provider, AWS Lambda. We are now introducing a brand new, modern API, built on web platform standards, that we think will dramatically improve the developer experience of authoring functions.

Functions are now defined as methods that receive a standard Request and return a standard Response, in line with the Edge Functions API.

A Netlify-specific Context object gives you access to information about the incoming request, like geolocation, IP address, and metadata pertaining to your site and deploy. It also provides a convenient way to manipulate cookies:

import { Context } from "@netlify/functions"

export default async (req: Request, context: Context) => {
  if (context.cookies.get("chocolate")) {
    return new Response("Sorry, no more cookies for you")
  }

  context.cookies.set("chocolate", "yummy")

  return new Response("Here's a chocolate cookie! 🍪")
}

Custom endpoints

When you create a function, Netlify automatically creates an endpoint with the format /.netlify/functions/<function name> so you can start interacting with your code straight away. However, often times developers want to serve their functions on a different endpoint, which historically was achieved by creating a redirect rule pointing to the function endpoint.

We’re making that a lot easier by letting you specify the function endpoint within the function code itself, using a new config export:

import { Config, Context } from "@netlify/functions"

export default async (req: Request, context: Context) => {
  return new Response(`Your IP is ${context.ip}`)
}

export const config: Config = {
  path: "/whatismyip"
}

When you deploy the function above, it will be served on the /whatismyip URL path — no redirect rules required.

Advanced routing

When using functions to build API endpoints, developers often have to process input from URL parameters, which can quickly grow into a complex router that you shouldn’t have to build over and over again.

We’re now making it possible to define custom endpoints using the URLPattern web platform standard, with the full power of wildcards and named groups, and access the extracted values conveniently inside the function:

import { Config, Context } from "@netlify/functions";

export default async (req: Request, context: Context) => {
  const { city, country } = context.params

  return new Response(`Travel guide for ${city} in ${country}!`)
}

export const config: Config = {
  path: "/travel-guide/:country/:city"
}

When you deploy the code above and access /travel-guide/portugal/lisbon, the function will return Travel guide for Lisbon in Portugal.

HTTP method matching

Another common scenario when building non-trivial applications with functions is the need to run some business logic in response to only certain types of requests. For example, you might want to have a function that only runs for POST requests and lets all other requests hit a static file.

That is now possible using the method property of the new config export, which accepts one or more HTTP verbs:

import { Config, Context } from "@netlify/functions";

export default async (req: Request, context: Context) => {
  const data = await req.text()

  await processData(data)

  return new Response("Thank you for your submission!")
}

export const config: Config = {
  method: "POST",
  path: "/form-submission"
}

This capability has also been added to Edge Functions, using the same syntax.

Zero-config streaming

When we launched support for response streaming, we exposed a stream wrapper that developers could use to tell the platform that a function would stream its response.

That requirement is going away with the new API. If you’d like to return a streamed response, you can simply return a standard Response object with a stream as the body:

import { Context } from "@netlify/functions"

export default async (req: Request, context: Context) => {
  const encoder = new TextEncoder()
  const formatter = new Intl.DateTimeFormat("en", { timeStyle: "medium" })
  const body = new ReadableStream({
    start(controller) {
      controller.enqueue(encoder.encode("<html><body><ol>"))
      let i = 0
      const timer = setInterval(() => {
        controller.enqueue(
          encoder.encode(
            `<li>Hello at ${formatter.format(new Date())}</li>\n\n`
          )
        )
        if (i++ >= 5) {
          controller.enqueue(encoder.encode("</ol></body></html>"))
          controller.close()
          clearInterval(timer)
        }
      }, 1000)
    }
  })

  return new Response(body)
}

Lambda compatibility mode

It’s important to clarify that the existing API is not going anywhere and existing functions will continue to work in the same way. In fact, you can still choose to create new functions using this syntax, which can be particularly useful for developers who want to migrate workflows from AWS Lambda into Netlify with minimal refactoring.

You can read more about this in the documentation for the Lambda compatibility mode.

Try it out today

We invite you to try the new functions experience today. Visit our documentation for more information on how to get started.

If you use the Netlify CLI to develop or deploy your functions, make sure you update to version 16.6.2 or above.

Finally, we would love to hear about your experience through our support portal or our community forum. Your feedback played a key role in the development of the improvements we’re announcing today, and will undoubtedly shape the next one.

Want to learn more?

Register for free and tune in to Netlify Compose next week to hear more about Netlify Functions and other exciting primitives announcements.

Keep reading

Recent posts

How do the best dev and marketing teams work together?