Hacker News new | ask | show | jobs
by pech0rin 597 days ago
Rails (and possibly Django and Laravel) are just light-years ahead of any other stack for building web apps. They have dealt with all the tedium, know all the requirements, and actually get out of your face when building an application. I have been developing web apps for 15 years now.

I have tried Meteor (back in the day), Remix, Nextjs, Node w/ Express, etc. Always talking about how much better they are. But in my mind web dev is a solved problem. The js stuff is mainly just developers wanking off, driven by a bunch of dollars from big companies.

Systems stuff, deployment infra, etc. is great for stuff like Rust & Go, but shoehorning into web dev makes no sense. I would love to just move on from this debate but it seems thats going to never be possible.

14 comments

I must say that even if it’s not a trendy stack, I find Spring Framework/Spring Boot to be the best all-around web application stack. Very easy integration with the tons of java libs you have around that can do virtually anything, a statically typed language which can help in a lot of situations (just data binding by convention via Jackson is great since forever, while it’s an afterthought in dynamically typed languages).
I've been incredibly pleased with Ktor and Kotlin, as well. JVM underneath, robust libraries, easy to use infra, using Exposed for the ORM which is mostly (genuinely) a joy.

The best thing I think Rails still has is ActiveAdmin. Everything else, I really can take or leave.

Admin is the one area where Django has the edge, but it's enough on its own for me to push Django over Rails for a lot of "just put a UI around some data, please" use cases.
> The best thing I think Rails still has is ActiveAdmin. Everything else, I really can take or leave.

ActiveAdmin gets you off the ground very quickly, but is also extremely inflexible (and, IIRC, poorly maintained). The last time I worked on an ActiveAdmin backend we had to use all sorts of weird hacks to build the interface the way our backoffice team needed it to be.

AA is really just some wrapper and glue around some other tools… which aren’t super well documented either, but it definitely does mean that a) you can do weird/custom stuff, and that it’s a PITA to figure out how.
In another company I had to completely replace ActiveAdmin with "vanilla" Rails abstractions as it was quite buggy and caused Rails to hang indefinitely as soon as you edited any ruby file. The admin part also turned out to be the most used part of the app, so it probably made sense to replace it in any case, but the bugginess at the time was more than I could handle.
I recall Active admin having really clunky UI a couple years ago. I just checked it again and it looks really sleek!
I did write a lot of Java but never called myself a Java developer, and in my current company there are a lot of hardcore Java devs who used to swear by the Spring stack (some even liked JSF!), and a lot of them are moving things to Quarkus (https://quarkus.io/). No idea why, just an observation.
They are moving there because it's new and shiny, not because it's better.

Spring and Spring Boot are incredibly productive and give you a ton of stuff out of the box, whereas some people actually enjoy writing a lot of plumbing code as a distraction/challenge from boring business code. Those people will migrate to "lean" frameworks because it will give them the opportunity to write more low-level plumbing code.

> They are moving there because it's new and shiny, not because it's better.

I highly doubt that.

The real reason is likely more about the GraalVM, which spring hasn't supported until very recently. (And still only with caveats)

That sort of proves my point, though. Spring support for GraalVM is ongoing and will likely be quite useable and mature out of the box.

The people jumping to Quarkus or Micronaut are more eager to chase the new shiny and are willing to spend the time debugging not-yet-mature stacks.

Edit: To be clear, the reply mentions fanboyism but we are talking about the maturity of a stack. Spring has been around for 20 years and is not going anywhere. Quarkus just reached 5.

The GraalVM is significantly more performant. Calling that "chasing the new shiny" redefines the meaning of the expression, which has historically been about side-grades for unclear advantages.

Especially considering that Springs support isn't full yet, and quarkus has been around for 5yrs now.

They're both production ready stacks though, really strange to have spring fanboyism in 2024

JSF can be a great experience when coupled with the right framework like PrimeFaces.
My impression after many years of working with JSF: PrimeFaces or not, it's a lot of server-side state making it hard to work on the front-end and an unnecessary burden on the server.

I have also some nice things to say, and I'm not going to make a detailed analysis here but IMHO, it's really not worth the tradeoff.

Agreed, and yet the celebration of stuff like Blazor Server, Phoenix, among others show that some folks really like this approach.

Personally the experience with JSF and Web Forms, is what makes me appreciate any framework that exposes the underlying browser stack, instead of pretending it is something it is not.

I need to disagree, as I think JSF to be a rather clunky approach, but I admit I never used PrimeFaces.
ASP.NET Core is similar. Not necessarily trendy, but very efficient to work in.
I think part of the problem may be that a lot of people are familiar with old versions of Java before things like lambdas and anonymous interface implementations were possible. Writing Java without some of those things can be pretty painful.
From my experience, these frameworks are like the express lane for kicking off a project because there are no big decisions to make. But once you’re knee-deep in Rails, Django, or Laravel and need to do something off the beaten path, things can get dicey. Why? Because you didn’t write the glue code yourself, so there's a gap in understanding, not really a technical roadblock (most of the time!). My point is, if you dive into these frameworks and actually learn the guts, you'll save yourself tons of time coding by, well, reading code.

Now, do I actually do this? Absolutely not. Rewriting everything is way too much fun, and I live for the thrill of trying new things, even if it makes zero business sense.

When I first learnt Django I sometimes felt like that, but I actually found the source code for it and DRF to be very readable, to the point that it's very obvious where they expect you to step outside the guardrails.
As a personal anecdote,I have not at all found this for drf. I personally dread every time something goes wrong in our api code, it's a sea of overcomplicated inheritance trees (some of this is our fault, but it's at drfs direction imo) and factors that eventually just end up with me never being able to find where anything actually happens, other than via a mountain of print statements.

Django by contrast, I agree, it's perfectly clear. (Though some of the meta magic does get spooky, but that's the nature of meta magic, and I generally find the tradeoffs are worth it)

I liked https://www.cdrf.co/ for exploring DRF.

You basically have either a property or a function with the name get_property for a certain number of things (queryset, serialiser, pagination class, etc.) in any case. I tend to recommend in our projects style guides that once you want to override the behaviour of a mixin, you don’t inherit from the mixin anymore.

The two biggest issues I came across with teams in DRF were people coupling the serialised directly to a single database model (i.e. using ModelSerializer everywhere, even when that didn’t make sense), and trying to put too much stuff into a single class based view or viewset.

I find DRF has a lot of places where someone can alter the behavior of handling the request, which can make it really hard to track down where some field or behavior is coming from. You can define methods on the view, serializer, model, or filter (or some superclass of these) to totally change how some response is formed. It is very flexible, and can save a lot of typing if you have all the conventions in your head (and everybody working on a project strictly follows the same conventions). But I find plain Django or something like Flask much easier to grok.
What’s an example of a feature for a Laravel site where not fully understanding the mechanisms of Laravel under the hood would make that existing code get in the way of building the new feature? Genuine question.
Luckily I have a real life example from a customer project I was involved as a consultant: Integrating a custom identity provider with multi-factor authentication. This was from many years ago though. They also used to have some performance problems in some naively implemented middleware and needed to deep-dive into how things actually work before being able to optimize. And commands - I was doing the integration with our software and their command queue was always causing problems with stuck jobs until they read the implementation. The specific problem with Laravel as a product is (was?) that the docs are too beginner oriented and perhaps "you don't need to know what's under the hood" mindset is exactly what's causing this. I got to know many experienced PHP developers who got really frustrated because of the ELI5 style docs.

You can't always rely on the docs too, however excellent they may be - some game developers read code from game engines to optimize, some web developers read code from their web frameworks. But, some change their whole stack when they get frustrated, and I argue that it makes little to no business sense to do so. Just understand what you are working with and deeply.

I can't speak for the other frameworks, but with Django this would have not been a problem at all. In Django, most "batteries included" features really just are 1st party plugins, i.e. you can choose to not use the builtin authentication stack and bring your own. All of this is officially supported and well documented, e.g. https://docs.djangoproject.com/en/5.1/topics/auth/customizin...
I do not agree. Rails is absolutely great in terms of features and productivity, but will fail you elsewhere i.e. it is not the silver bullet for webdev. Do not take my opinion, look at data - https://www.youtube.com/watch?v=Qp9SOOtgmS4

If you are using Rails for anything where you are not absolutely sure of how many users or RPS you will have, you are just saving money in launch time but spending more on servers.

Shopify is built using Ruby on Rails, they successfully handle enormous traffic spikes during Black Friday sales without issues.

So I think we're good with performance.

Everything can scale if you throw enough servers at it. Of-course Shopify scales, they even spent time and money to build a JIT on top of Ruby. As a smaller company, does everyone have the time and money to spend on servers or optimising the language to this extent?
That's the nice thing! You don't need to optimise the language and build a JIT as a smaller company, Shopify already did that for you. Just like Google did for Javascript, which lead to Javascript having any performance at all (which lead to node being a thing).

Also remember that Shopify didn't start out making billions. They started as a small side project on a far, far slower version of Ruby and Rails.

Same with GitHub, same with many others that are either still on Rails or started there.

You can optimise things later once you actually have customers, know the shape of your problem and where the actual pain points are/what needs to be scaled.

To me, I care a ton about performance (it's an area I work in), but there's not a lot of sense in sacrificing development agility for request speed on things that may not matter or be things people will pay for. Especially when you're small.

No, they only have time for features and productivity, which is, as you pointed out earlier, what rails is good at.
Smaller companies have less traffic, need less expensive servers, and have no need to spend money optimising the language. They can focus on that when they make billions of dollars, like Shopify does.
And in the meantime just passively benefit from the OSS improvements along the way
>So I think we're good with performance.

>On Rails, the most heavy page has a P95 duration of 338 ms. There is of course room for improvement but it's plenty snappy.

I guess everyone will have different opinion on P95 at 338ms. The great thing is that we are getting cheaper CPU Core price and YJIT. As long as this trend continues, the definition of Fast Enough will cover more grounds for more people.

There's lots of tricks you can do, such as preloading pages when the users hovers over the link. This makes even a "slow" page load of 400ms feel pretty much instant to a human.
These kinds of tests are useless (to me at least) for three reasons.

First, these kinds of tests don't do anything useful and just show that some frameworks have more overhead than others. Once you have an app that was developed over years rather than hours and actually does a lot of stuff on every request, it's a whole different game.

Second, the kinds of applications I write rarely get more than 10-20 requests per second. If Rails would peak at 2500 rps as that YouTube video tests it at, that would be plenty. If I were writing some kind of IoT platform rather than a business app, I'd probably not start with Rails for that reason.

Third, for an actual web application, you want to consider what the user experiences, not just how fast the server responds. You can make an application feel much faster than the server response times by preloading on hover, (http) caching, async loading of things that are not visible yet, etc.

> just saving money in launch time but spending more on servers

That seems like an amazingly good trade off, even if it were true which I am not sure about.

I'd go as far as saying it's a selling point, not just a compromise. Flexibility now can come at the cost of vertical scaling when it's EASIER to get funding and when you will probably have cash flow? Hell yeah. Compared to preemptively hyperscaling at an initial high cost, or using a possibly non-existent mythical framework that is somehow hyper performant, low cost, and as flexible as Rails etc... I know what I'd go with.
It is. On the other hand this kind of mindset is the reason why there is climate change.
I’m pretty sure the decision to use Ruby On Rails instead of another platform for building my web applications is not in fact the reason why there is climate change.
the "rails doesn't scale" myth has been debunked for a decade now and anyone with the slightest clue about performance can scale a rails app using the same techniques that you'd use to scale any other language and framework

yjit and fibers have made things even better, and plenty more is coming I'm sure

> you are just saving money in launch time but spending more on servers.

But... That's kind of the whole point

If RPS become a problem you can probably switch to JRuby. I did exactly this 15 years ago for EUs biggest software company and it worked out quite well.
Have you seen the latest state of JRuby development or seen the posts of its development team. If you are comfortable with the idea of your main runtime being dependent on the time / finances / availability of around 5 (or less) core developers I would say you are ok with JRuby.
As someone that used AOLServer, was in a startup doing something like Rails but in 1999 with Tcl, I don't really agree.

The Rails demo wasn't that appealing to me, other than showing the difference on how lucky one might get regarding adoption and spotlight being in the right place.

Nowadays I still don't see a value, and rather go for Spring or ASP.NET.

By the way, the founders of that Tcl based startup, went on to create OutSystems, which is one of the few successful RAD tools for Web development at enterprise scale, and Portuguese success stories in IT world.

Tcl for web development was great and AOLServer ahead of its time
I came through to note that most of this applies to Django, too.

I've historically preferred RoR but with the tremendous growth of Python in the last 10+ years, Django has become a more practical choice. ML and data science devs are already familiar with Python and, with the Django docs being as excellent as they are, these folks can be productive in a very short amount of time -- should they need to be. I've seen this firsthand on multiple projects.

Also, along with the author's case for the path of least resistance, the Django framework results in fewer "decisions" (arguments) about application structure than using a less opinionated library or micro-framework.

The Django/FLOSS community is also much more active than I was expecting it to be (Rails bias, probably) and has been very pleasant to interact with.

I only wish Django had Rails-like generators and in-built data seeding (e.g. rake db:seed).

Django has been an absolute pleasure to work with. Contrast it to flask, which is a complete footgun factory. I agree 100% on there being (honestly, massive) value in reducing decision points in the project. Very few devs truly have the experience needed to see around the corners in their designs and architecture, and Django represents the culmination of decades of learnings on what works, and works well.

Overall, I’ve been very impressed with the product and maintainers. There are so few OSS projects that rise or the level of quality that Django has managed to achieve. Now if only they could sort out type hints ;).

You can seed with JSON files as "fixtures" and run `python manage.py loaddata fixturename`.

The thing I wish Django had better OOTB support for is background tasks, I've not used it but I understand this is very well done in Rails and Laravel.

Interesting! I will give fixtures a look. I've shied away because -- unless you introduce a manual step to generate them, my understanding is that they're static.

You're spot on about background jobs. Rails added support 2-3 major versions ago and there's no shortage of back-ends. With Django, it seems to be Celery-or-bust and there's no Django API that I'm aware of. I actually recently rolled my own solution using SQS and a dedicated compose service which runs a management script (in the Django context). It works but ... it's klunky, the API is ad hoc and there's no monitoring/retries/etc.

I picked up Django as my web server of choice this year and found the same delightful to work with. Given I generate content outside of the django app I had to roll my own data seeder.

It’s actually quite straightforward using CSVs and models to load each row in.

Can see it getting complex once I need to seed a large dataset or with loads of relationships. Look forward to seeing an official 3rd party app that takes away the complexity from my code base for seeding.

I've been using django-seed and it's fine. The API is a little confusing, it hasn't been updated in years and there are some sharp edges (e.g. auto-M2M2M).

Yes, to your point, it would be great to see the jazzband project adopt/anoint it or another solution.

I agree.

Unfortunately every team I’ve worked in hasn’t seen the light and prefers FastAPI/SQLAlchemy/Pydantic (before FastAPI it was Flask).

My theory is that the initial learning curves are different: with FastAPI it’s quick and easy. You barely have to read anything. Django has a steeper learning curve. There’s a lot of reading involved. Type hints aren’t a big thing in Django, but they are in FastAPI, and the average full stack dev seems to like them.

Later on it’s totally different of course. With FastAPI you’re building it all from scratch, and it’ll be much worse than the Django solution.

Type hints are were the whole Python ecosystem is going, so using them is more integration at a deeper level than using an integrated framework, which is not relying on them.

SQLAlchemy was historically a much better ORM than Django's. It's layered architecture combined with Alembic does make a difference.

I still agree that using the integrated thing anyway is probably the right way to do it if you are working in a team. I also think Django should just adopt these components and we would not have the discussion in the first place.

> Type hints are were the whole Python ecosystem is going

I see what you’re saying, but a lot of Python users, especially those who have been using it pre-3, would say that this is unfortunate.

> I also think Django should just adopt these components and we would not have the discussion in the first place.

Oof, such a monoculture sounds terrible to me!

I think SQLAlchemy vs Django ORM was a 2007 blogging topic: https://www.b-list.org/weblog/2007/sep/04/orm-wars/
While it is not Django's responsibility to unite the Python ecosystem, continuing to rely on a tool a sizeable share of the community deems inferior to a popular alternative will keep these discussions open and results in the fragmentation OP is talking about.

Now of course it is not Django's responsibility to unite the Python ecosystem in the first place and they can value other factors and arguments as they see fit.

Although this very thread shows that there might have been something to it.

A corollary is the debate itself leads to a waste of effort that multiplies across all users. I use Rails only in anger, but to see literally nobody bike shed on the ORM is pretty amazing. Seems like you use Active Record or you write SQL and either way move on with life.
In ruby, the sequel database toolkit is vastly superior to activerecord, and that is a subject of discussion here and there. The difference is that rails is what most rubyists use at work, unlike in python, where choices are more diverse.
Why would Django move away from an ORM that works, at scale, in millions of deployed websites? They'd have to support both for many years in any case.

> a sizeable share of the community deems inferior

Well, yeah, SQLAlchemy is standalone, you can use it in a lot more situations than Django's ORM in practice, because you're not tied to using it in a Django site. But that doesn't mean it's "better"

I've had this debate with someone recently, as soon as you actually want to use FastAPI/Flask in something that's not an internal only microservice, you end up building Django on top of it anyway ad-hoc way. It also ends up in more of a mess, because while Django doesn't enforce a code structure as such, the default way of doing things is fairly good.

The main thing I miss about Django is always the DB migrations in any case. I found that pattern to be very flexible and very powerful.

Dotnet is also very good for building web apps, it also includes static typing and a huge ecosystem.

I agree that web dev is basically a solved problem, I don’t know why stuff like next.js exists

Some people like writing typescript.

This forum leans backend heavy and there's definitely a bias against using javascript on the backend. But many top websites use it for their infrastructure. It's not all hype driven development.

I disagree. Rails is fine but just a differential approach. I prefer a standalone fronted that talks to an api layer. Web Frontend for me is remix. Mobile is react native and api layer could be any language you're productive in, eg. Java,.net or javascript.
I like the rails dev experience, but it feels like they haven’t come up with nice new front end solutions that an integrated framework like nextjs has done.

One specific example is images and srcset. If you are doing a react front end anywhere in your app (not even an SPA) interfacing with the asset pipeline doesn’t have a canonical solution.

This just makes it feel behind the times, since what I always liked about rails was the “one right way” that was always reasonably sane.

So it feels like nowadays you need to trade user functional front end app things, like load time and LCP for dev experience in rails. Sad.

I mean the Rails way would be Hotwire. It’s dead simple and a joy to program.
I've been working on a Rails codebase for a few years now. The biggest downside coming from TypeScript codebases is that lack of static typing and the immature static typing ecosystem in Ruby. I know DHH publicly denounced strong typing, but if you're coming from a language with it, Ruby & Rails is a hard sell.
There's some progress in typing ruby code. You may want to check https://github.com/Shopify/tapioca
I just spent two weeks wasting my time trying to code my pet project in various flavours of Next.js plus Prisma/Drizzle etc and gave up at having to constantly reinvent the wheel or work around some incomplete/naive implementation. And then went back to Rails where everything just works. Etc etc etc
It always sounds mean to say it, but there are definitely some things in JS land that feel way more amateur hour by comparison to more established ecosystems.

Somewhat unfair comparison but I expect authors to at least learn from the mistakes of the past.

Reinventing the wheel suggests they're not even paying attention to the past, let along learning from it...
Django.

Plus with Django and Py03, one can write the service layer in Rust(if you’re into that).

It also enables building an interface to Python’s data tools.

I use Django and did a deep dive into py03 the other month seems straightforward to use.

What use cases with Django would you say it makes sense to reach for?

Why bunch Node w/ Express together with the others and dismiss it? (genuinely curious).

Rails has a high learning curve. Perhaps people working with it for years don't notice it. Node + Express seems faster to learn and ship, but my experience with Rails is limited.

“… the rest is developers wanking off …”

Hahaha this made me chuckle out loud.