@nextrush/adapter-serverlessServerless
Deploy a NextRush app to AWS Lambda, Google Cloud Functions, or Azure Functions in one line.
Run a NextRush app as a serverless function. The adapter separates the execution model (per-invocation, stateless, timeout→504, warm-instance reuse) from each provider's event format — you import one Tier-1 handler and never touch the mapper plumbing underneath.
Source & internals
README · ARCHITECTURE · see also Adapter Contract
| Package | @nextrush/adapter-serverless |
| Status | Beta |
| Support tier | Internal — non--node adapter until GA, may change without a major (ADR-0005) |
Included in nextrush? | No — standalone install |
| Runtime | AWS Lambda, Google Cloud Functions, Azure Functions — built on @nextrush/adapter-edge's fetch engine |
Cloudflare Workers uses a different package
Cloudflare's Tier-1 handler (createCloudflareHandler) ships in
@nextrush/adapter-edge, not here — it
shares the edge execution model, not the serverless one.
Installation
$ pnpm add @nextrush/adapter-serverless
Quick start
import { createApp } from '@nextrush/core';
import { createLambdaHandler } from '@nextrush/adapter-serverless';
const app = createApp();
app.use(async (ctx) => {
ctx.json({ message: 'Hello from Lambda!' });
});
export const handler = createLambdaHandler(app);Tier-1 handlers (what you actually import)
| Function | Platform | Event shapes handled |
|---|---|---|
createLambdaHandler(app, options?) | AWS Lambda | Function URL / API Gateway HTTP API (v2) and REST API (v1) — auto-detected per invocation, no explicit provider needed |
createLambdaStreamingHandler(app, options?) | AWS Lambda response streaming (awslambda.streamifyResponse) | Lambda Function URL streaming |
createGoogleHandler(app, options?) | Google Cloud Functions | HTTP-triggered functions — a (req, res) drop-in for functions.http() |
createAzureHandler(app, options?) | Azure Functions | HTTP-triggered functions (v4 model) — a (req) => response drop-in for app.http() |
// Google Cloud Functions
import { createGoogleHandler } from '@nextrush/adapter-serverless';
import * as functions from '@google-cloud/functions-framework';
functions.http('api', createGoogleHandler(app));// Azure Functions (v4 model)
import { createAzureHandler } from '@nextrush/adapter-serverless';
import { app as functions } from '@azure/functions';
functions.http('api', { handler: createAzureHandler(app) });See Google Cloud Functions deployment and Azure Functions deployment for the full deploy commands and platform-specific configuration these two drop-ins need.
These two signatures changed in 1.0.0-beta.1
Before 1.0.0-beta.1, createGoogleHandler and createAzureHandler took a
normalized event struct that you built from the platform's req yourself. That
behavior is preserved unchanged under the new names
createGoogleEventHandler / createAzureEventHandler — rename your call to
keep an existing hand-written bridge working, or delete the bridge and pass the
drop-in straight to the platform. Reach for the *EventHandler names for
fixture testing, a custom bridge, or a host whose request object is not the
standard SDK shape.
Knowing which platform you are on
ctx.runtime is 'edge' on every provider here — this adapter runs on
@nextrush/adapter-edge's fetch engine, whose runtime detector has no
AWS/GCP/Azure branch. A check for ctx.runtime === 'node' typechecks and never
matches.
ctx.platform is the field that names the provider: 'lambda', 'gcf', or
'azure'. Each Tier-1 handler sets it explicitly, so it is declared rather than
guessed.
import { createLambdaHandler } from '@nextrush/adapter-serverless';
app.use(async (ctx) => {
ctx.json({ platform: ctx.platform, runtime: ctx.runtime });
});
export const handler = createLambdaHandler(app);Each Tier-1 handler accepts ServerlessHandlerOptions:
interface ServerlessHandlerOptions {
/** Per-invocation timeout (ms). Exceeding it produces a 504 result instead of hanging the invocation. */
timeout?: number;
}export const handler = createLambdaHandler(app, { timeout: 5000 });Advanced: building a custom provider (Tier 3)
See Event mapping for how the built-in mappers above translate a
platform event into the same Request/Response every adapter uses — the mental model for what
you're implementing below.
Application developers should stop at the Tier-1 handlers above. Implement
EventMapper only to add a platform NextRush doesn't ship (Oracle, Fly.io,
OpenFaaS, an internal platform):
import { createServerlessAdapter } from '@nextrush/adapter-serverless';
import type { EventMapper } from '@nextrush/adapter-serverless';
const myMapper: EventMapper<MyEvent, MyResult> = {
name: 'my-platform',
toRequest(event) {
/* build a Web Request from the platform event */
},
fromResponse(response, event) {
/* map the Response back to the platform's expected result */
},
};
const adapter = createServerlessAdapter({ mappers: [myMapper] });
export const handler = adapter.createHandler(app);mappers is an immutable, per-adapter registry — there is no global mutable
mapper registry. When more than one mapper is supplied, an explicit
provider name wins; each mapper's optional detect() only runs as a
fallback when no provider is named.
Troubleshooting
Timeout returns a 504 result, not a thrown error
Exceeding timeout produces a 504-shaped result via the platform's normal
response path — it does not reject the returned promise. Check the
response status your platform's logs show, not a caught exception.
Every mapper guards the one field it cannot translate without and throws a named
[nextrush/serverless] error naming the likely cause (a wrong payload format, or
an incomplete hand-written bridge on the *EventHandler path) instead of a raw
TypeError from framework internals. On GCF, a request whose rawBody is absent
while body is already parsed logs a [nextrush/serverless] warning and omits
the body rather than stringifying an object into it.
Because this adapter runs on @nextrush/adapter-edge's engine, that package's
development-mode diagnostics apply here too: the ctx.waitUntil() no-op warning
(serverless invocations supply no execution context), the boot-reuse warning when
createApp() is called inside the exported handler, and the timeout-attribution
log accompanying every 504. See
@nextrush/adapter-edge for the exact messages.
Related
- Platforms overview
@nextrush/adapter-edge— Cloudflare Workers, Vercel Edge, Netlify Edge- Deployment guides