I've been building some apps with stacks lately that are supposed to be more modern and performant. Namely an app with Spring Boot and another with Micronaut. Both had a React frontend. It really made me appreciate Rails' omakase approach. Just having a form that shows validation errors from the backend and having something as simple as Rails' flash messages isn't solved by the frameworks themselves and requires you to build it yourself or find a third-party solution that might or might not do the basic thing you need or might or might not be well-supported. Rails truly solves the problems 90% of web apps share. It might not be in a way that's perfect for your specific project but it will likely work and you can swap it out one you've validated you app or feature.
Rails is awesome, and so is Django. I’ve built mission-critical apps in both and still do with Python. That said, I’d love to switch to Go for building large monoliths since it has a tighter type system and better concurrency constructs.
The problem is, Go community has never really filled that gap. I love Go, but the whole "Go doesn’t need a Rails or Django" mindset is part of why it hasn’t taken off in this space. Building networking tools and CLIs in Go is great, but when it comes to quickly building a full-stack web app, I still reach for Rails or Django. So this whole "X is dead" doesn't apply to Rails at all.
With tools like ogen[1], one can take a single OpenAPI document and generate server code with a static router, request/response validation, Prometheus metrics, OpenTelemetry tracing, and more out of the box.
It can also generate clients and webhooks. Authentication is just declaring a SecurityScheme in the OpenAPI document then implementing a single function. The rest of the backend is just implementing a single interface. Unlike oapi-codegen, there is no need to tinker with routing libraries or middleware for authentication and logging.
Pair this with sqlc[2] and SQLite's `pragma user_version`, and you get type-safe database code and database migrations for free. I will concede that adding SQLite is a manual process, but its just two imports added to main.go.
Frontend is entirely your choice. Go's standard library provides good enough text templating that I don't miss ERB or Django-style templates. Using the standard library's `embed` package, one can easily embed static assets into a single binary, so deployment can be as simple as `go build` and moving the binary.
I have a hard time using languages besides Go for developing backends, because the code generation tools make Go as convenient as frameworks like Quarkus while staying lightweight and fast.
I was looking for a mature, complete and powerful statically typed stack as well. ASP.NET was my clear answer (not Go or Rust).
There's a lot of noise coming from Microsoft to sell their new products (this year: Aspire.NET). But don't be mislead by this noise: .NET Core (C#, ASP.NET Minimal API or MVC, EF Core) is more batteries included and reliable than most other options. The only gripe I have is the need to get into the OOP and DI mindset ("create custom implementations of some abstract classes and put them into DI and the framework calls your implemented methods magically" kind of stuff). Takes some time, but not a big deal for experienced devs (and younger ones can learn faster anyway :-)).
One can argue it goes against some of the Go principles, but it's a really nice stack for solos or small teams without dedicated SREs. And as you grow you can BYOC & deploy it yourself or completely rewrite your API layer using Go stdlib.
You would still need NextJS or Remix/RR7 for the front-end, but one nice thing is that it would auto-generate the client SDK in TypeScript which makes integration a breeze. And while I personally prefer Remix/RR7 for frontend, Encore has integration with Vercel PR feature which is really hard to beat.
I’m a big fan of Django and Go as well but the only thing in the Go ecosystem that I’ve found that comes close is beego: https://github.com/beego/beego
But it still needs to mature quite a bit before I’d be comfortable saying it’s anywhere near Django or Rails
I’m working on a project in go right now, and I’m really, really enjoying it, but I really do not disagree with you. AI has helped me overcome those framework hurdles. The codebase feels extremely clean to me.
My gut still says rails for customer facing, Django for internal tooling or data work.
Ruby has Sorbet if you want to add typing. And better concurrency constructs for Ruby are in the final stages of being backed with Fibers. For example, Falcon is the new Ruby web server that’s built with Fibers. It’s not quite ready to replace Puma but Fibers are coming along.
The author of Stanza language has this insightful article on the viability of a programming language for creating a powerful framework like Ruby on Rails [1]. Surprisingly there's no Go and Java equivalent, either it's the incompetence of the programming languages (can't) or the programmers (won't), or both.
Node/Express is my goto for quick and dirty picoservices that only really run on local developer machines. Asp.Net WebAPI or MVC is my ideal backend stack
> if you follow (the Rails Guides) start to finish, you'll have a Rails app in production. And it isn't just hello world. Your app will have authentication, caching, rich text, continuous integration, and a database. That's a real application.
These features are great for established apps like GitHub and Airbnb, but if you're making a tiny startup, and want to test ideas quickly, I wouldn't spend time on CI, caching, Rails's authentication (use extremely feature rich Devise gem), Rails's 'turbo' features, and writing tests. These are all good things for medium or larger apps, or well-funded apps with a long run way, but are usually cost-benefit negative for small apps.
Turbo saves a fraction of a second on many page loads, but can add days of development time for those not fluent in javascript when it causes some core functionality to not work (e.g. devise's Log out!). Testing is very important on large apps but for quickly flicking a few ideas together and getting it in front of users; unless you're a banking or healthcare app, they can probably be postponed until you have traction.
Be mindful of your size and timelines and don't succumb to 'default bias' where you use things simply because they were there out of the box. Feel confident to say 'no, we don't need that (for now)'.
If you're looking to build a SaaS app, start with a professionally curated Rails template. It will save you months of development time. Payments/Auth/etc are built in and there are solid patterns in place to extend from.
I don’t agree with your position on tests. I find that writing tests even for small applications saves me time. And that’s even in a language with a sophisticated type system.
I’m also not sure how much time you imagine one spends on setting up CI. In my case it’s just one file with about 20 lines in it, and I usually just copy and paste it from previous projects.
Glad to see Rails is looking better than ever! I've been supporting a few Rails web apps since the Rails 2.3 days -almost 12 years- and today's rails is quite different, like a fully evolved Pokémon. Thankfully the comprehensive Rails Upgrade Guides are solid and well documented. It was manageable to upgrade my apps one version at a time over the years without a major refactor. Rails embraces new developments in web tech, so it's never been backwards compatible, but at least their changes are well documented. ActiveStorage was a huge improvement over the 3rd party gems for file attachments, and came with cloud provider support. The toughest lift was the migration to Webpacker from Bundler for the javascript stuff, which we only finally did a couple years ago. But now it looks like that is all behind us with Import Maps support. I'm looking forward to upgrading these apps once again to 8.1 this year.
I took a pay -loss- to maintain a Rails app for a client with a small budget, about 4 years ago on an outdated app using Ruby 2.3. Super happy with the decision. It’s too easy to add features or upgrade the app and I love working in the codebase.
As a single developer of an open source Rails project that has grown to serve ~120k MAU, I can attest to this article’s claims. One tidbit to add: ActiveStorage, which provides file attachment features, is another excellent piece of the Rails family. I’ve been using Dokku but looking forward to trying Kamal. Rails keeps getting better, and Ruby keeps getting faster.
As someone who doesn't do enough web dev to justify learning Ruby just for Rails: how does it compare to Django? That's the only batteries-included web backend framework I'm familiar with...
Having years of experience in both, though not recently in rails, these are some of my thoughts:
Obviously Django ties you into python and its ecosystem while Rails means ruby (and its gems). The ecosystem is more important than the language. This can either impact your project a lot, or not much at all, depending on context.
Rails doesn't have the equivalent of Django's admin CMS. There are gems but Django is still much stronger. A lot of orgs have their entire CMS / administrated-by-staff part of the product written in it.
Rails, otoh, has a very powerful scaffolding cli. If you are proficient, you can generate some basic crud stuff in minutes from A to Z.
In general, I think Rails is at an even higher level of abstraction than Django. A lot of the architecture or structure is more or less given with rails, whereas you need to make a lot more choices with Django yourself. Routing is a good example. The 'batteries' that are included are also a bit bigger and seem to be in much more active development than Django.
Also a generalization: rails/ruby seems to value brevity and the DRY principle a lot more than is common in django/python. There's a split in taste on this, often python devs find the 'magic' of Rails rather frivolous and unreadable - even though django has a fair bit of metaprogramming itself, whereas Rails devs think the 'pythonic simplicity and straightforwardness' is actually rather crude. Or to be a bit more precise: in the rails world, code duplication seems to be thought of as a greater evil than semantic coupling.
I realize these are all quite subjective, and probably reflecting my own development experience more than being an accurate feature-by-feature comparison.
This is my go to line and nobody has challenged me on it thusfar:
If I was building a web ‘app’, consumer facing product, I’d reach for Rails. I think scaffolding up to ‘market ready’ seems easier in Rails. I say this having never really done this in production.
For internal tooling (using the admin panel), data based work, or geospatial work, stick to python
The biggest difference is python vs ruby. Python’s ecosystem is massive, so if you want to pull in any third party libs you have plenty of choices for whatever you may need. Django also has auth and the admin interface built in, both of which are very nice.
One place that I think there is a big difference in developer experience is in testing. Rails, as described in the article, comes with CI setup and corresponding tests are automatically generated when using rails generators.
Historically, Django Admin is better (in terms of ease of use and flexibility) than anything equivalent in Ruby, but Rails has better conventions for tests and routing. (Or at least that's my opinion.)
I also like ActiveRecord + Arel more than the Django default ORM, but that's more so preference driven by like the Ruby AR syntax more than the Python. (And a general unsupported opinion that Ruby is a slightly better/more pleasant language for writing code than Python.)
There’s a thing here that seems to separate people like the article author from…well, from me. They just have a deep, deep affection for Ruby and Rails.
It makes everything great, and every new surprise is like discovering that your new special friend also knows how to juggle! And speaks Cantonese! How cool is that?? Oh, they’re afraid of spiders? How cute. But did you know they went to Ecuador in college?
There’s a honeymoon effect that just never stops, whereas for me it never started. I’m actually jealous.
Very accurate. Every programming language or framework has this kind of emotional attachment of enthusiastic users, to a certain extent. But nothing quite like Rails. Its in the culture.
Personally, I don't like a variety of things about Rails. Like its love for pluralization of everything. But every time I've wanted to have similar productivity with say, a Javascript backend, I find it basically impossible.
At the same time, I am always shocked out how many people fight against Rails conventions when building in Rails. (Not that you've done this, but seriously, I take over a random code base and they'll have done something like written a worse version of Active Job from scratch for no real reason.)
After using SQLite in production for a little while, I don't think "SQLite is all you need." Migrations are a pain, so any long-lived app will eventually experience pain. As an example, SQLite doesn't have a way to add a NOT NULL constraint to an existing column; you have to rebuild the entire table using a temp table.
> As an example, SQLite doesn't have a way to add a NOT NULL constraint to an existing column; you have to rebuild the entire table using a temp table.
Or any other constraint for that matter, every few months I look for ADD CONSTRAINT again, only to rediscover there isn't anything.
The lack of any sort of PL language (or even just trivial stored procs aliasing queries) also makes migrations more annoying, CTE can handle some of the load but the verbosity and limitations of basic SQL make that awkward, and needing to round-trip through the host language for everything is frustrating (even more so when the host language is statically typed and thus requires adaptation out).
They will have to pry Postgres from my cold, dead hands.
That said, I do think it's really positive that sqlite3 is now a first class option in the framework. Tons of high quality work by very smart people has been invested in recent years.
This isn't what rails advocates, is it? I thought SQLite in rails is a replacement for redis, not for postgres. I've been out of the loop though.
EDIT: this comment is more about rails itself than the actual blog. I take the point being, that sqlite is fine for starting out with a tiny app if you have very little users, and I think that is true.
However, migrating later on to a different database is a always a pain, so I wouldn't recommend starting out with sqlite if you intend to do that later on (with your production data).
Loading comment...
The problem is, Go community has never really filled that gap. I love Go, but the whole "Go doesn’t need a Rails or Django" mindset is part of why it hasn’t taken off in this space. Building networking tools and CLIs in Go is great, but when it comes to quickly building a full-stack web app, I still reach for Rails or Django. So this whole "X is dead" doesn't apply to Rails at all.
It can also generate clients and webhooks. Authentication is just declaring a SecurityScheme in the OpenAPI document then implementing a single function. The rest of the backend is just implementing a single interface. Unlike oapi-codegen, there is no need to tinker with routing libraries or middleware for authentication and logging.
Pair this with sqlc[2] and SQLite's `pragma user_version`, and you get type-safe database code and database migrations for free. I will concede that adding SQLite is a manual process, but its just two imports added to main.go.
Frontend is entirely your choice. Go's standard library provides good enough text templating that I don't miss ERB or Django-style templates. Using the standard library's `embed` package, one can easily embed static assets into a single binary, so deployment can be as simple as `go build` and moving the binary.
I have a hard time using languages besides Go for developing backends, because the code generation tools make Go as convenient as frameworks like Quarkus while staying lightweight and fast.
[1] https://ogen.dev/
[2] https://sqlc.dev/
Loading comment...
Loading comment...
There's a lot of noise coming from Microsoft to sell their new products (this year: Aspire.NET). But don't be mislead by this noise: .NET Core (C#, ASP.NET Minimal API or MVC, EF Core) is more batteries included and reliable than most other options. The only gripe I have is the need to get into the OOP and DI mindset ("create custom implementations of some abstract classes and put them into DI and the framework calls your implemented methods magically" kind of stuff). Takes some time, but not a big deal for experienced devs (and younger ones can learn faster anyway :-)).
Loading comment...
Loading comment...
Java, Kotlin, Scala, C#, F#, OCaml, Haskell, D, are also much better for networking tools and CLI.
And nowadays people can't even complain the Java AOT options are commercial, or .NET is stuck on Windows.
Loading comment...
One can argue it goes against some of the Go principles, but it's a really nice stack for solos or small teams without dedicated SREs. And as you grow you can BYOC & deploy it yourself or completely rewrite your API layer using Go stdlib.
You would still need NextJS or Remix/RR7 for the front-end, but one nice thing is that it would auto-generate the client SDK in TypeScript which makes integration a breeze. And while I personally prefer Remix/RR7 for frontend, Encore has integration with Vercel PR feature which is really hard to beat.
But it still needs to mature quite a bit before I’d be comfortable saying it’s anywhere near Django or Rails
Loading comment...
My gut still says rails for customer facing, Django for internal tooling or data work.
[1] Stop Designing Languages. Write Libraries Instead:
http://lbstanza.org/purpose_of_programming_languages.html
Loading comment...
Loading comment...
Loading comment...
Loading comment...
Loading comment...
These features are great for established apps like GitHub and Airbnb, but if you're making a tiny startup, and want to test ideas quickly, I wouldn't spend time on CI, caching, Rails's authentication (use extremely feature rich Devise gem), Rails's 'turbo' features, and writing tests. These are all good things for medium or larger apps, or well-funded apps with a long run way, but are usually cost-benefit negative for small apps.
Turbo saves a fraction of a second on many page loads, but can add days of development time for those not fluent in javascript when it causes some core functionality to not work (e.g. devise's Log out!). Testing is very important on large apps but for quickly flicking a few ideas together and getting it in front of users; unless you're a banking or healthcare app, they can probably be postponed until you have traction.
Be mindful of your size and timelines and don't succumb to 'default bias' where you use things simply because they were there out of the box. Feel confident to say 'no, we don't need that (for now)'.
Jumpstart Pro is great. https://jumpstartrails.com/
So is Bullet Train. https://bullettrain.co/
Loading comment...
Loading comment...
I’m also not sure how much time you imagine one spends on setting up CI. In my case it’s just one file with about 20 lines in it, and I usually just copy and paste it from previous projects.
Loading comment...
Loading comment...
Loading comment...
Loading comment...
Loading comment...
Loading comment...
Loading comment...
Asking out or curiosity.
Obviously Django ties you into python and its ecosystem while Rails means ruby (and its gems). The ecosystem is more important than the language. This can either impact your project a lot, or not much at all, depending on context.
Rails doesn't have the equivalent of Django's admin CMS. There are gems but Django is still much stronger. A lot of orgs have their entire CMS / administrated-by-staff part of the product written in it.
Rails, otoh, has a very powerful scaffolding cli. If you are proficient, you can generate some basic crud stuff in minutes from A to Z.
In general, I think Rails is at an even higher level of abstraction than Django. A lot of the architecture or structure is more or less given with rails, whereas you need to make a lot more choices with Django yourself. Routing is a good example. The 'batteries' that are included are also a bit bigger and seem to be in much more active development than Django.
Also a generalization: rails/ruby seems to value brevity and the DRY principle a lot more than is common in django/python. There's a split in taste on this, often python devs find the 'magic' of Rails rather frivolous and unreadable - even though django has a fair bit of metaprogramming itself, whereas Rails devs think the 'pythonic simplicity and straightforwardness' is actually rather crude. Or to be a bit more precise: in the rails world, code duplication seems to be thought of as a greater evil than semantic coupling.
I realize these are all quite subjective, and probably reflecting my own development experience more than being an accurate feature-by-feature comparison.
If I was building a web ‘app’, consumer facing product, I’d reach for Rails. I think scaffolding up to ‘market ready’ seems easier in Rails. I say this having never really done this in production.
For internal tooling (using the admin panel), data based work, or geospatial work, stick to python
Loading comment...
Loading comment...
I also like ActiveRecord + Arel more than the Django default ORM, but that's more so preference driven by like the Ruby AR syntax more than the Python. (And a general unsupported opinion that Ruby is a slightly better/more pleasant language for writing code than Python.)
Loading comment...
Rails gives you way more structure than Django.
Loading comment...
Loading comment...
Loading comment...
Loading comment...
Loading comment...
It makes everything great, and every new surprise is like discovering that your new special friend also knows how to juggle! And speaks Cantonese! How cool is that?? Oh, they’re afraid of spiders? How cute. But did you know they went to Ecuador in college?
There’s a honeymoon effect that just never stops, whereas for me it never started. I’m actually jealous.
Loading comment...
At the same time, I am always shocked out how many people fight against Rails conventions when building in Rails. (Not that you've done this, but seriously, I take over a random code base and they'll have done something like written a worse version of Active Job from scratch for no real reason.)
Or any other constraint for that matter, every few months I look for ADD CONSTRAINT again, only to rediscover there isn't anything.
The lack of any sort of PL language (or even just trivial stored procs aliasing queries) also makes migrations more annoying, CTE can handle some of the load but the verbosity and limitations of basic SQL make that awkward, and needing to round-trip through the host language for everything is frustrating (even more so when the host language is statically typed and thus requires adaptation out).
That said, I do think it's really positive that sqlite3 is now a first class option in the framework. Tons of high quality work by very smart people has been invested in recent years.
EDIT: this comment is more about rails itself than the actual blog. I take the point being, that sqlite is fine for starting out with a tiny app if you have very little users, and I think that is true.
However, migrating later on to a different database is a always a pain, so I wouldn't recommend starting out with sqlite if you intend to do that later on (with your production data).
But in the rails context couldn’t you mostly manage with an ActiveRecord validation? I know it wouldn’t be ideal.
Loading comment...