Skip to content
FLAVIO COPES
flaviocopes.com

Netlify Lambda Functions Tutorial

By

Learn how to create a modern Netlify Function with TypeScript, Web Request and Response APIs, custom routing, local testing, and environment variables.

~~~

Netlify Functions add server-side endpoints to a site without you managing a server.

A modern function receives a standard Web API Request, gets Netlify-specific information from a Context, and returns a Response.

The old callback-based exports.handler syntax still appears in many tutorials, but new functions should use a default export.

Create the project

Start in an existing site or create a small project:

npm init -y
npm install @netlify/functions
npm install --save-dev netlify-cli

Netlify’s default functions directory is netlify/functions/.

Create netlify/functions/hello.mts:

import type { Config, Context } from '@netlify/functions'

export default async (request: Request, context: Context) => {
  const name = new URL(request.url).searchParams.get('name') ?? 'friend'

  return Response.json({
    message: `Hello, ${name}!`,
    requestId: context.requestId
  })
}

export const config: Config = {
  path: '/api/hello',
  method: 'GET'
}

The config export gives the function a clean route. Without a custom path, a function named hello is available at /.netlify/functions/hello.

The functions overview documents the current handler and routing APIs.

Run the function locally

Start Netlify’s local development environment:

npx netlify dev

Call the function from a browser or another terminal:

curl "http://localhost:8888/api/hello?name=Flavio"

The port can differ if it is already in use. Use the URL printed by Netlify CLI.

Read request data

The handler receives a standard Request, so you use familiar Web APIs.

Read the HTTP method:

request.method

Read a header:

request.headers.get('authorization')

Parse JSON from a request body:

const data = await request.json()

Read query parameters:

const url = new URL(request.url)
const page = url.searchParams.get('page')

Validate untrusted input before using it. Return a clear 400 response when the request is invalid.

Return responses

Return plain text:

return new Response('Created', {
  status: 201
})

Return JSON:

return Response.json(
  { error: 'Not found' },
  { status: 404 }
)

Return a method error and advertise the supported method:

return new Response('Method not allowed', {
  status: 405,
  headers: {
    Allow: 'POST'
  }
})

The method field in the function config can restrict which methods route to the handler, but your application should still return intentional responses for the methods it supports.

Use path parameters

Configure a dynamic path:

import type { Config, Context } from '@netlify/functions'

export default async (request: Request, context: Context) => {
  return Response.json({
    id: context.params.id
  })
}

export const config: Config = {
  path: '/api/items/:id',
  method: 'GET'
}

A request to /api/items/42 sets context.params.id to 42.

Store secrets as environment variables

Set a secret through the Netlify UI or CLI:

npx netlify env:set API_KEY "your-secret-value" \
  --secret \
  --scope functions

Read it only in server-side code:

const apiKey = process.env.API_KEY

The value passed on the command line may remain in shell history. For sensitive production values, prefer the Netlify UI or another approved secret-management workflow.

Do not commit .env files containing secrets. Do not return secrets to the browser or expose them through environment-variable prefixes intended for client-side code.

Netlify documents function scopes and configuration in its environment variable guide.

Deploy the function

Commit the function with the rest of the site. A Git-connected Netlify project bundles and deploys it during the normal deploy.

For a manual draft deploy:

npx netlify deploy

Publish only after testing the draft:

npx netlify deploy --prod

Open the deploy summary to verify that Netlify detected the function.

When to write a raw Netlify Function

Write a function directly when you need a standalone API endpoint, webhook, scheduled task, or background task.

Frameworks such as Next.js, Astro, Nuxt, and SvelteKit often generate functions through their Netlify adapters. In that case, use the framework’s route APIs for normal application pages and endpoints instead of duplicating the routing layer.

Start with Netlify’s function setup guide and check the current runtime limits before designing long-running or large-payload work.

Tagged: Services · All topics
~~~

Related posts about services: