Envelopes¶
Envelope packages extend the official AWS Lambda event types (SQS, SNS, API Gateway, etc.) with
strongly typed payload accessors. Instead of deserializing JSON manually, you work with
BodyContent<T>, MessageContent<T>, or similar properties that the framework populates before your
handler executes.
Behind the scenes, aws-lambda-host injects the UseExtractAndPackEnvelope middleware at the end of
every pipeline. That middleware automatically calls IRequestEnvelope.ExtractPayload before your
handler runs and IResponseEnvelope.PackPayload after it finishes, guaranteeing consistent
serialization for both built-in envelopes and your own custom envelope types.
Why Envelopes?¶
- Strong typing –
SqsEnvelope<Foo>ensures handlers only run when payloads deserialize intoFoo. - Zero boilerplate – No more
JsonSerializer.Deserializecalls sprinkled through handlers. - Consistent serialization –
EnvelopeOptionsapplies globally, including Native AOTJsonSerializerContextsupport. - Extensible – Implement
IRequestEnvelope/IResponseEnvelopefor proprietary event shapes or alternative serialization formats (XML, Protobuf, etc.).
Provided Envelopes¶
Install only the envelopes you need; each one lives in its own NuGet package.
| Event Source | Package | NuGet |
|---|---|---|
| SQS | AwsLambda.Host.Envelopes.Sqs | |
| SNS | AwsLambda.Host.Envelopes.Sns | |
| API Gateway / HTTP API | AwsLambda.Host.Envelopes.ApiGateway | |
| Kinesis Data Streams | AwsLambda.Host.Envelopes.Kinesis | |
| Kinesis Data Firehose | AwsLambda.Host.Envelopes.KinesisFirehose | |
| Kafka (MSK / self-managed) | AwsLambda.Host.Envelopes.Kafka | |
| CloudWatch Logs | AwsLambda.Host.Envelopes.CloudWatchLogs | |
| Application Load Balancer (ALB) | AwsLambda.Host.Envelopes.Alb |
Each package ships with README examples in the repository if you need event-specific guidance.
Quick Start¶
Install the envelope package that matches your event source, then use the envelope type in your
handler. This SQS example demonstrates the pattern; swap SqsEnvelope<T> with another envelope type
to handle SNS, API Gateway, etc.
Custom Serialization & EnvelopeOptions¶
All envelope packages respect the global EnvelopeOptions configuration. Call
builder.Services.ConfigureEnvelopeOptions to tweak System.Text.Json behavior, register
JsonSerializerContext instances for Native AOT, or enable XML readers/writers for custom envelopes.
The framework automatically copies JsonOptions.TypeInfoResolver into the internal
LambdaDefaultJsonOptions, so every envelope (including complex ones like CloudWatch Logs) gains the
same serialization metadata.
Need XML or another format? Set options.XmlReaderSettings / XmlWriterSettings and implement your
envelope using System.Xml. See the SQS README in the repo for a complete XML sample.
Advanced Configuration¶
LambdaDefaultJsonOptions– aws-lambda-host maintains a secondJsonSerializerOptionsinstance for Lambda-specific envelopes (e.g., SNS→SQS fan-out). Most apps shouldn’t touch it; the host copies yourJsonOptions.TypeInfoResolverautomatically. Only override it when you need different converters for those hybrid envelopes.-
Itemsdictionary – Store arbitrary context for custom envelopes:Program.cs Inside your envelope implementation, read
options.Itemsto control validation or routing logic.
Creating Custom Envelopes¶
Implement IRequestEnvelope and/or IResponseEnvelope when you control the event schema or need a
non-standard payload format. The middleware automatically invokes these interfaces, so you only write
the extraction logic.
In a handler:
| Program.cs | |
|---|---|
Response envelopes work the same way—implement IResponseEnvelope and serialize into a string
property inside PackPayload.
Batch Envelopes¶
If your custom event contains multiple records (similar to SQS), deserialize each entry inside
ExtractPayload. Keep the original serialized string plus a [JsonIgnore] property for the strongly
typed object.
Best Practices¶
- Check for null – Always guard against
BodyContent/PayloadContentbeingnull. Set it tonullif deserialization fails instead of throwing. - Use
[JsonIgnore]– Keep serialized strings (Body,Payload, etc.) separate from the deserialized object to avoid recursive serialization. - Return
SQSBatchResponsewhen required – For SQS/SNS to SQS fan-out scenarios, populateBatchItemFailuresto signal per-message errors. - Centralize configuration – Prefer
ConfigureEnvelopeOptionsor configuration binding over ad-hoc serializer tweaks. - Log deserialization issues – Logging helps diagnose malformed payloads without crashing the Lambda.
When to Use Envelopes¶
Choose envelopes whenever:
- You want compile-time type checking for Lambda payloads.
- Your event contains nested JSON/XML that you’d otherwise deserialize manually.
- You need consistent serialization between request and response envelopes (API Gateway, ALB).
- You’re preparing for Native AOT and want the serialization metadata defined in one place.
Not every Lambda needs an envelope—handlers that already consume strongly typed SDK models can rely on the base event types. Mix and match envelopes based on the triggers your project uses.