Using Ruby on AWS Lamba

If you love Ruby and Lambda like we do, then re:Invent 2018 was like Christmas arriving early. Here's how you can get up to speed quickly with running Ruby code on Lambda.

When Ruby support on AWS Lambda was announced yesterday, I was so excited about it that I had to try it right away. We've been using Lambda for a while at Honeybadger, and I have longed to be able to write our functions in Ruby. Having played with the new Ruby support for a few hours, I'm feeling confident we'll be spending less time with Node, Go, and Python. :)

A Quick Example

While the announcement blog post from AWS can get you up and running quickly with Ruby on Lambda, I wanted to share an example of using the Serverless framework to deploy your Ruby Lambda functions. I've found this framework does a fantastic job of removing the annoyances of working with Lambda functions. While the current version (1.34) of the framework doesn't have template generation for Ruby projects ready yet (the PR was merged a couple of hours before I started writing this post), it's easy enough to get started without the generator. Here's a sample config file that I'll use for this walkthrough, which is a simple function that will populate a DynamoDB table with metadata associated with S3 objects when they are created:

The resources section of the config results in the automatic creation of a new DynamoDB table, and the name of the newly-created table is placed in the an environment variable for the function, which we'll use in the code. The function is triggered by SNS events for an SNS topic that has been created previously. That SNS topic receives notifications for PUT events on the S3 bucket, which is also created manually.

Here's the Ruby code:

The code doesn't do a whole lot -- it receives SNS events, loops through the records in the SNS messages to get the info about each S3 object that was created, performs a HEAD request on the S3 object to get the metadata, then puts (creates or updates) an item in the DynamoDB table. The only dependency for this function is the AWS SDK, which is included in the runtime environment, so you don't even need to worry about a Gemfile. However, if you do have some additional gems you'd like to bring to the party, that's easy to do. Let's take a look at how to include additional gems as we talk about deployment.

Deployment

Getting this code in its current state to Lambda is super easy, thanks to the Serverless framework:

sls deploy

That one command will do all of this for you:

  • Zip up your code
  • Put the zip file onto S3
  • Deploy the function in Lambda (complete with environment variables and SNS trigger)
  • Create the IAM policies
  • Create the DynamoDB table

Once the deployment is done, creating objects in the bucket will result in new items being added to the DynamoDB table.

Dependencies

Getting additional gem dependencies included with your deployed function is easy -- all you need to do is create a Gemfile, add the gems you want to bundle, and run bundle install --path vendor/bundle. This will bundle the gems into the local directory, and they will get zipped up and added to the function with the rest of your code.

The one caveat for dependencies, though, are gems that require some sort of C extension to be compiled. Since your development environment is most likely different from the Lambda runtime environment, you need to do a little more work to get those extensions compiled to work in AWS. Thanks to the lambci Docker images, though, and the Docker image I created on top of their Ruby image, it's not hard to do. To bundle your dependencies and have them compiled properly, just run my docker image, like so:

docker run --rm -v $(pwd):/var/task stympy/lambda-ruby2.5

All it does is run the bundler command line mentioned above, so the gems will be placed in vendor/bundle, ready to be included in the ZIP file that is created by the deploy command.

With that, you're off to the races. I hope you'll enjoy running Ruby in Lambda as much I have. :)

author photo

Benjamin Curtis

Ben has been developing web apps and building startups since '99, and fell in love with Ruby and Rails in 2005. Before co-founding Honeybadger, he launched a couple of his own startups: Catch the Best, to help companies manage the hiring process, and RailsKits, to help Rails developers get a jump start on their projects. Ben's role at Honeybadger ranges from bare-metal to front-end... he keeps the server lights blinking happily, builds a lot of the back-end Rails code, and dips his toes into the front-end code from time to time. When he's not working, Ben likes to hang out with his wife and kids, ride his road bike, and of course hack on open source projects. :)

“We’ve looked at a lot of error management systems. Honeybadger is head and shoulders above the rest and somehow gets better with every new release.”
Michael Smith
Try Error Monitoring Free for 15 Days