An implementation of the aws lambda runtime for zig
-
⚡ small and fast
Zig is impressively fast and small by default and can be made even faster and smaller with common
optimize
compilation flags. ❄ avg cold start duration11ms
💾 avg memory10MB
⚡ avg duration1-2ms
-
📦 painless and easy packaging
Zig comes with a self-contained build tool that makes cross compilation for aws deployment targets painless
zig build -Dtarget=aarch64-linux -Doptimize={ReleaseFast,ReleaseSmall}
Coming soon...
-
streaming response support
By default aws lambda buffers and then returns a single response to client but can be made streaming with opt in configuration
-
event struct types
At present it is up to lambda functions themselves to parse the and self declare event payloads structures and serialize responses. We would like to provide structs for common aws lambda event and response types to make that easier
Below is an example echo lambda that echo's the event that triggered it.
const std = @import("std");
const lambda = @import("lambda");
pub fn main() !void {
// 👇 wrap a free standing fn in a handler type
var wrapped = lambda.wrap(handler);
// 👇 start the runtime with this handler
try lambda.run(null, wrapped.handler());
}
fn handler(allocator: std.mem.Allocator, context: lambda.Context, event: []const u8) ![]const u8 {
_ = allocator;
_ = context;
return event;
}
Create a new exec project with zig init-exe
. Copy the echo handler example above into src/main.zig
Create a build.zig.zon
file to declare a dependency
.zon short for "zig object notation" files are essentially zig structs.
build.zig.zon
is zigs native package manager convention for where to declare dependencies
.{
.name = "my-first-zig-lambda",
.version = "0.1.0",
.dependencies = .{
+ // 👇 declare dep properties
+ .lambda = .{
+ // 👇 uri to download
+ .url = "https://github.com/softprops/zig-lambda-runtime/archive/refs/tags/v0.2.0.tar.gz",
+ // 👇 hash verification
+ .hash = "12202c21b4111b1b549508847b0de394f2188d16560287e532441457314d7c0671fa",
+ },
},
.minimum_zig_version = "0.12.0",
.paths = .{""},
}
the hash below may vary. you can also depend any tag with
https://github.com/softprops/zig-lambda-runtime/archive/refs/tags/v{version}.tar.gz
or current main withhttps://github.com/softprops/zig-lambda-runtime/archive/refs/heads/main/main.tar.gz
. to resolve a hash, omit it and let zig tell you the expected value.
This library targets the provided lambda runtime, prefer provided.al2023
the latest, which assumes an executable named bootstrap
.
To produce one of these, add the following in your build.zig
file
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
+ // 👇 de-reference lambda dep from build.zig.zon
+ const lambda = b.dependency("lambda", .{
+ .target = target,
+ .optimize = optimize,
+ }).module("lambda");
// 👇 create an execuable named `bootstrap`. the name `bootstrap` is important
var exe = b.addExecutable(.{
.name = "bootstrap",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
+ // 👇 add the lambda module to executable
+ exe.addModule("lambda", lambda);
b.installArtifact(exe);
}
Then build an arm linux executable by running zig build -Dtarget=aarch64-linux --summary all
We're using
aarch64
because we'll be deploying to thearm64
lambda runtime architecture below
Also consider optimizing for faster artifact with
zig build -Dtarget=aarch64-linux -Doptimize=ReleaseFast --summary all
or smaller artifact withzig build -Dtarget=aarch64-linux -Doptimize=ReleaseSmall --summary all
. The default is aDebug
build which trades of speed and size for faster compilation. Seezig build --help
for more info
Package your function in zip file (aws lambda assumes a zip file) zip -jq lambda.zip zig-out/bin/bootstrap
The follow shows how to deploy a lambda using a standard aws deployment tool, aws sam cli.
Create a template.yml
sam deployment template
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Resources:
Function:
Type: AWS::Serverless::Function
Properties:
# 👇 use the latest provided runtime
Runtime: provided.al2023
# 👇 deploy on arm architecture, it's more cost effective
Architectures:
- arm64
MemorySize: 128
# 👇 the zip file containing your `bootstrap` binary
# example: zip -jq lambda.zip zig-out/bin/bootstrap
CodeUri: "lambda.zip"
# 👇 required for zip but not used by the zig runtime, put any value you like here
Handler: handler
FunctionName: !Sub "${AWS::StackName}"
Policies:
- AWSLambdaBasicExecutionRole
Create a samconfig.toml
to store some local sam cli defaults
this file is can be updated overtime to evolve with your infra as your infra needs evolved
version = 1.0
[default.deploy.parameters]
resolve_s3 = true
s3_prefix = "zig-lambda-demo"
stack_name = "zig-lambda-demo"
region = "us-east-1"
fail_on_empty_changeset = false
capabilities = "CAPABILITY_IAM"
Then run sam deploy
to deploy it
Does this look interesting but you're new to zig and feel left out? No problem, zig is young so most us of our new are as well. Here are some resources to help get you up to speed on zig
- softprops 2023