{"id":2302,"date":"2019-01-04T18:49:38","date_gmt":"2019-01-04T18:49:38","guid":{"rendered":"https:\/\/www.danielpradilla.info\/blog\/?p=2302"},"modified":"2019-01-04T21:35:50","modified_gmt":"2019-01-04T21:35:50","slug":"aws-lambda-python","status":"publish","type":"post","link":"https:\/\/www.danielpradilla.info\/blog\/aws-lambda-python\/","title":{"rendered":"10 things I learned while deploying my first python function to AWS Lambda"},"content":{"rendered":"<p><a href=\"https:\/\/aws.amazon.com\/lambda\/\"><img loading=\"lazy\" decoding=\"async\" data-attachment-id=\"2303\" data-permalink=\"https:\/\/www.danielpradilla.info\/blog\/aws-lambda-python\/aws-lambda\/\" data-orig-file=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2019\/01\/AWS-Lambda.png\" data-orig-size=\"696,720\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"AWS-Lambda\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2019\/01\/AWS-Lambda-290x300.png\" data-large-file=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2019\/01\/AWS-Lambda.png\" src=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2019\/01\/AWS-Lambda-290x300.png\" class=\"aligncenter size-medium wp-image-2303\" width=\"290\" height=\"300\" alt=\"\" srcset=\"https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2019\/01\/AWS-Lambda-290x300.png 290w, https:\/\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2019\/01\/AWS-Lambda.png 696w\" sizes=\"auto, (max-width: 290px) 100vw, 290px\" \/><\/a><\/p>\n<p>I spent a few days on and off trying to deploy a <a href=\"http:\/\/flask.pocoo.org\/docs\/1.0\/#\">Flask<\/a> REST service to <a href=\"https:\/\/aws.amazon.com\/lambda\/\">AWS Lambda<\/a>, just to experience what the cool kids were talking about. These are some of the things I learned along the way:<\/p>\n<p>&nbsp;<\/p>\n<h3>Zappa is the easiest packager\/deployer for python (as of December 2018)<\/h3>\n<p><a href=\"https:\/\/github.com\/Miserlou\/Zappa\">Zappa<\/a> provides good quality feedback on the packaging\/deployment process. It&#8217;s compatible with all the popular python REST frameworks. Minimally configure, deploy and you are done. It packages your whole environment and your own modules, so you will face minimal &#8220;module not found&#8221; errors.<\/p>\n<p>Zappa provides a &#8220;tail&#8221; function that allows you to debug the errors in your deployment directly from the command line.<\/p>\n<p>&nbsp;<\/p>\n<h3>Zappa doesn&#8217;t work properly with Anaconda (as of December 2018)<\/h3>\n<p>I use Anaconda for environment management. Zappa is geared towards venv users. There are &#8220;hacky&#8221; ways of making it work. Setting the VIRTUAL_ENV environment variable, according to <a href=\"https:\/\/github.com\/Miserlou\/Zappa\/issues\/167\">https:\/\/github.com\/Miserlou\/Zappa\/issues\/167<\/a>, got me a long way. But I had a third-party module that kept failing. I spent 6 hours of a weekend that I&#8217;ll never get back on this.<\/p>\n<p>&nbsp;<\/p>\n<h3>Anaconda&#8217;s environment management is very different than venv<\/h3>\n<p>Files are stored elsewhere (conda info &#8211;envs is your friend). I&#8217;ve used Anaconda since forever, so I didn&#8217;t know that venv stored files locally within your project. Ugh! (am I getting this wrong? please tell me so). By default, Anaconda stores your requirements outside of your project folder. Naturally, this wreaks havoc with anything that is expecting an environment folder within your project.<\/p>\n<p>&nbsp;<\/p>\n<h3>Chalice is almost as good as Zappa<\/h3>\n<p><a href=\"https:\/\/github.com\/aws\/chalice\">Chalice<\/a> is the native tool from AWS for doing these kind of things. It&#8217;s not a packager \/ deployer like Zappa but a whole framework, so you have to refactor your code from whatever framework you are using. Fortunately for me the syntax is almost the same as Flask.<\/p>\n<p>Chalice relies on your requirements.txt as a guide to package the dependencies of your lambda functions. Good if you have a messy environment.<\/p>\n<p>Debugging the deployment is brutal.<\/p>\n<p>&nbsp;<\/p>\n<h3>Chalice doesn&#8217;t automatically package your own modules<\/h3>\n<p><a href=\"https:\/\/chalice.readthedocs.io\/en\/latest\/topics\/packaging.html\">According to the documentation<\/a> you have to put all your modules in a magical &#8220;chalicelibs&#8221; directory. Even after doing that, I still had import problems (importing a local module that was importing another local module). I solved it by spelling out the location, using &#8220;from . import mymodule&#8221;<\/p>\n<p>&nbsp;<\/p>\n<h3>AWS Lambda packages are restricted to 50MB<\/h3>\n<p>Messy environment? too many requirements? you are out of luck. AWS Lambda packages are <a href=\"https:\/\/docs.aws.amazon.com\/lambda\/latest\/dg\/limits.html\">limited to 50MB, zipped<\/a>.<\/p>\n<p>I actually had a huge 28MB library (zipped!) that I had to strategically trim down (hi, technical debt!) in order to fit it into my package.<\/p>\n<p>Probably this is a sign that I shouldn&#8217;t be uploading a python class, but the actual methods independently. I know, it&#8217;s lambda <strong>functions<\/strong> not lambda <strong>class with everything and the kitchen sink<\/strong><\/p>\n<p>&nbsp;<\/p>\n<h3>You can upload a class with a bunch of methods and a REST api and enjoy the benefits of serverless<\/h3>\n<p>Not the best pattern, not the most efficient solution, but hey, for small stuff works. You get a million requests for free.<\/p>\n<p>&nbsp;<\/p>\n<h3>You can decrease the response time if you increase the memory allocation of your function<\/h3>\n<p>I was getting a 500ms response time, good but an order of magnitude slower that I was getting on my laptop. Until I read this text below the &#8220;Memory&#8221; slider in the Lambda console<\/p>\n<blockquote><p>&#8220;Your function is allocated CPU proportional to the memory configured.&#8221;<\/p>\n<\/blockquote>\n<p>I moved the slider to 1024MB and the response time went down to 125ms!<\/p>\n<p>&nbsp;<\/p>\n<h3>Lambda functions are a good solution for APIs<\/h3>\n<p>I&#8217;ve been using Docker since 2016 for packaging small python APIs, but deploying them and managing the Dockerfiles is kind of a pain. If you manage to refactor your application down to single-purpose methods, AWS Lambda offers an impressively easy way to deploy pay-per-use load-balanced functions in a secure server whose hardware and OS stack you don&#8217;t have to manage. This schema works best for functions that will be run sporadically and don&#8217;t need an always-on server.<br \/>\nCome to think of it, few functions are rarely running *all* the time, and if the inputs are the same, then you can leverage the Cloudfront cache. <a href=\"https:\/\/github.com\/epsagon\/lambda-cost-calculator\">This cost calculator<\/a> might help you estimate total cost once you deploy.<\/p>\n<p>&nbsp;<\/p>\n<h3>Links that saved me (beside the docs)<\/h3>\n<p><a href=\"https:\/\/read.iopipe.com\/the-right-way-to-do-serverless-in-python-e99535574454\">The Right Way&#x2122; to do Serverless in Python<\/a><\/p>\n<p><a href=\"https:\/\/realpython.com\/aws-chalice-serverless-python\/#build-and-run-locally_2\">Building Serverless Python Apps Using AWS Chalice<\/a><\/p>\n<p><a href=\"https:\/\/read.acloud.guru\/adventures-in-migrating-to-serverless-a63556b39042\">The fear and frustration of migrating a simple web app to serverless<\/a><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I spent a few days on and off trying to deploy a Flask REST service to AWS Lambda, just to experience what the cool kids were talking about. These are some of the things I learned along the way: &nbsp; Zappa is the easiest packager\/deployer for python (as of December 2018) Zappa provides good quality&hellip; <a class=\"more-link\" href=\"https:\/\/www.danielpradilla.info\/blog\/aws-lambda-python\/\">Continue reading <span class=\"screen-reader-text\">10 things I learned while deploying my first python function to AWS Lambda<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[331],"tags":[],"class_list":["post-2302","post","type-post","status-publish","format-standard","hentry","category-software-development-en-en","entry"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1tlzy-B8","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":2399,"url":"https:\/\/www.danielpradilla.info\/blog\/my-python-logging-setup\/","url_meta":{"origin":2302,"position":0},"title":"My Python logging setup","author":"Daniel Pradilla","date":"24\/08\/2023","format":false,"excerpt":"Working on various Python projects has taught me the importance of consistent logging, especially when dealing with distributed computing frameworks like Spark. Logging is not just about keeping track of errors or information; it's about having a detailed and systematic record of the operations to understand the flow of your\u2026","rel":"","context":"In &quot;Software Dev.&quot;","block_context":{"text":"Software Dev.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/software-development-en-en\/"},"img":{"alt_text":"My Python logging setup","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2023\/08\/5aadc010-b913-4eb0-9388-cd8d6c743271.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2023\/08\/5aadc010-b913-4eb0-9388-cd8d6c743271.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2023\/08\/5aadc010-b913-4eb0-9388-cd8d6c743271.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2023\/08\/5aadc010-b913-4eb0-9388-cd8d6c743271.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":2229,"url":"https:\/\/www.danielpradilla.info\/blog\/linear-optimization-with-or-tools-containerizing-a-gunicorn-web-application\/","url_meta":{"origin":2302,"position":1},"title":"Linear optimization with or-tools: containerizing a gunicorn web application","author":"Daniel Pradilla","date":"15\/05\/2018","format":false,"excerpt":"Previously, we left our app working with our local python+gunicorn+nginx installation. In order to get there we had to do quite a bit of configuration and if we wanted to deploy this in a server or send it to a friend, we would have to go through a very error-prone\u2026","rel":"","context":"In &quot;Software Dev.&quot;","block_context":{"text":"Software Dev.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/software-development-en-en\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/05\/docker.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/05\/docker.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/05\/docker.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":2205,"url":"https:\/\/www.danielpradilla.info\/blog\/linear-optimization-with-or-tools\/","url_meta":{"origin":2302,"position":2},"title":"Linear Optimization with or-tools","author":"Daniel Pradilla","date":"07\/06\/2017","format":false,"excerpt":"\u00a0 Getting started Over the last couple of months I've been getting my feet wet with linear programming and mathematical optimisation. I got a sense of how it all worked from this Discrete Optimisation course in Coursera and googling around I discovered that there are a ton of tools out\u2026","rel":"","context":"In &quot;Best of&quot;","block_context":{"text":"Best of","link":"https:\/\/www.danielpradilla.info\/blog\/category\/bestof\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/06\/grocery_bag_brown_bag.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/06\/grocery_bag_brown_bag.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/06\/grocery_bag_brown_bag.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/06\/grocery_bag_brown_bag.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":2212,"url":"https:\/\/www.danielpradilla.info\/blog\/linear-optimization-with-or-tools-building-a-web-front-end-with-falcon-and-gunicorn\/","url_meta":{"origin":2302,"position":3},"title":"Linear Optimization with or-tools \u00e2\u20ac\u201d building a web front-end with falcon and gunicorn","author":"Daniel Pradilla","date":"14\/11\/2017","format":false,"excerpt":"In a previous post, I put together a script for solving a linear optimisation problem using Google's OR-tools. This python script is callable from the command line and you kinda need to know what you are doing and how to organize the parameters. So, in order to address this difficulty,\u2026","rel":"","context":"In &quot;Software Dev.&quot;","block_context":{"text":"Software Dev.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/software-development-en-en\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/11\/groceryshopping.gif?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/11\/groceryshopping.gif?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/11\/groceryshopping.gif?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2017\/11\/groceryshopping.gif?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":2245,"url":"https:\/\/www.danielpradilla.info\/blog\/recommender-system-for-finding-subject-matter-experts-using-the-enron-email-corpus\/","url_meta":{"origin":2302,"position":4},"title":"Recommender system for finding subject matter experts using the Enron email corpus","author":"Daniel Pradilla","date":"20\/11\/2018","format":false,"excerpt":"This is a little project to create a recommender system to find mentors inside an organization, using Natural Language Processing. It started as an excuse to build a data visualization I had in mind: an interactive word cloud that did something. When I started, I didn't know anything about Topic\u2026","rel":"","context":"In &quot;Best of&quot;","block_context":{"text":"Best of","link":"https:\/\/www.danielpradilla.info\/blog\/category\/bestof\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/11\/bubbles2.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/11\/bubbles2.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.danielpradilla.info\/blog\/wp-content\/uploads\/2018\/11\/bubbles2.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":2300,"url":"https:\/\/www.danielpradilla.info\/blog\/uploading-and-downloading-documents-from-amazon-s3-using-bash\/","url_meta":{"origin":2302,"position":5},"title":"Uploading and downloading documents from Amazon S3 using bash","author":"Daniel Pradilla","date":"12\/12\/2018","format":false,"excerpt":"You need to upload a file to S3 and cannot install new packages in the server, nor the s3 client tools. You only have bash, openssl and sed. Go. I found and adapted a script by\u00a0Viktor Szakats, that creates all the proper headers expected by the latest AWS API. I\u2026","rel":"","context":"In &quot;Software Dev.&quot;","block_context":{"text":"Software Dev.","link":"https:\/\/www.danielpradilla.info\/blog\/category\/software-development-en-en\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/posts\/2302","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/comments?post=2302"}],"version-history":[{"count":0,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/posts\/2302\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/media?parent=2302"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/categories?post=2302"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.danielpradilla.info\/blog\/wp-json\/wp\/v2\/tags?post=2302"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}