Element 84 Logo

Serverless Devise with Jets


Over the past few years, serverless design has taken the cloud community by storm. It is hard to ignore–with promises like “pay only for what you use”, “no security patching”, and “infinite scalability”.

Being on the cutting edge can have drawbacks too, which in this case is what I would describe as an absence of mature development tools. After years as a Rails developer, I am used to having a development toolbox that empowers me to turn around any incoming issue or requirement in a short amount of time, with a minimal amount of code. In the current serverless landscape, I find myself spending much more time scratching my head over YML templates, CloudFormation Stacks, Permissions & Access Policies, and a variety of other components central to cloud-native development.

After reading about the Jets framework (https://rubyonjets.com), which takes the Controllers and Routes from a Rails app and handles translating them into API Gateway and Lambda resources, I decided to give it a try.

In this post, I am taking one of my favorite Rails gems–Devise–and configuring it to run inside of a Serverless Rails application. If you’re not familiar with Devise, it is an authentication library that provides:

  • User Registration (endpoint + UI)
  • Sign-In / Sign-Out (endpoints + UI)
  • Password Reset (endpoint + email + UI)
  • Encrypted password storage

For my setup, I decided to create an RDS instance in the free-tier, but these same steps should work if you wanted an entirely on-demand setup, using Aurora Serverless as your database.

Jets Setup

In your terminal:

gem install jets      # requires Ruby 2.5.x
jets _5.2.3_ new demo_app    # no Rails 6 support yet
cd demo_app
# in your Gemfile, add: gem 'devise'
rails g devise:install
rails g devise User
rails db:migrate
rails g devise:views
rails g devise:views users
mkdir -p .jets/demo_app/.env
# set your DB value, e.g. DATABASE_URL=postgres://postgres:letmein123@database-1.cnmgdemxd6t.us-east-1.rds.amazonaws.com?pool=5
jets deploy

If all goes well, your output should appear similar to this:

If you visit the API Gateway Endpoint and find that the endpoint is timing out, there may be an issue with the JS Parser. You can confirm this by reviewing the CloudWatch Logs.

To solve this issue, you can simply move these two gems in your Gemfile further down into the :development group:

If you then see the familiar Rails error regarding a Database migration, you can follow the steps below to run the migration on your RDS instance via your local machine:

vim .env.development.remote
# add your RDS value: DATABASE_URL=[RDS_string]
JETS_ENV_REMOTE=1 jets db:create db:migrate

This should perform the migration, and you should now be up and running!

Bottom Line

The motivation for this post was the lack of mature serverless tooling. There were parts to this experience that were a breeze–like the ability to automatically translate a Rails app into a set of API Gateway and Lambda resources. But there were also times where I found myself with a familiar amount of skepticism (for example: running an RDS migration from my local machine is obviously not a polished workflow, and I don’t know yet if Jets supports deployments to accounts with Multi-Factor Authentication. I also need to explore further with things like an ElastiCache layer, or including performance tracking tools like NewRelic).

There is plenty of mindshare to be won in the serverless landscape, so it is exciting to see another option in this space. I am looking forward to the continued development of the Jets framework, and the capabilities that it provides to developers.

Matt Bialas

Senior Software Engineer