# serverless-http turns an Express or Koa app into a Lambda handler without a socket

> serverless-http wraps a normal Node web application so its middleware stack runs inside a serverless invocation, with no listening server and no ports. The payoff is that your existing routes and middleware survive the move to Lambda; the cost is that anything depending on a persistent process, such as in-memory sessions or web sockets, does not come with it.

**dougmoscrop/serverless-http** — Use your existing middleware framework (e.g. Express, Koa) in AWS Lambda 🎉

- Repository: https://github.com/dougmoscrop/serverless-http
- Stars: 1,777 · Forks: 174
- Language: JavaScript
- License: NOASSERTION
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/dougmoscrop-serverless-http

## The wrapper pattern: one call, one exported handler

The module does one thing. You hand it your app object and it returns a handler function that a serverless runtime can invoke. No HTTP server is created, no port is bound, no socket is opened, and the README states that plainly: your code runs in the same execution pipeline you are already familiar with.

The Koa version is concise:

```javascript
const serverless = require('serverless-http');
const Koa = require('koa'); // or any supported framework

const app = new Koa();

app.use(/* register your middleware as normal */);

module.exports.handler = serverless(app);
```

That is the whole migration for a straightforward app. You keep registering middleware exactly as you did, and the only change is what you export.

The README also shows the promise form, which exists because people usually have other work to do around the invocation:

```javascript
const handler = serverless(app);
module.exports.handler = async (event, context) => {
  const result = await handler(event, context);
  return result;
};
```

The Azure example shows why the provider option exists. The signature changes completely, from `(event, context)` to `(context, req)`, and the response is assigned rather than returned:

```javascript
const handler = serverless(app, { provider: 'azure' });
module.exports.funcName = async (context, req) => {
  context.res = await handler(context, req);
}
```

Passing `provider` is what selects that adaptation, so the same app object works on more than one platform with a different export shape.

## Framework support ranges from solid to experimental

The supported framework list is ordered roughly by confidence, and the ordering is the information. Node's own `http.createServer` and Connect sit at the top, followed by Express and Koa, which are the two with real examples in the README.

Below that, everything is marked with an asterisk and the section heading itself says Experimental. That covers Restana, Sails, Hapi, Fastify, Restify, Polka and Loopback. Only one example directory actually ships in the tree, `examples/hapi`, so the Hapi case has something to look at and the rest are asserted rather than demonstrated.

Provider support is narrower. AWS is the primary target and the provider documentation directory, `docs/PROVIDERS.md`, covers it. Genezio is a documented integration with its own deployment guide and a one-click Express hello world deploy button in the README. Azure is described as experimental, untested, and probably outdated, in those words. That is an unusually honest annotation and it should be taken at face value rather than discovered the hard way.

Deeper documentation sits alongside the README in `docs/EXAMPLES.md` for more complete examples and `docs/ADVANCED.md` for advanced configuration options.

## v4.0.0 changed the stream under you

There is one upgrade warning worth reading twice, because it is the only place the README discusses a compatibility hazard.

Version 4.0.0 does not intentionally introduce breaking changes, but it uses a PassThrough stream internally instead of a stub. The README calls this a sensitive area, and says that in order to avoid unintentional breaks a semver major version was used anyway. The advice given is that you should hopefully not have to change anything, but to test thoroughly.

That is the correct characterisation: the public API did not move, the internals under it did. Code that passed 3.x because it depended on a stub never reading from the stream may behave differently once a real PassThrough is in the path. The failure mode would be a hang or a truncated response rather than a thrown error, which is the kind of bug that hides behind a short test.

The manifest is at version 4.0.0 and requires Node `>=12.0`. There are no GitHub releases for this project, so the version in `package.json` is the reference point and `npm` is where you find a tagged build.

The last push was on 2026-10-13 and the repository is not archived.

## What serverless does not fix

The README has a Limitations section, and it is the part to read before porting anything. Your code is running in a serverless environment, so you cannot rely on your server being up in the sense that you should not use in-memory sessions or web sockets. You are also subject to provider specific restrictions on request and response size and on duration.

Those are not style warnings. Code that assumes a persistent process should be reviewed before deployment.

The README's framing of the project is the right one to keep: this is a familiar way of expressing your app logic, not an attempt to make serverless do something it cannot. The wrapper removes the socket, not the constraints of the execution model.

The project favors retaining the familiar middleware model, while leaving the execution-model constraints described in the limitations section in place.

## Test and packaging details in the manifest

The npm scripts show how the project checks itself, which tells you what a change is expected to keep working.

```json
"scripts": {
  "pretest": "tsc --strict --skipLibCheck --noEmit test/typecheck.ts",
  "test": "nyc mocha",
  "posttest": "eslint lib test"
}
```

Type checking runs before the tests rather than alongside them, the unit tests run under mocha with nyc for coverage, and linting of `lib` and `test` runs after. There are also two integration scripts, `test:integration:offline` running `test/integration/test-offline.js` and `test:integration:aws` running `test/integration/test-aws.js`, both with `--exit`.

That split is the practical takeaway for a consumer. The manifest provides separate offline and AWS integration test scripts.

A `serverless-http.d.ts` file sits at the root and is wired as the `types` entry, with `serverless-http.js` as `main`, so TypeScript consumers get declarations without a separate `@types` package. There is an `examples/` folder for the framework samples and a `lib/` directory holding the implementation, with an `.eslintrc` and `.eslintignore` governing style.

One loose end on licensing: the repository metadata flags a custom licence that GitHub cannot classify, and there is a `LICENSE.txt` in the root, while the manifest's `license` field reads MIT. Read `LICENSE.txt` directly rather than relying on either label if redistribution matters to you.

## Conclusion

Teams with an existing Express, Koa or Connect codebase that must run behind API Gateway should adopt serverless-http, since it keeps the middleware stack intact instead of asking for a rewrite. Code that depends on a long-lived process should be reviewed before migration, and the asterisked frameworks are marked experimental in the README. Before upgrading past 3.x, read the note about v4.0.0 replacing a stub with a PassThrough stream and test your handler, since the maintainers took a semver major for that change alone.

## FAQ

### Which frameworks work with serverless-http?

Node's http.createServer, Connect, Express, Koa and Restana are listed without an asterisk. Sails, Hapi, Fastify, Restify, Polka and Loopback are marked experimental, and an hapi example ships in the repository.

### What broke in serverless-http 4.0.0?

The README says v4.0.0 does not intentionally introduce breaking changes. It replaced an internal stub with a PassThrough stream, which it calls a sensitive area, so a semver major was used anyway. The README advises testing thoroughly.

### Can I use in-memory sessions with serverless-http?

You should not rely on in-memory sessions or web sockets in a serverless environment. Provider-specific restrictions also apply to request size, response size and duration.

### Does serverless-http support providers other than AWS Lambda?

It supports AWS as the primary target and Genezio as a documented integration. Azure is supported through a provider option but the README describes it as experimental, untested and probably outdated.

### What Node version does serverless-http need?

The package manifest declares engines node >=12.0, and the current version is 4.0.0.

## Sources

- [dougmoscrop/serverless-http on GitHub](https://github.com/dougmoscrop/serverless-http)
- [Issues](https://github.com/dougmoscrop/serverless-http/issues)
- [README](https://github.com/dougmoscrop/serverless-http/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dougmoscrop-serverless-http
