khone/koʊ.neɪ/
Experimental
χώνη · funnel

An HTTP microbatching gateway for AWS Lambda.

Khone buffers requests by route and batching dimensions for a few milliseconds, invokes target Lambdas with batched payloads, and routes each per-request response back to the original caller. It deliberately trades a few milliseconds per request for lower target invocation cost and fewer cold starts, especially when handlers are waiting on downstream I/O rather than consuming CPU. That's the whole pitch.

RuntimeRust · LMI
InterfaceFunction URL · RESPONSE_STREAM
StatusExperimental
// microbatching simulatorclients → khone gateway → batched λ invocations
live
clientskhone gatewayλ services (16×)
16
45 ms
avg batch3.2×
invoke cost31%
added p95+165ms
in flight0
01 / Architecture

One funnel,
fewer invocations.

The gateway is a Rust Lambda Function URL router running on Lambda Managed Instances. It accepts HTTP requests, batches inside each execution environment, invokes target Lambdas with batched payloads, and demultiplexes per-request responses back to clients. Batches that exceed the invoke payload limit are split before invocation when possible.

01HTTP requestsHTTP requests arrive at the gateway via Lambda Function URL with RESPONSE_STREAM invoke mode.
02Route matchA compiled route from Spec.paths identifies the target Lambda, method, and key dimensions.
03MicrobatchIn-memory queue per target, route, mode, and key flushes when maxBatchSize, maxWaitMs, or an adaptive policy fires.
04Target LambdaOne or more invocations receive the batched payload and process every item in a single execution context.
05Streaming responseBuffered JSON returns one reply per batch; NDJSON streams per-item events as the handler produces them.
06DemultiplexThe gateway maps each response id back to the waiting client request and streams it home.
02 / Integration

Three integrations for
three handler shapes.

Adopt Khone with the smallest change that fits your workload — from a layer drop-in for handlers that cannot change, to a native batch handler when one invocation should share data loading across all items.

Layer proxyNo code change

Layer Proxy

Mode A

A Lambda layer + Runtime API proxy presents one outer batch invocation as multiple virtual runtime invocations. Existing handlers run unmodified.

  • Drop-in for legacy handlers
  • Runtime-specific (Node, Python)
  • Best when handler changes are out of scope
AdapterAdd an SDK

Adapter

Mode B

A small wrapper preserves the familiar single-request handler shape. The adapter handles batch correlation, per-item errors, and response formatting.

  • Familiar handler signature
  • Per-item error isolation
  • Node and Rust SDKs
Native batchFull control

Native Batch

Mode C

The handler receives the whole batch. Use it when one invocation should share data loading, fan-out, or response generation across all items.

  • Custom batch processing
  • Shared work amortization
  • Streaming via NDJSON
03 / Configuration

Declare it
where it lives.

The KhoneGateway macro creates the gateway Lambda, Function URL, execution role, and config artifact. Your stack supplies target functions and an existing LMI capacity provider.

template.yamlyaml
Transform:
  - AWS::Serverless-2016-10-31
  - KhoneGateway

Resources:
  GatewayService:
    Type: Khone::Gateway::Service
    Properties:
      CapacityProviderArn: !Ref GatewayCapacityProviderArn
      MemorySize: 2048
      Timeout: 30
      ExecutionEnvironmentMemoryGiBPerVCpu: 2.0
      PerExecutionEnvironmentMaxConcurrency: 64
      ConfigPrefix: !Sub "khone/${AWS::StackName}/gateway/"
      GatewayConfig:
        DefaultTimeoutMs: 2000
      Spec:
        openapi: 3.0.0
        paths:
          /items/{id}:
            get:
              x-target-lambda: !GetAtt ItemsFn.Arn
              x-khone:
                maxBatchSize: 16
                maxWaitMs: 35
                invokeMode: response_stream
handler.js (Mode B)javascript
const { batchAdapter } = require("khone-lambda-adapter");

// Single-request handler shape - preserved.
async function handleItem(event) {
  const item = await db.get(event.pathParameters.id);
  return {
    statusCode: 200,
    headers: { "content-type": "application/json" },
    body: JSON.stringify(item),
  };
}

// Adapter handles batch correlation, per-item errors,
// and the NDJSON response framing.
exports.handler = batchAdapter(handleItem);
04 / Performance

Pay less
per request.

The public benchmark normalizes target invocation cost to the standard endpoint, an API Gateway HTTP API plus Lambda baseline, at 100%. In the high-traffic profile,target-aware batching delivered the lowest estimated target cost. The standard endpoint stays fastest because it avoids the gateway hop. Khone trades some of that latency for lower target invocation cost; as a side effect, traffic spikes can stay on warm sandboxes already processing batches instead of forcing new cold starts. The target Lambdas call a backend Lambda URL that simulates delayed downstream responses.

target-aware · 256 MB · high traffic
17.7%

of standard target invocation cost in the curated round-2 high-traffic public report.

ProfileEndpointP95Target cost
Low · 1/10/50 rpsstandard198 ms100.0%
Low · 1/10/50 rpssteady317 ms65.4%
Low · 1/10/50 rpsadaptive283 ms85.1%
Low · 1/10/50 rpstarget-aware463 ms45.1%
High · 50/100/150 rpsstandard197 ms100.0%
High · 50/100/150 rpssteady308 ms32.4%
High · 50/100/150 rpsadaptive304 ms36.2%
High · 50/100/150 rpstarget-aware464 ms17.7%
Target memory: 256 MBBackend Lambda: 80-160 msLMI provider: m8g4 LMI envs · 64 conc/envRound 2: low traffic 0 errors
05 / Documentation

Read your way in.

Start with workload fit and quickstart, deploy the LMI gateway, connect handlers, and keep the exact contracts close when you need them.

Start

Evaluate the fit and deploy a first gateway.

Deploy

Understand and deploy the LMI gateway model.

Operate

Tune and observe a running gateway.

Reference

Look up fields, protocols, APIs, and commands.