Skip to content

Add AWS Lambda response streaming support #348

@j-d-ha

Description

@j-d-ha

Motivation

AWS released preview response streaming support for .NET Lambda packages in release_2026-05-06:

  • Amazon.Lambda.Core 3.0.0: adds preview response streaming APIs.
  • Amazon.Lambda.RuntimeSupport 2.0.0: adds runtime support for sending streaming responses.
  • Amazon.Lambda.AspNetCoreServer(.Hosting): adds opt-in ASP.NET Core response streaming support.

MinimalLambda currently uses a buffered response model (Func<Stream, ILambdaContext, Task<Stream>>, InvocationDataFeature.ResponseStream = MemoryStream). That makes every response materialize before Lambda sends it. Response streaming would enable:

  • lower time-to-first-byte for long-running handlers,
  • LLM/token streaming and progressive output,
  • large generated exports without buffering entire payloads in memory,
  • responses above the classic 6 MB buffered payload limit where supported by Lambda invocation mode.

What AWS added

Public API surface in Amazon.Lambda.Core

New namespace: Amazon.Lambda.Core.ResponseStreaming

Important types:

  • LambdaResponseStreamFactory
    • CreateStream()
    • CreateHttpStream(HttpResponseStreamPrelude prelude)
  • LambdaResponseStream : Stream
    • write-only
    • non-seekable
    • BytesWritten
  • HttpResponseStreamPrelude
    • StatusCode
    • Headers
    • MultiValueHeaders
    • Cookies

Key behavior from package source/docs:

  • Once a Lambda function creates a response stream, all output must be written to that stream.
  • Handler return value is ignored after stream creation.
  • CreateHttpStream writes an HTTP response prelude first; status/headers/cookies must be known before body bytes.
  • Feature is marked [RequiresPreviewFeatures] and requires <EnablePreviewFeatures>true</EnablePreviewFeatures>.

Example shape:

#pragma warning disable CA2252

var prelude = new HttpResponseStreamPrelude
{
    StatusCode = HttpStatusCode.OK,
    Headers =
    {
        ["Content-Type"] = "text/plain"
    }
};

await using var stream = LambdaResponseStreamFactory.CreateHttpStream(prelude);
await stream.WriteAsync("hello\n"u8.ToArray());
await stream.WriteAsync("world\n"u8.ToArray());

#pragma warning restore CA2252

Runtime support in Amazon.Lambda.RuntimeSupport

The runtime support implementation:

  • initializes a per-invocation stream context,
  • starts a streaming HTTP POST to Lambda Runtime API,
  • sends Lambda-Runtime-Function-Response-Mode: streaming,
  • uses HTTP/1.1 chunked transfer encoding,
  • writes errors via trailing headers (Lambda-Runtime-Function-Error-Type, Lambda-Runtime-Function-Error-Body),
  • completes stream after handler returns or reports error.

Preview caveat from AWS package message: until managed .NET Lambda runtime client supports response streaming, use executable deployment with latest Amazon.Lambda.RuntimeSupport and enable preview features.

Proposed MinimalLambda support

Add response streaming as opt-in feature, not default behavior.

Possible API

Expose a MinimalLambda-owned abstraction so AWS preview types do not leak everywhere:

public interface ILambdaResponseStreamingFeature
{
    bool IsAvailable { get; }
    bool HasStarted { get; }

    Stream CreateStream();
    Stream CreateHttpStream(LambdaHttpResponsePrelude prelude);
}

public sealed class LambdaHttpResponsePrelude
{
    public int? StatusCode { get; set; }
    public IDictionary<string, string> Headers { get; } = new Dictionary<string, string>();
    public IDictionary<string, IList<string>> MultiValueHeaders { get; } = new Dictionary<string, IList<string>>();
    public IList<string> Cookies { get; } = new List<string>();
}

Implementation can adapt to Amazon.Lambda.Core.ResponseStreaming.HttpResponseStreamPrelude internally behind #if NET8_0_OR_GREATER and preview warnings.

Pipeline behavior

  • Register response streaming feature per invocation when available.
  • If stream is created, skip normal buffered serializer/response stream path.
  • If no stream is created, preserve existing behavior.
  • Ensure only one stream can be created per invocation.
  • Ensure status/headers are finalized before first body write for HTTP streaming.
  • Decide error behavior:
    • if error before stream creation: existing Lambda error path,
    • if error after stream creation: let Amazon.Lambda.RuntimeSupport report streaming trailers.

Host options

Possible opt-in:

builder.Services.Configure<LambdaHostOptions>(options =>
{
    options.EnableResponseStreaming = true;
});

Need decide exact option location/name.

Targeting / dependencies

Likely requirements:

  • net8.0+ only for streaming implementation.
  • Amazon.Lambda.Core >= 3.0.0.
  • Amazon.Lambda.RuntimeSupport >= 2.0.0.
  • <EnablePreviewFeatures>true</EnablePreviewFeatures> where streaming support is enabled/compiled.
  • AOT/trimming review: avoid reflection/dynamic paths.

Acceptance criteria

  • MinimalLambda can expose a per-invocation streaming Stream without forcing buffered MemoryStream response.
  • Existing buffered response behavior remains unchanged by default.
  • Streaming can be enabled explicitly via host/configuration option.
  • Streaming implementation compiles only where AWS package supports it (net8.0+).
  • Preview warnings are contained/documented.
  • Tests cover:
    • no stream created => buffered path used,
    • stream created => serializer/buffered response skipped,
    • second stream creation fails or is prevented,
    • HTTP prelude maps status, headers, multi-value headers, cookies,
    • errors before vs after stream creation.
  • Docs include deployment notes for executable/latest Amazon.Lambda.RuntimeSupport, function URL/API Gateway streaming invocation modes, and current preview caveats.

References

AWS release:

AWS Lambda response streaming docs:

AWS announcement/background:

aws-lambda-dotnet source areas to inspect:

  • Libraries/src/Amazon.Lambda.Core/ResponseStreaming/
  • Libraries/src/Amazon.Lambda.RuntimeSupport/Bootstrap/ResponseStreaming/
  • Libraries/src/Amazon.Lambda.AspNetCoreServer/ response streaming additions

Relevant upstream discussion/issues:

MinimalLambda current buffered areas to inspect:

  • src/MinimalLambda/Runtime/LambdaBootstrapAdapter.cs
  • src/MinimalLambda/Runtime/LambdaHandlerComposer.cs
  • src/MinimalLambda/Core/Features/InvocationDataFeature.cs
  • src/MinimalLambda/Core/Features/InvocationDataFeatureFactory.cs

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions