Deploys and Redirects with Functions and Express.js

Hi, I am trying to deploy a react app with lambda functions.

Here’s my repo:
And deployed url:

For convenience, here is my netlify.toml and the functions in question:


  functions = "lambda-build"
  command = "npm run build"
  publish = "build"

  from = "/e/*"
  to = "/.netlify/functions/express"
  status = 200

  from = "/d/*"
  to = "/.netlify/functions/default"
  status = 200


import App from '../App.js'
import React from 'react';
import ReactDOMServer from 'react-dom/server';

exports.handler = async (event, context) => {
  const app = ReactDOMServer.renderToString(<App path={event.path} />);

  return {
    statusCode: 200,
    body: app,


import App from '../App.js'
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import express from 'express'
import serverless from 'serverless-http'

const app = express();
const router = express.Router();

router.get('*', async (req, res) => {
  const app = ReactDOMServer.renderToString(<App path={req.path} />);
  return res.status(200).send(app);

app.use('/.netlify/functions/express', router);
exports.handler = serverless(app);

I have two questions:

  1. The functions work when I run netlify dev locally, but they aren’t working when I deploy.

Locally, the route .netlify/functions/default/123 prints .netlify/functions/default/123 on the screen, as expected. when deployed, the same route says “page not found.” You can test this at

Is there anything that needs to be set up in particular to deploy lambda functions?

  1. I want to redirect certain URLs to certain functions. Using netlify dev (where the functions are working), redirects work for the default function syntax but not for Express. I think the issue has to do with the status code not being set correctly, but even if I explicitly set res.status(200) in the express function, the redirect doesn’t work. The express function works fine when I navigate directly to .netlify/functions/express, but using e/123, I see “Cannot GET /e/123” and the logs show:
Request from ::1: GET /.netlify/functions/express
Response with status 404 in 38 ms.
Request from ::1: GET /.netlify/functions/express.html
Response with status 404 in 1 ms.
Request from ::1: GET /.netlify/functions/express.htm
Response with status 404 in 0 ms.
Request from ::1: GET /.netlify/functions/express/index.html
Response with status 404 in 32 ms.
Request from ::1: GET /.netlify/functions/express/index.htm
Response with status 404 in 32 ms.

Hey @dyelax,
The first (and maybe only!) issue is that your functions are not getting uploaded. I can tell because when I look here:
there’s nothing under “Published deploy” at the top that says “View Functions in production”

It looks like you’ve set your functions directory in the netlify.toml to be “lambda-build” but in your repo, the directory is called “lambda-functions”- could you try changing that and see if it fixes things for you?

Hi @jen, thanks for the reply! I’ve resolved my first problem: When I run netlify dev locally, I get a message that says “Function builder netlify-lambda detected: Running npm script lambda-build”. This doesn’t happen when I push to deploy, so I needed to change my build command from npm run build to npm run build && npm run lambda-build. The deployed site now runs the functions.

However, I’m still having the redirect issue. When I use the full /.netlify/functions/express/123 route, I get a 200 response and everything works fine, but when I try the redirect /e/123, I get a 404 if I specify status = 200 in the toml redirect rule. If I get rid of status = 200 in the toml, the redirect works, but doesn’t keep the shortened URL (it switches the url to the full /.netlify/functions/express/123, which I don’t want). I think this indicates that my express function isn’t returning a 200 status for the redirect. Any ideas why that might be?

Hey @dyelax,
I think this is about Express routing and our redirects. To be honest, I don’t fully understand how all the paths change as requests flow through Netlify’s server and the lambda function, but could you try something like this?

router.get("/e/*", (req, res) => {

app.use("/", router);

I made a test here and seems to work as you’re hoping: