My Ruby on Rails stack for side projects in 2021
Tags: rails, ruby, webdev
Published: 2021-03-01 14:41:08

---
title: My Ruby on Rails stack for side projects in 2021
published: true
date: 2021-03-01 14:32:00 UTC
tags: rubyonrails, ruby, webdev
canonical_url: https://www.mskog.com/posts/my-recommended-rails-stack-in-2021
---

 ![My Ruby on Rails stack for side projects in 2021](https://s3-eu-central-1.amazonaws.com/mskog-cms/2021/02/vaggelis-karofilakis-5tW8SwF6trE-unsplash.jpg)

Why would you start a new side project in Ruby on Rails in 2021? Shouldn't you use something like [Next.js](https://nextjs.org/) or even [Blitz](https://github.com/blitz-js/blitz)? Well, I find that Ruby on Rails is still one of the most productive ways to create an application. It is [safe and boring](http://boringtechnology.club/) and it gets the job done.

With [HTML over the wire](https://m.signalvnoise.com/html-over-the-wire/) becoming popular with tools like [Phoenix LiveView](https://github.com/phoenixframework/phoenix_live_view) and [Laravel Livewire](https://laravel-livewire.com/), you can't go wrong with good old Ruby on Rails. You can even try [Hotwire](https://hotwire.dev/) to stream HTML over web sockets.

With all that said I thought I'd share my recommended stack for Ruby on Rails development in 2021.

## TLDR

This is long, so if you don't want to read the whole thing then here is a quick summary:

**Ruby and Rails versions** : Ruby 3 and Ruby on Rails 6  
**Architecture** : Use "the Rails way"  
**Background jobs** : [Sidekiq](https://sidekiq.org/)  
**Database** : [PostgreSQL](https://www.postgresql.org/)  
**Asset Management** : [Webpacker](https://github.com/rails/webpacker)  
**CSS** : [Tailwind](https://tailwindcss.com/)  
**Javascript** : [Alpine.js](https://github.com/alpinejs/alpine), [Stimulus](https://stimulus.hotwire.dev/), and [Vue](https://vuejs.org/)  
**Pagination** : [Pagy](https://github.com/ddnexus/pagy)  
**Testing** : [RSpec](https://rspec.info/) or [Minitest](https://github.com/seattlerb/minitest) with [VCR](https://github.com/vcr/vcr)  
**Periodic jobs** : [Clockwork](https://github.com/Rykian/clockwork)  
**Code formatting** : [Prettier](https://prettier.io/) for Javascript. [Rubocop](https://github.com/rubocop/rubocop) for Ruby  
**Exception management** : [Rollbar](https://rollbar.com/) or [Honeybadger](https://www.honeybadger.io/)  
**Sending email** : [Postmark](https://postmarkapp.com/)  
**Slugs** : [friendly\_id](https://github.com/norman/friendly_id)  
**Full Text Search** : [pg\_search](https://github.com/Casecommons/pg_search) or [searchkick](https://github.com/ankane/searchkick)  
**Deployment** : [Heroku](https://www.heroku.com/) or [Dokku](https://github.com/dokku/dokku)  
**Self-hosted tools** : [Thumbor](https://github.com/thumbor/thumbor), [Huginn](https://github.com/huginn/huginn), [OpenFaaS](https://www.openfaas.com/) and [Grafana](https://grafana.com/)  
**Editor tools** : [Solargraph](https://github.com/castwide/solargraph), [Rails fast nav](https://github.com/jemmyw/vscode-rails-fast-nav), [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode), [ruby-rubocop](https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop)  
**Monitoring** : [InfluxDB](https://www.influxdata.com/), [Grafana](https://grafana.com/) and [influxdb-rails](https://github.com/influxdata/influxdb-rails)  
**Templating engine** : ERB  
**Admin tool** : [activeadmin](https://activeadmin.info/)

### Ruby and Rails versions

Use the latest Ruby and the latest Rails versions. This is currently Ruby 3.0 and Rails 6.1. They both work well together and I haven't found any reason to stay on the 2.x Ruby versions.

### Rails architecture

**Caveat** : This is just my opinion and if you do things differently then that is great too!

If you are building a side project with Ruby on Rails then I think that you should stick to the Rails way of doing things. Do not reach for fancy things like [DDD](https://en.wikipedia.org/wiki/Domain-driven_design) or [hexagonal architecture](https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)), especially not if your app is small. There is a very real [YAGNI](https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it) factor when it comes to software architecture and you can waste a lot of time designing something that you don't need.

Don't introduce [decorators and view models](https://github.com/drapergem/draper). Use helpers instead.  
Don't extract domain models. Put the code in the ActiveRecord models and the controllers.  
Don't reach for [interactors](https://mkdev.me/en/posts/a-couple-of-words-about-interactors-in-rails) to model your domain logic.  
Don't try to [avoid duplication](https://sandimetz.com/blog/2016/1/20/the-wrong-abstraction) too early.

I have done multiple apps that need all of the above, but those were huge business critical projects with tens of thousands of lines of code. I've started out with an advanced design from the start so many times and then realized that I didn't even need it.

Once you see a pattern emerging in your app you can start thinking about these things. Perhaps your views got all cluttered with presentation logic that don't really belong in your model. Then, and only then, should you think about perhaps introducing decorators or view components.

Your codebase will eventually tell you what it wants to be and once you are experienced enough you will be able to tell when you need to restructure things.

![](https://thumbs.mskog.com/https://s3-eu-central-1.amazonaws.com/mskog-cms/2021/02/photo-1487958449943-2429e8be8625.jpeg)

### Background jobs

[Sidekiq](https://sidekiq.org/). I've been using that for many years now and it has been rock solid both for side projects and work projects. I also recommend using [ActiveJob](https://guides.rubyonrails.org/active_job_basics.html) with Sidekiq just to make things a bit easier and rails-like. It will make [things a bit slower](https://github.com/mperham/sidekiq/wiki/Active-Job#performance) but that shouldn't matter for side projects.

One issue with Sidekiq is that you won't have access to rate limiting and scheduled jobs unless you pay for the enterprise version. If you are running a business then this is probably a good idea but we are going for dirt cheap here. The rate limit part can be solved using something like [ruby-limiter](https://github.com/Shopify/limiter) for global rate limiting and [sidekiq\_limit\_fetch](https://github.com/brainopia/sidekiq-limit_fetch) to limit concurrency per queue. It doesn't have official support for modern Sidekiq versions but in my experience it works fine anyway. You should probably not use that for business critical things however.

If you want to get fancy you can also take a look at [Faktory](http://contribsys.com/faktory/), which is a polyglot job processing framework from the creator of Sidekiq. Then you can write your jobs in any language you want as well.

### Database

Use a relational database such as PostgreSQL or MySQL. I do not recommend using document databases such as MongoDB because there is really no reason for it in my opinion. PostgreSQL is plenty fast and you probably won't need things like horizontal scaling for a side project. You can of course try something fancy like [FaunaDB](https://fauna.com/), [CockroachDB](https://www.cockroachlabs.com/), or any of the many database flavors.

This might come off as old school, but when I develop side projects I need something that [stores my data safely](http://cryto.net/~joepie91/blog/2015/07/19/why-you-should-never-ever-ever-use-mongodb/) and is easy to backup with rock solid performance. PostgreSQL checks all those boxes and it has always served me well. Let me put it his way: There is no reason to ponder "is my data safe" when using PostgreSQL.

![My Ruby on Rails stack for side projects in 2021](https://s3-eu-central-1.amazonaws.com/mskog-cms/2021/02/1_PY24xlr4TpOkXW04HUoqrQ.jpeg)<figcaption>Even the logo is amazing.</figcaption>

### Asset Management

Two ways: [Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html) or [Webpacker](https://edgeguides.rubyonrails.org/webpacker.html). I always use Webpacker. It is modern, you have access to the full NPM ecosystem, and it has all the modern features such as tree shaking and hot module replacement.

Webpacker itself is just a Rails style wrapper on top of Webpack. You probably don't have to worry about [configuring webpack](https://webpack.js.org/configuration/) if you use Webpacker so that is great.

### CSS

OK I realize that this is highly opinionated so I'm just going to give you my recommendation: I'm a big fan of [Tailwind](https://tailwindcss.com/). I find that its utility-based approach is great for getting things done. I like it so much that I even paid for the premium component package [TailwindUI](https://tailwindui.com/). It is just one of those things that you either like or don't like. Since you already use Webpacker(right?) you can use whatever you want so find something you like, learn everything about it, and then stick to it.

### Javascript

I have divided this into three sections to make it easier to recommend things.  
Javascript is one of those things where you can really screw yourself over by choosing the wrong thing. I recommend starting very small and only expand when you know that you need it.

![My Ruby on Rails stack for side projects in 2021](https://s3-eu-central-1.amazonaws.com/mskog-cms/2021/02/photo-1583484963886-cfe2bff2945f.jpeg)

**Just a little Javascript**  
This is when you need things like "show this element when I click this button" and "show the value of this input field in this h2-tag as I type it". For this I recommend using [Alpine.js](https://github.com/alpinejs/alpine). You don't need to juggle script tags and jQuery with Alpine and it gets the job done when you need something fast and simple. It can however gunk up your HTML quite a bit so when you get to that point you might want to move on to the next section.

**Some Javascript**  
Once you need to introduce NPM packages and need something more organized then Alpine might get messy. At this point I would introduce [Stimulus](https://stimulus.hotwire.dev/). It is made by the creators of Ruby of Rails. It will clean up a lot of gunk introduced by Alpine and leave you with reusable controllers. Here you can import NPM packages and it works very well with Webpacker. You can of course keep using Alpine as well and use Stimulus for the more advanced things if you wish since they work very well together.

**A lot of Javascript**  
You might not reach this stage and you should be very careful about choosing to go down this path prematurely since it is quite a bit of work. If you need advanced state management, high performance and complicated client side logic then Stimulus might no longer cut it. You may have to reach for a declarative, component based library like [React](https://reactjs.org/), [Vue](https://vuejs.org/), or [Svelte](https://svelte.dev/). All of these, and others, work very well with Webpacker and there are wrappers to make things easier for you. For example we have [React on Rails](https://github.com/shakacode/react_on_rails) for React integration.

Again, you need to be careful about taking this step because once you start using something like React you have to _replace your HTML_ with React components to use it. You cannot simply have React "use your HTML" as a template. You have to rewrite everything from that DOM node and "down" to be able to use React properly. However, if you use Vue then you can [reuse your existing HTML](https://gorails.com/forum/rails-6-with-full-vue-frontend-vs-sprinkled-vue-components) as the template in Vue. This might make the transition easier and much like Stimulus did Vue will become "Javascript sprinkles" on top of your existing HTML. I don't think that something similar can be done with React. Hit me up on Twitter if you know of a way!

* * *

But Magnus, what about [Hotwire](https://hotwire.dev/) or [StimulusReflex](https://docs.stimulusreflex.com/)? If you send HTML over the wire then you won't need to add any advanced Javascript at all right? The simple answer is that I don't have enough experience with these tools to be able to recommend them. They seem _very_ promising however and I will absolutely write an article about this technology once I have worked with them some more.

Bottom line: Do not reach for something advanced unless you know that you need it. Stick with simple things like Alpine.js until you are absolutely sure that you need something else.

### Caching

Since you already use [Redis](https://redis.io/) to get Sidekiq going then you might as well [use that](https://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-rediscachestore) for your cache as well.

For the actual caching part you should use [Russian Doll Caching](https://blog.appsignal.com/2018/04/03/russian-doll-caching-in-rails.html), also known as Fragment Caching. This is the preferred way of caching things in Rails. I also would like you recommend using [Action Caching](https://guides.rubyonrails.org/caching_with_rails.html#action-caching) if you can get away with it. It was removed back in Ruby on Rails 4 but there is a [gem that you can use](https://github.com/rails/actionpack-action_caching). It was removed from Rails because it can be a hassle to get the cache expiration to work properly and such. I try to use it whenever I can however because it is so much faster.

I wrote more about caching in my article about [Ruby on Rails performance](https://www.mskog.com/posts/42-performance-tips-for-ruby-on-rails/#page-and-action-caching) so you might want to check that out as well.

### Pagination

I've been using [Kaminari](https://github.com/kaminari/kaminari) in the past but I've since switched to P[agy](https://github.com/ddnexus/pagy). It has all the bells and whistles that you can think of like [countless pagination](https://ddnexus.github.io/pagy/api/countless.html), pagination using AJAX, and built-in helpers for many CSS frameworks.

### Testing

This should probably be a full article. I could write about what to test, when to test it and how much to test. I will probably make this into an article of its own so I'll just stick to writing about which frameworks and tools I recommend here.

This will be a bit of a boring one since you really can't go wrong with either [RSpec](https://rspec.info/) or [Minitest](https://github.com/seattlerb/minitest) and it is a matter of preference. If you want something that is close to bare-bones Ruby then use Minitest. If you want something declarative and like having DSLs for things then use RSpec. I find that RSpec is a bit easier to organize and its helpers are nice. Personally I use them both but I've been leaning towards Minitest lately since that is the Rails default. It also has parallel tests out of the box while you have to use something like [parallel\_tests](https://github.com/grosser/parallel_tests) to get that going in RSpec. If you test suite is large then having built-in parallelization is fantastic.

For test setup I use [Factorybot](https://github.com/thoughtbot/factory_bot) instead of fixtures since I find that to be much easier to reason about.

Finally, a word about mocking external APIs. You can do this in many ways from setting up manual mocks using [Webmock](https://github.com/bblimke/webmock), to using fake servers with [Sinatra](https://github.com/sinatra/sinatra) or [WebValve](https://github.com/betterment/webvalve), all the way to replaying previous calls using [VCR](https://github.com/vcr/vcr). They all have their pros and cons, but for fast development I'm a big fan of VCR. You don't have to muck around with setting up mocks with fake data loaded from fixtures. VCR however can be messy too since you literally replaying past requests in your tests. The fixtures created by VCR can also become large and slow. For very fast development however, it is what I recommend. Once you run into enough problems I would take a look at the fake server approach instead.

### Periodic jobs

There are many tools for this. For Sidekiq you can use its [built-in periodic jobs feature](https://github.com/mperham/sidekiq/wiki/Ent-Periodic-Jobs). That is only for the enterprise version however. There are a number of gems with similar functionality like [sidekiq-cron](https://github.com/ondrejbartas/sidekiq-cron) and [sidekiq-scheduler](https://github.com/moove-it/sidekiq-scheduler). There is also the [Clockwork](https://github.com/Rykian/clockwork) gem that is not tied to Sidekiq. Personally I use Clockwork, since that is not tied to Sidekiq and it has been working well for many years. This will however start another Rails process to do the scheduling so there will be extra RAM use.

### Code formatting

You should absolutely use code formatting tools that run every single time you save your files. They take a lot of work out of coding so that you can focus on implementing features.

For Javascript code I use [Prettier](https://prettier.io/). It comes with reasonable defaults and a non-approach to settings. It is opinionated, gets the job done and there isn't a million things to configure.

For Ruby I use [Rubocop](https://github.com/rubocop/rubocop). You can set this up so that it runs using [Spring](https://github.com/rails/spring) by generating a binstub using [spring-commands-rubocop](https://github.com/toptal/spring-commands-rubocop). It will make it run a bit faster. Rubocop also has plugins for your testing framework.

For ERB I use [ERB Formatter/Beautify](https://marketplace.visualstudio.com/items?itemName=aliariff.vscode-erb-beautify). It works very well if you use Visual Studio Code.

### Performing HTTP Requests

I used to use [Faraday](https://github.com/lostisland/faraday) for this but I've switched to the [HTTP](https://github.com/httprb/http) gem. I find it to be a bit cleaner and easier to use.

### Exception management

I use [Rollbar](https://rollbar.com/pricing/) to capture errors in production. It has a very generous free tier and it starts at $1 a month once you go past that. [Honeybadger](https://www.honeybadger.io/plans/) is also a great option.

In development mode you should make sure to use [better errors](https://github.com/BetterErrors/better_errors) to get nicer error pages when things go wrong.

### Continuous integration

If you run your tests and deployment on an external service then you have a lot of options. Personally I use [Circle CI](https://circleci.com/) for all my projects, Ruby or not. It has a very generous free tier as well as extra stuff for open source projects. The paid tier starts at $30 a month which is reasonable.

### Sending email

This is a bit of an odd one to be included perhaps but since getting the emails to arrive safely is pretty then this is quite important. I've used [Sendgrid](https://sendgrid.com/) and [Mailgun](https://mailgun.com/) in the past but I have found them both to be unreliable. Messages don't arrive correctly sometimes or they get stuck in Microsoft spam filters. I would recommend everyone to use [Postmark](https://postmarkapp.com/pricing) for all your email needs. They get the job done and you never have to worry about deliverability. I'm not even getting paid to say that; I just like them that much. They are not free however and start at $10 a month for 10000 emails.

![My Ruby on Rails stack for side projects in 2021](https://s3-eu-central-1.amazonaws.com/mskog-cms/2021/02/photo-1603791440384-56cd371ee9a7.jpeg)

### Slugs

Sometimes you want a nice URL and perhaps not "myapp.com/movies/1234". Instead you want "myapp.com/movies/parasite". For this you should use the [friendly\_id](https://github.com/norman/friendly_id) gem. It handles every single conceivable feature for slugging such as generating slugs, multiple languages as well as slug history if you need that.

### Full Text Search

I think there are two reasonable options here. You can either use a service such as [Elasticsearch](https://www.elastic.co/) or use built-in functionality in PostgreSQL with the [pg\_search](https://github.com/Casecommons/pg_search). I find that pg\_search is better if you can get away with it because it is simply using PostgreSQL. You will need to think carefully about indexes if you have a lot of data though since full text search can be very slow.

If you decide to use Elasticsearch then you should use the [searchkick](https://github.com/ankane/searchkick) gem to make it a breeze.

Finally, you can also use an externally hosted service such as [Algolia](https://www.algolia.com/). Don't immediately reach for that however since you will need to manage indexing yourself and it can become expensive if you have a lot of queries.

### Deployment

If you are ok with paying a bit for hosting then just use [Heroku](https://www.heroku.com/) and don't look back. It is a "push code to deploy" with hosted databases and everything. They have all you need to deploy and run your app, but it can get quite expensive. I went into this in greater detail in [this article I wrote](https://www.mskog.com/posts/heroku-vs-self-hosted-paas/).

If you want the cheapest way possible but still easy then you should use [Dokku](https://github.com/dokku/dokku). It is a self-hosted "mini Heroku". All you need is a cheap server, an hour to install it and then you are off to the races. I went into Dokku in greater detail in the [Heroku post mentioned earlier](https://www.mskog.com/posts/heroku-vs-self-hosted-paas/).

_If you need a cheap and solid server then feel free to use my [referral code](https://hetzner.cloud/?ref=GjnpYTNYtgRU) to get €20 in credit at Hetzner. Read my [review](https://www.mskog.com/posts/hetzner-cloud-review-revisited-in-2020/) for more information._

### Self-hosted tools

These are not Rails-specific but they are very nice to have for any app.

**[Thumbor](https://github.com/thumbor/thumbor)**  
Self-hosted image transformation and optimization tool.

**[Huginn](https://huginn.mskog.com/)**  
Self-hosted Zapier/IFTTT alternative.

**OpenFAAS**  
Self-hosted serverless functions. See [this article](https://www.mskog.com/posts/self-hosting-serverless-with-openfaas/) for more details.

**InfluxDB + Telegraf + Grafana**  
Self-hosted monitoring and visualization stack.

![My Ruby on Rails stack for side projects in 2021](https://s3-eu-central-1.amazonaws.com/mskog-cms/2021/02/kjc8zTZo.png)<figcaption>A Grafana server monitoring dashboard</figcaption>

I wrote more about self-hosted tools in [this article](https://www.mskog.com/posts/self-hosted-tools-for-web-development/)

### Editor tools

There are more examples in my article about [Visual Studio Code plugins for Rub](https://www.mskog.com/posts/visual-studio-code-plugins-for-ruby/)y. These are the essentials:

**[Ruby](https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby)**  
Well...you'll need this.

**[Solargraph](https://github.com/castwide/solargraph)**  
"Go to definition"  in your editor. Code navigation

[**Rails fast nav**](https://marketplace.visualstudio.com/items?itemName=jemmyw.rails-fast-nav)  
Navigate your Rails apps faster

[**Prettier**](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)  
Run and display prettier from within Visual Studio Code

[**rubo-rubocop**](https://marketplace.visualstudio.com/items?itemName=misogi.ruby-rubocop)  
Run your Rubocop cops from within VSCode.

### Monitoring

If you're ok with paying some money then use [Datadog](https://www.datadoghq.com/pricing/). It has server monitoring, log management, and application monitoring. If you want something self-hosted then use the InfluxDB+Grafana stack mentioned earlier and then use [influxdb-rails](https://github.com/influxdata/influxdb-rails) to push metrics. It works really well and Grafana can give you some really solid visualizations.

### Templating engine

I used to be a huge fan of [HAML](https://haml.info/), but now we have things like [Emmet](https://emmet.io/) and autoformatting. I also write HTML in React and Vue so the jump to HAML is not great. I highly recommend that you just stick to ERB which is the Rails default. If you have an app that is full of HAML templates then you can use [https://haml2erb.org/](https://haml2erb.org/) to convert them to ERB.

### Admin tool

I've tried most of the the [admin tool](https://www.ruby-toolbox.com/categories/rails_admin_interfaces)s out there and I find that [activeadmin](https://activeadmin.info/index.html) is the best choice. It has a very powerful, yet daunting, [DSL](https://activeadmin.info/documentation.html) for generating admin tools. You can have a very decent admin section with little effort using activeadmin, so I highly recommend trying that before writing your own.

### Misc gems

In no particular order:

[**Down**](https://github.com/janko/down): Safe file downloads  
[**Discard**](https://github.com/jhawthorn/discard): Soft-delete.  
[**Feedjira**](https://github.com/feedjira/feedjira) **.** RSS management  
[**sitemap_generator**](https://github.com/kjvarga/sitemap_generator) Generate sitemaps with ease  
[**meta-tags**](https://github.com/kpumuk/meta-tags) **.** Create SEO tags, Twitter cards and opengraph sharing attributes.  
**[html-pipeline](https://github.com/gjtorikian/html-pipeline).** Tools for doing auto-linking of URLs inside text blocks and more.

## Conclusion

Wow that was a long one. Thank you so much for making all the way to the end and I hope that your future Ruby on Rails projects will be successful.