Mayfly: Bringing Elixir to AWS Lambda
- tags
- #Elixir #Lambda #Aws #Serverless #Otp
- categories
- Development Cloud
- published
- reading time
- 3 minutes
A lightweight AWS Lambda Custom Runtime that brings the full power of Elixir to serverless functions.
I’m excited to announce Mayfly - a custom AWS Lambda runtime designed specifically for Elixir. Mayfly makes it simple to run Elixir code serverless without compromise.
🌐 Visit elixir-aws-lambda.dev for complete documentation, examples, and guides.
Why Mayfly?
- Zero Boilerplate: Focus on your business logic, not Lambda implementation details
- Native Elixir: Use standard
{:ok, result}/{:error, reason}patterns - OTP Support: Run GenServers and full OTP applications in Lambda
- Proper Error Handling: Get meaningful Elixir stacktraces in Lambda responses
Quick Start
# 1. Add to dependencies
def deps do
[{:mayfly, github: "bmalum/mayfly"}]
end
# 2. Create handler
defmodule MyFunction do
def handle(event) do
{:ok, %{message: "Hello from Elixir!", event: event}}
end
end
# 3. Build and deploy
$ mix lambda.build --zip
API Gateway Example
defmodule MyApp.ApiHandler do
def handle(event) do
case {event["httpMethod"], event["path"]} do
{"GET", "/users"} ->
{:ok, %{
statusCode: 200,
body: Jason.encode!(%{users: fetch_users()})
}}
{"POST", "/users"} ->
body = Jason.decode!(event["body"])
{:ok, %{
statusCode: 201,
body: Jason.encode!(create_user(body))
}}
_ ->
{:ok, %{statusCode: 404, body: Jason.encode!(%{error: "Not found"})}}
end
end
end
Custom Docker Images
For production deployments or when you need specific system dependencies, you can build custom Docker images:
FROM public.ecr.aws/lambda/provided:al2023
# Install Erlang/OTP and Elixir
RUN dnf install -y tar gzip && \
curl -fSL https://github.com/erlang/otp/releases/download/OTP-26.2.1/otp_src_26.2.1.tar.gz -o otp.tar.gz && \
tar -xzf otp.tar.gz && cd otp_src_26.2.1 && \
./configure && make && make install && \
cd .. && rm -rf otp_src_26.2.1 otp.tar.gz
RUN curl -fSL https://github.com/elixir-lang/elixir/releases/download/v1.16.0/elixir-otp-26.zip -o elixir.zip && \
unzip elixir.zip -d /usr/local && rm elixir.zip
# Copy your Lambda function
COPY _build/lambda/rel/my_function /var/task
COPY bootstrap /var/runtime/bootstrap
CMD ["Elixir.MyFunction.handle"]
Build and deploy:
# Build release
MIX_ENV=lambda mix release
# Build Docker image
docker build -t my-elixir-lambda .
# Push to ECR and deploy
aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_REGISTRY
docker tag my-elixir-lambda:latest $ECR_REGISTRY/my-elixir-lambda:latest
docker push $ECR_REGISTRY/my-elixir-lambda:latest
This approach gives you full control over the runtime environment and allows you to include native dependencies or custom configurations.
Build Options
# Local build
mix lambda.build --zip
# Docker build (cross-platform)
mix lambda.build --docker --zip
# Custom output directory
mix lambda.build --zip --outdir ./deploy
Event Source Support
Mayfly works with all AWS event sources:
S3 Events:
def handle(%{"Records" => records}) do
Enum.each(records, fn record ->
bucket = get_in(record, ["s3", "bucket", "name"])
key = get_in(record, ["s3", "object", "key"])
process_s3_object(bucket, key)
end)
{:ok, %{processed: length(records)}}
end
EventBridge:
def handle(%{"detail-type" => type, "detail" => detail}) do
case type do
"Order Placed" -> process_order(detail)
"User Registered" -> process_registration(detail)
_ -> {:ok, %{status: "ignored"}}
end
end
Documentation
Complete documentation at elixir-aws-lambda.dev :
- Official Website - Documentation and examples
- Getting Started Guide - Step-by-step tutorial
- Deployment Guide - Production best practices
Try It Out
git clone https://github.com/bmalum/mayfly.git
cd mayfly
mix docs
Why “Mayfly”?
Mayflies are ephemeral creatures with short lifespans - some live just hours. Like Lambda functions, they’re lightweight, purpose-built, and designed for brief but important tasks.
Links:
Tags: #elixir #lambda #aws #serverless #otp