Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.39.1">
<meta name="project" content="Mayfly v0.1.0">
<title>🪰 Mayfly — Mayfly v0.1.0</title>
<link rel="stylesheet" href="dist/html-elixir-ZFNMEJKT.css" />
<link rel="canonical" href="https://elixir-aws-lambda.dev/docs/readme.html" />
<script defer src="dist/sidebar_items-32970337.js"></script>
<script defer src="docs_config.js"></script>
<script defer src="dist/html-HBZYRXZS.js"></script>
</head>
<body>
<script>(()=>{var t="ex_doc:settings",e="dark";var o="dark",s="light";var E="sidebar_state",n="closed";var r="sidebar_width";var a="sidebar-open";var i=new URLSearchParams(window.location.search),S=i.get("theme")||JSON.parse(localStorage.getItem(t)||"{}").theme;(S===o||S!==s&&window.matchMedia("(prefers-color-scheme: dark)").matches)&&document.body.classList.add(e);var d=sessionStorage.getItem(E),A=d!==n&&!window.matchMedia(`screen and (max-width: ${768}px)`).matches;document.body.classList.toggle(a,A);var c=sessionStorage.getItem(r);c&&document.body.style.setProperty("--sidebarWidth",`${c}px`);var p=/(Macintosh|iPhone|iPad|iPod)/.test(window.navigator.userAgent);document.documentElement.classList.toggle("apple-os",p);})();
</script>
<div class="body-wrapper">
<button id="sidebar-menu" class="sidebar-button sidebar-toggle" aria-label="toggle sidebar" aria-controls="sidebar">
<i class="ri-menu-line ri-lg" title="Collapse/expand sidebar"></i>
</button>
<nav id="sidebar" class="sidebar">
<div class="sidebar-header">
<div class="sidebar-projectInfo">
<a href="https://github.com/bmalum/mayfly" class="sidebar-projectImage">
<img src="assets/logo.png" alt="Mayfly" />
</a>
<div>
<a href="https://github.com/bmalum/mayfly" class="sidebar-projectName" translate="no">
Mayfly
</a>
<div class="sidebar-projectVersion" translate="no">
v0.1.0
</div>
</div>
</div>
<ul id="sidebar-list-nav" class="sidebar-list-nav" role="tablist" data-extras=""></ul>
</div>
</nav>
<output role="status" id="toast"></output>
<main class="content page-extra" id="main" data-type="extras">
<div id="content" class="content-inner">
<div class="top-search">
<div class="search-settings">
<form class="search-bar" action="search.html">
<label class="search-label">
<span class="sr-only">Search documentation of Mayfly</span>
<div class="search-input-wrapper">
<input name="q" type="text" class="search-input" placeholder="Press / to search" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" />
<button type="button" tabindex="-1" class="search-close-button" aria-hidden="true">
<i class="ri-close-line ri-lg" title="Cancel search"></i>
</button>
</div>
</label>
</form>
<div class="autocomplete">
</div>
<div class="engine-selector" data-multiple="false">
<button type="button" class="engine-button" aria-label="Select search engine" aria-haspopup="true" aria-expanded="false">
<i class="ri-search-2-line" aria-hidden="true"></i>
<span class="engine-name">Default</span>
<i class="ri-arrow-down-s-line" aria-hidden="true"></i>
</button>
<div class="engine-dropdown" hidden role="menu">
<button type="button"
class="engine-option"
data-engine-url="search.html?q="
role="menuitemradio"
aria-checked="true">
<span class="name">Default</span>
<span class="help">In-browser search</span>
</button>
</div>
</div>
<button class="icon-settings display-settings">
<i class="ri-settings-3-line"></i>
<span class="sr-only">Settings</span>
</button>
</div>
</div>
<div id="top-content">
<div class="heading-with-actions top-heading">
<h1>🪰 Mayfly</h1>
<a href="https://github.com/bmalum/mayfly/blob/main/README.md#L1" title="View Source" class="icon-action" rel="help">
<i class="ri-code-s-slash-line" aria-hidden="true"></i>
<span class="sr-only">View Source</span>
</a>
</div>
<div align="center"> <img width="300" src="./mayfly.png" alt="Mayfly Logo"/>
<h3>A lightweight AWS Lambda Custom Runtime for Elixir</h3>


</div><h2 id="why-mayfly" class="section-heading"><a href="#why-mayfly" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Why Mayfly?</span></h2><p><strong>Mayfly</strong> lets you leverage the full power of Elixir in AWS Lambda without compromise. Run your Elixir code in a serverless environment with:</p><ul><li><strong>Zero Boilerplate</strong> - Focus on your business logic, not Lambda implementation details</li><li><strong>Native Elixir Experience</strong> - Use the same coding patterns and libraries you love</li><li><strong>Optimized Performance</strong> - Designed specifically for Elixir's strengths in AWS Lambda</li><li><strong>Proper Error Handling</strong> - Get meaningful stack traces and error reports</li></ul><p>Unlike generic custom runtimes, Mayfly is purpose-built for Elixir, bringing the language's reliability and expressiveness to serverless functions.</p><h2 id="quick-start" class="section-heading"><a href="#quick-start" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Quick Start</span></h2><pre><code class="makeup elixir" translate="no"><span class="c1"># 1. Add Mayfly to your dependencies</span><span class="w">
</span><span class="c1"># In mix.exs</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">deps</span><span class="w"> </span><span class="k" data-group-id="9435468508-1">do</span><span class="w">
</span><span class="p" data-group-id="9435468508-2">[</span><span class="w">
</span><span class="p" data-group-id="9435468508-3">{</span><span class="ss">:mayfly</span><span class="p">,</span><span class="w"> </span><span class="ss">github</span><span class="p">:</span><span class="w"> </span><span class="s">"bmalum/mayfly"</span><span class="p" data-group-id="9435468508-3">}</span><span class="w">
</span><span class="p" data-group-id="9435468508-2">]</span><span class="w">
</span><span class="k" data-group-id="9435468508-1">end</span><span class="w">
</span><span class="c1"># 2. Create your handler function</span><span class="w">
</span><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyFunction</span><span class="w"> </span><span class="k" data-group-id="9435468508-4">do</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="9435468508-5">(</span><span class="n">event</span><span class="p" data-group-id="9435468508-5">)</span><span class="w"> </span><span class="k" data-group-id="9435468508-6">do</span><span class="w">
</span><span class="p" data-group-id="9435468508-7">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="9435468508-8">%{</span><span class="ss">message</span><span class="p">:</span><span class="w"> </span><span class="s">"Hello from Elixir!"</span><span class="p">,</span><span class="w"> </span><span class="ss">event</span><span class="p">:</span><span class="w"> </span><span class="n">event</span><span class="p" data-group-id="9435468508-8">}</span><span class="p" data-group-id="9435468508-7">}</span><span class="w">
</span><span class="k" data-group-id="9435468508-6">end</span><span class="w">
</span><span class="k" data-group-id="9435468508-4">end</span><span class="w">
</span><span class="c1"># 3. Build and deploy</span><span class="w">
</span><span class="c1"># Terminal</span><span class="w">
</span><span class="err">$</span><span class="w"> </span><span class="n">mix</span><span class="w"> </span><span class="n">lambda</span><span class="o">.</span><span class="n">build</span><span class="w"> </span><span class="o">--</span><span class="n">zip</span><span class="w">
</span><span class="c1"># Upload lambda.zip to AWS Lambda and set handler to "Elixir.MyFunction.handle"</span></code></pre><h2 id="table-of-contents" class="section-heading"><a href="#table-of-contents" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Table of Contents</span></h2><ul><li><a href="#features">Features</a></li><li><a href="#requirements">Requirements</a></li><li><a href="#installation">Installation</a></li><li><a href="#usage">Usage</a></li><li><a href="#documentation">Documentation</a></li><li><a href="#configuration">Configuration</a></li><li><a href="#error-handling">Error Handling</a></li><li><a href="#deployment">Deployment</a></li><li><a href="#performance">Performance</a></li><li><a href="#troubleshooting">Troubleshooting</a></li><li><a href="#roadmap">Roadmap</a></li><li><a href="#community--contributing">Community & Contributing</a></li><li><a href="#license">License</a></li></ul><h2 id="features" class="section-heading"><a href="#features" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Features</span></h2><ul><li><strong>Full Elixir Support</strong>: Run any Elixir code in AWS Lambda, including GenServers and OTP applications</li><li><strong>Simple API</strong>: Clean, idiomatic interface for Lambda functions with minimal boilerplate</li><li><strong>Robust Error Handling</strong>: Get meaningful error reports with proper Elixir stacktraces</li><li><strong>Build Tooling</strong>: Mix tasks for packaging and deployment with Docker and local build support</li><li><strong>Flexible Integration</strong>: Works seamlessly with API Gateway, S3, EventBridge and other AWS services</li></ul><h2 id="requirements" class="section-heading"><a href="#requirements" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Requirements</span></h2><ul><li>Elixir ~> 1.15</li><li>AWS Account with Lambda access</li><li>Mix</li></ul><h2 id="installation" class="section-heading"><a href="#installation" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Installation</span></h2><p>Add Mayfly to your dependencies in <code class="inline">mix.exs</code>:</p><pre><code class="makeup elixir" translate="no"><span class="kd">def</span><span class="w"> </span><span class="nf">deps</span><span class="w"> </span><span class="k" data-group-id="6200187469-1">do</span><span class="w">
</span><span class="p" data-group-id="6200187469-2">[</span><span class="w">
</span><span class="p" data-group-id="6200187469-3">{</span><span class="ss">:mayfly</span><span class="p">,</span><span class="w"> </span><span class="ss">github</span><span class="p">:</span><span class="w"> </span><span class="s">"bmalum/mayfly"</span><span class="p" data-group-id="6200187469-3">}</span><span class="w">
</span><span class="p" data-group-id="6200187469-2">]</span><span class="w">
</span><span class="k" data-group-id="6200187469-1">end</span></code></pre><p>Run <a href="https://hexdocs.pm/mix/Mix.Tasks.Deps.Get.html"><code class="inline">mix deps.get</code></a> to fetch the dependency.</p><h2 id="usage" class="section-heading"><a href="#usage" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Usage</span></h2><h3 id="creating-a-lambda-function" class="section-heading"><a href="#creating-a-lambda-function" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Creating a Lambda Function</span></h3><ol><li><p><strong>Define your handler function</strong></p><p>Create a module with a function that accepts a map and returns <code class="inline">{:ok, result}</code> or <code class="inline">{:error, reason}</code>:</p><pre><code class="makeup elixir" translate="no"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">MyLambda</span><span class="w"> </span><span class="k" data-group-id="7220440955-1">do</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="7220440955-2">(</span><span class="n">payload</span><span class="p" data-group-id="7220440955-2">)</span><span class="w"> </span><span class="k" data-group-id="7220440955-3">do</span><span class="w">
</span><span class="c1"># Process the payload</span><span class="w">
</span><span class="p" data-group-id="7220440955-4">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="7220440955-5">%{</span><span class="ss">message</span><span class="p">:</span><span class="w"> </span><span class="s">"Hello from Elixir!"</span><span class="p">,</span><span class="w"> </span><span class="ss">received</span><span class="p">:</span><span class="w"> </span><span class="n">payload</span><span class="p" data-group-id="7220440955-5">}</span><span class="p" data-group-id="7220440955-4">}</span><span class="w">
</span><span class="k" data-group-id="7220440955-3">end</span><span class="w">
</span><span class="k" data-group-id="7220440955-1">end</span></code></pre></li><li><p><strong>Build your Lambda package</strong></p><pre><code class="makeup bash" translate="no"><span class="">mix lambda.build --zip
</span></code></pre></li><li><p><strong>Deploy to AWS Lambda</strong></p><ul><li>Create a new Lambda function in the AWS Console</li><li>Select "Custom runtime" as the runtime</li><li>Upload the generated <code class="inline">lambda.zip</code> file</li><li>Set the handler environment variable to <code class="inline">Elixir.MyLambda.handle</code></li></ul></li></ol><h3 id="advanced-examples" class="section-heading"><a href="#advanced-examples" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Advanced Examples</span></h3><h4>API Gateway Integration</h4><p>When integrating with API Gateway, structure your response like this:</p><pre><code class="makeup elixir" translate="no"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">Api.Handler</span><span class="w"> </span><span class="k" data-group-id="3925884892-1">do</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">process</span><span class="p" data-group-id="3925884892-2">(</span><span class="n">event</span><span class="p" data-group-id="3925884892-2">)</span><span class="w"> </span><span class="k" data-group-id="3925884892-3">do</span><span class="w">
</span><span class="p" data-group-id="3925884892-4">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="3925884892-5">%{</span><span class="w">
</span><span class="ss">statusCode</span><span class="p">:</span><span class="w"> </span><span class="mi">200</span><span class="p">,</span><span class="w">
</span><span class="ss">headers</span><span class="p">:</span><span class="w"> </span><span class="p" data-group-id="3925884892-6">%{</span><span class="w">
</span><span class="s">"Content-Type"</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="s">"application/json"</span><span class="w">
</span><span class="p" data-group-id="3925884892-6">}</span><span class="p">,</span><span class="w">
</span><span class="ss">body</span><span class="p">:</span><span class="w"> </span><span class="nc">Jason</span><span class="o">.</span><span class="n">encode!</span><span class="p" data-group-id="3925884892-7">(</span><span class="p" data-group-id="3925884892-8">%{</span><span class="w">
</span><span class="ss">message</span><span class="p">:</span><span class="w"> </span><span class="s">"Hello from Elixir!"</span><span class="p">,</span><span class="w">
</span><span class="ss">path</span><span class="p">:</span><span class="w"> </span><span class="n">event</span><span class="p" data-group-id="3925884892-9">[</span><span class="s">"path"</span><span class="p" data-group-id="3925884892-9">]</span><span class="p">,</span><span class="w">
</span><span class="ss">method</span><span class="p">:</span><span class="w"> </span><span class="n">event</span><span class="p" data-group-id="3925884892-10">[</span><span class="s">"httpMethod"</span><span class="p" data-group-id="3925884892-10">]</span><span class="w">
</span><span class="p" data-group-id="3925884892-8">}</span><span class="p" data-group-id="3925884892-7">)</span><span class="w">
</span><span class="p" data-group-id="3925884892-5">}</span><span class="p" data-group-id="3925884892-4">}</span><span class="w">
</span><span class="k" data-group-id="3925884892-3">end</span><span class="w">
</span><span class="k" data-group-id="3925884892-1">end</span></code></pre><h4>Error Handling</h4><pre><code class="makeup elixir" translate="no"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">Example.WithError</span><span class="w"> </span><span class="k" data-group-id="0437393070-1">do</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="0437393070-2">(</span><span class="p" data-group-id="0437393070-3">%{</span><span class="s">"should_fail"</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="no">true</span><span class="p" data-group-id="0437393070-3">}</span><span class="p" data-group-id="0437393070-2">)</span><span class="w"> </span><span class="k" data-group-id="0437393070-4">do</span><span class="w">
</span><span class="p" data-group-id="0437393070-5">{</span><span class="ss">:error</span><span class="p">,</span><span class="w"> </span><span class="s">"Requested failure"</span><span class="p" data-group-id="0437393070-5">}</span><span class="w">
</span><span class="k" data-group-id="0437393070-4">end</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="0437393070-6">(</span><span class="p" data-group-id="0437393070-7">%{</span><span class="s">"raise_error"</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="no">true</span><span class="p" data-group-id="0437393070-7">}</span><span class="p" data-group-id="0437393070-6">)</span><span class="w"> </span><span class="k" data-group-id="0437393070-8">do</span><span class="w">
</span><span class="k">raise</span><span class="w"> </span><span class="s">"Demonstrating error handling"</span><span class="w">
</span><span class="k" data-group-id="0437393070-8">end</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="0437393070-9">(</span><span class="n">payload</span><span class="p" data-group-id="0437393070-9">)</span><span class="w"> </span><span class="k" data-group-id="0437393070-10">do</span><span class="w">
</span><span class="p" data-group-id="0437393070-11">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="0437393070-12">%{</span><span class="ss">status</span><span class="p">:</span><span class="w"> </span><span class="s">"success"</span><span class="p">,</span><span class="w"> </span><span class="ss">payload</span><span class="p">:</span><span class="w"> </span><span class="n">payload</span><span class="p" data-group-id="0437393070-12">}</span><span class="p" data-group-id="0437393070-11">}</span><span class="w">
</span><span class="k" data-group-id="0437393070-10">end</span><span class="w">
</span><span class="k" data-group-id="0437393070-1">end</span></code></pre><h4>Handling Binary Data</h4><pre><code class="makeup elixir" translate="no"><span class="kd">defmodule</span><span class="w"> </span><span class="nc">ImageGenerator</span><span class="w"> </span><span class="k" data-group-id="7724625936-1">do</span><span class="w">
</span><span class="kd">def</span><span class="w"> </span><span class="nf">generate</span><span class="p" data-group-id="7724625936-2">(</span><span class="n">payload</span><span class="p" data-group-id="7724625936-2">)</span><span class="w"> </span><span class="k" data-group-id="7724625936-3">do</span><span class="w">
</span><span class="c1"># Generate image data</span><span class="w">
</span><span class="n">image_data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">create_image</span><span class="p" data-group-id="7724625936-4">(</span><span class="n">payload</span><span class="p" data-group-id="7724625936-4">)</span><span class="w">
</span><span class="p" data-group-id="7724625936-5">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="7724625936-6">%{</span><span class="w">
</span><span class="ss">isBase64Encoded</span><span class="p">:</span><span class="w"> </span><span class="no">true</span><span class="p">,</span><span class="w">
</span><span class="ss">body</span><span class="p">:</span><span class="w"> </span><span class="nc">Base</span><span class="o">.</span><span class="n">encode64</span><span class="p" data-group-id="7724625936-7">(</span><span class="n">image_data</span><span class="p" data-group-id="7724625936-7">)</span><span class="p">,</span><span class="w">
</span><span class="ss">headers</span><span class="p">:</span><span class="w"> </span><span class="p" data-group-id="7724625936-8">%{</span><span class="s">"Content-Type"</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="s">"image/png"</span><span class="p" data-group-id="7724625936-8">}</span><span class="w">
</span><span class="p" data-group-id="7724625936-6">}</span><span class="p" data-group-id="7724625936-5">}</span><span class="w">
</span><span class="k" data-group-id="7724625936-3">end</span><span class="w">
</span><span class="kd">defp</span><span class="w"> </span><span class="nf">create_image</span><span class="p" data-group-id="7724625936-9">(</span><span class="n">payload</span><span class="p" data-group-id="7724625936-9">)</span><span class="w"> </span><span class="k" data-group-id="7724625936-10">do</span><span class="w">
</span><span class="c1"># Implementation details...</span><span class="w">
</span><span class="k" data-group-id="7724625936-10">end</span><span class="w">
</span><span class="k" data-group-id="7724625936-1">end</span></code></pre><h2 id="documentation" class="section-heading"><a href="#documentation" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Documentation</span></h2><h3 id="online-documentation" class="section-heading"><a href="#online-documentation" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Online Documentation</span></h3><p>Full documentation with guides and API reference is available at <strong><a href="https://elixir-aws-lambda.dev/docs/">elixir-aws-lambda.dev/docs</a></strong></p><p>Quick links:</p><ul><li><strong><a href="https://elixir-aws-lambda.dev/docs/getting-started.html">Getting Started Guide</a></strong> - Step-by-step tutorial for your first Lambda function</li><li><strong><a href="https://elixir-aws-lambda.dev/docs/deployment.html">Deployment Guide</a></strong> - Advanced deployment scenarios and best practices</li><li><strong><a href="https://elixir-aws-lambda.dev/docs/api-reference.html">API Reference</a></strong> - Complete module and function documentation</li></ul><h3 id="generate-documentation-locally" class="section-heading"><a href="#generate-documentation-locally" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Generate Documentation Locally</span></h3><p>Generate and view the documentation on your machine:</p><pre><code class="makeup bash" translate="no"><span class="">mix docs
</span><span class="">open doc/index.html
</span></code></pre><h2 id="configuration" class="section-heading"><a href="#configuration" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Configuration</span></h2><h3 id="environment-variables" class="section-heading"><a href="#environment-variables" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Environment Variables</span></h3><ul><li><code class="inline">_HANDLER</code>: Required - The Elixir function to call, in the format <code class="inline">Elixir.Module.function</code></li><li><code class="inline">AWS_LAMBDA_RUNTIME_API</code>: Automatically set by AWS Lambda</li><li><code class="inline">LOGLEVEL</code>: Optional - Set to <code class="inline">debug</code> for more verbose logging</li></ul><h3 id="build-options" class="section-heading"><a href="#build-options" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Build Options</span></h3><p>The <code class="inline">lambda.build</code> mix task supports the following options:</p><ul><li><code class="inline">--zip</code>: Create a ZIP file for deployment</li><li><code class="inline">--outdir</code>: Specify the output directory (default: current directory)</li><li><code class="inline">--docker</code>: Build using Docker (useful for cross-platform compatibility)</li></ul><p>Example:</p><pre><code class="makeup bash" translate="no"><span class="">mix lambda.build --zip --docker
</span></code></pre><h3 id="custom-docker-build-environment" class="section-heading"><a href="#custom-docker-build-environment" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Custom Docker Build Environment</span></h3><p>You can provide your own <code class="inline">lambda.Dockerfile</code> in your project root to customize the build environment. This is useful when:</p><ul><li>Your dependencies require specific system libraries</li><li>You need a different Erlang/Elixir version</li><li>You want to add native dependencies for NIFs</li></ul><p>Create a <code class="inline">lambda.Dockerfile</code> in your project root:</p><pre><code class="dockerfile">FROM amazonlinux:2023
# Add your custom system dependencies
RUN yum install -y imagemagick-devel libxml2-devel
# Install Erlang/Elixir (customize versions as needed)
RUN yum install -y wget tar gcc make && \
wget https://github.com/erlang/otp/releases/download/OTP-27.2/otp_src_27.2.tar.gz && \
tar -zxf otp_src_27.2.tar.gz && \
cd otp_src_27.2 && \
./configure --without-javac && \
make -j$(nproc) && make install && \
cd / && rm -rf otp_src_27.2*
ENV MIX_ENV=lambda
WORKDIR /mnt/code
RUN mix local.rebar --force && mix local.hex --force</code></pre><p>If no <code class="inline">lambda.Dockerfile</code> is found in your project, Mayfly will use the default one from the library.</p><h2 id="error-handling" class="section-heading"><a href="#error-handling" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Error Handling</span></h2><p>Mayfly provides standardized error handling for Lambda functions:</p><ol><li><p><strong>Return <code class="inline">{:error, reason}</code></strong>: For expected errors</p><pre><code class="makeup elixir" translate="no"><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="8976125623-1">(</span><span class="n">payload</span><span class="p" data-group-id="8976125623-1">)</span><span class="w"> </span><span class="k" data-group-id="8976125623-2">do</span><span class="w">
</span><span class="k">case</span><span class="w"> </span><span class="n">validate</span><span class="p" data-group-id="8976125623-3">(</span><span class="n">payload</span><span class="p" data-group-id="8976125623-3">)</span><span class="w"> </span><span class="k" data-group-id="8976125623-4">do</span><span class="w">
</span><span class="ss">:ok</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p" data-group-id="8976125623-5">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="n">process</span><span class="p" data-group-id="8976125623-6">(</span><span class="n">payload</span><span class="p" data-group-id="8976125623-6">)</span><span class="p" data-group-id="8976125623-5">}</span><span class="w">
</span><span class="p" data-group-id="8976125623-7">{</span><span class="ss">:error</span><span class="p">,</span><span class="w"> </span><span class="n">reason</span><span class="p" data-group-id="8976125623-7">}</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p" data-group-id="8976125623-8">{</span><span class="ss">:error</span><span class="p">,</span><span class="w"> </span><span class="n">reason</span><span class="p" data-group-id="8976125623-8">}</span><span class="w">
</span><span class="k" data-group-id="8976125623-4">end</span><span class="w">
</span><span class="k" data-group-id="8976125623-2">end</span></code></pre></li><li><p><strong>Raise an exception</strong>: For unexpected errors</p><pre><code class="makeup elixir" translate="no"><span class="kd">def</span><span class="w"> </span><span class="nf">handle</span><span class="p" data-group-id="3620857681-1">(</span><span class="n">payload</span><span class="p" data-group-id="3620857681-1">)</span><span class="w"> </span><span class="k" data-group-id="3620857681-2">do</span><span class="w">
</span><span class="c1"># This will be caught and formatted properly</span><span class="w">
</span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">payload</span><span class="p" data-group-id="3620857681-3">[</span><span class="s">"a"</span><span class="p" data-group-id="3620857681-3">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">payload</span><span class="p" data-group-id="3620857681-4">[</span><span class="s">"b"</span><span class="p" data-group-id="3620857681-4">]</span><span class="w">
</span><span class="p" data-group-id="3620857681-5">{</span><span class="ss">:ok</span><span class="p">,</span><span class="w"> </span><span class="p" data-group-id="3620857681-6">%{</span><span class="ss">sum</span><span class="p">:</span><span class="w"> </span><span class="n">result</span><span class="p" data-group-id="3620857681-6">}</span><span class="p" data-group-id="3620857681-5">}</span><span class="w">
</span><span class="k" data-group-id="3620857681-2">end</span></code></pre></li></ol><p>Errors are formatted according to the AWS Lambda error response format with proper stacktraces.</p><h2 id="deployment" class="section-heading"><a href="#deployment" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Deployment</span></h2><h3 id="detailed-deployment-steps" class="section-heading"><a href="#detailed-deployment-steps" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Detailed Deployment Steps</span></h3><ol><li><p><strong>Build the Lambda package</strong>:</p><pre><code class="makeup bash" translate="no"><span class="">mix lambda.build --zip
</span></code></pre></li><li><p><strong>Create a new Lambda function</strong>:</p><ul><li>Open the AWS Lambda Console</li><li>Click "Create function"</li><li>Choose "Author from scratch"</li><li>Name your function</li><li>Select "Custom runtime" for Runtime</li><li>Create or select an execution role</li><li>Click "Create function"</li></ul></li><li><p><strong>Upload the deployment package</strong>:</p><ul><li>In the Function code section, click "Upload from"</li><li>Select ".zip file"</li><li>Upload the generated <code class="inline">lambda.zip</code> file</li><li>Click "Save"</li></ul></li><li><p><strong>Configure the handler</strong>:</p><ul><li>In the Runtime settings section, click "Edit"</li><li>Set the Handler to <code class="inline">Elixir.YourModule.function_name</code></li><li>Click "Save"</li></ul></li><li><p><strong>Test your function</strong>:</p><ul><li>Click "Test"</li><li>Configure a test event</li><li>Click "Test" to invoke your function</li></ul></li></ol><h2 id="performance" class="section-heading"><a href="#performance" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Performance</span></h2><h3 id="optimizing-cold-starts" class="section-heading"><a href="#optimizing-cold-starts" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Optimizing Cold Starts</span></h3><ul><li>Increase memory allocation (which also increases CPU power)</li><li>Minimize dependencies in your application</li><li>Consider provisioned concurrency for critical functions</li></ul><h3 id="memory-and-timeout-configuration" class="section-heading"><a href="#memory-and-timeout-configuration" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Memory and Timeout Configuration</span></h3><ul><li>Start with at least 512MB of memory for reasonable performance</li><li>Adjust timeout based on your function's processing needs</li><li>Monitor execution times to fine-tune these settings</li></ul><h2 id="troubleshooting" class="section-heading"><a href="#troubleshooting" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Troubleshooting</span></h2><h3 id="common-issues" class="section-heading"><a href="#common-issues" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Common Issues</span></h3><ol><li><strong>Handler Not Found</strong>: Ensure the <code class="inline">_HANDLER</code> environment variable is correctly set to <code class="inline">Elixir.Module.function</code></li><li><strong>Timeout Errors</strong>: Check if your function exceeds the Lambda timeout limit</li><li><strong>Memory Issues</strong>: Increase the Lambda memory allocation if needed</li><li><strong>Cold Start Performance</strong>: Consider increasing the memory allocation to improve cold start times</li></ol><h3 id="debugging-tips" class="section-heading"><a href="#debugging-tips" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Debugging Tips</span></h3><ul><li>Set <code class="inline">LOGLEVEL</code> environment variable to <code class="inline">debug</code> for verbose logging</li><li>Review CloudWatch logs for detailed error information</li><li>Test locally before deployment when possible</li></ul><h2 id="roadmap" class="section-heading"><a href="#roadmap" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Roadmap</span></h2><ul><li>[ ] Build with Docker Image for x86/arm64</li><li>[ ] Build Locally</li><li>[ ] Create ZIP File</li><li>[ ] CDK Sample</li><li>[ ] HexDocs and Hex.pm publishing</li><li>[ ] GitHub Actions CI/CD templates</li><li>[ ] Performance benchmarks and optimizations</li><li>[ ] Framework integrations (Phoenix, etc.)</li></ul><h2 id="community-contributing" class="section-heading"><a href="#community-contributing" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">Community & Contributing</span></h2><p>We welcome contributions of all kinds! Here's how you can help:</p><ul><li><strong>Bug Reports</strong>: Open an issue describing the bug and how to reproduce it</li><li><strong>Feature Requests</strong>: Open an issue describing the desired feature</li><li><strong>Code Contributions</strong>: Submit a pull request with your changes</li><li><strong>Documentation</strong>: Help improve or translate documentation</li><li><strong>Examples</strong>: Share how you're using Mayfly in your projects</li></ul><p>Before contributing, please review our:</p><ul><li>Code of Conduct (link)</li><li>Contributing Guidelines (link)</li></ul><h2 id="license" class="section-heading"><a href="#license" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i></a><span class="text">License</span></h2><p>Mayfly is licensed under the MIT License. See the LICENSE file for details.</p>
</div>
<div class="bottom-actions" id="bottom-actions">
<div class="bottom-actions-item">
</div>
<div class="bottom-actions-item">
<a href="changelog.html" class="bottom-actions-button" rel="next">
<span class="subheader">
Next Page →
</span>
<span class="title">
Changelog
</span>
</a>
</div>
</div>
<footer class="footer">
<p>
<span class="line">
<button class="a-main footer-button display-quick-switch" title="Search HexDocs packages">
Search HexDocs
</button>
<a href="Mayfly.epub" title="ePub version">
Download ePub version
</a>
</span>
</p>
<p class="built-using">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" target="_blank" rel="help noopener" translate="no">ExDoc</a> (v0.39.1) for the
<a href="https://elixir-lang.org" title="Elixir" target="_blank" translate="no">Elixir programming language</a>
</p>
</footer>
</div>
</main>
</div>
</body>
</html>