I have no strong opinion on serverless but I’ve used Rails for 13 years now (in massive $multi-million SaaS products as well as hobby projects) and it still makes me happy. I keep thinking about learning Node and React but I just can’t be bothered because Rails lets me get things done so quickly while also being a joy to write Ruby and Rspec.<p>Regarding hosting, I think this is actually a great time to host Rails apps either via Heroku, via the new Digital Ocean k8s app cluster or – and this is my new favourite tool – using Hatchbox.io to deploy apps to Digital Ocean or AWS. It’s a dream!
Every time I read that one of the “downsides” of RoR is that it “doesn’t sound cool” I know I’m in the right place! I’ll have mature teammates who understand the right tool for the right job. I won’t have to work with magpie developers with an acute case of not-invented-here syndrome.<p>Granted Rails isn’t the answer to everything. I’ve been loving what we can accomplish with elixir/Phoenix. But I’ll leave the hipsterism to the JS community and marvel as they reinvent wheels over and over again.
For people in a similar situation, I'd strongly suggest giving Phoenix (on Elixir) a look. It's a "boring" Rails style server side rendered web framework, but with a few extra powers:<p>* Elixir is a great functional programming language<p>* When your backend needs to do more complex or longer running work it's just more Elixir rather than complicated architecture involving task queues etc. (because you have the concurrency of the BEAM to manage it)<p>* You have options like LiveView for your frontend. You don't have to use it, but it's there.<p>I agree with what you said about testability for Lambda style architectures. How do you spin up an offline version of some or all of that to see if it works? The BEAM world is nice for me because you can run a similar architecture of separate things (albeit all in one language), but have a much better testing setup.
I've seen a lot more discussion of Ruby recently than in past years, and maybe I'm just finding what I'm on the lookout for, but either way it makes me happy :)
> A lambda publishes a message to SNS, another one picks it up and writes something to DynamoDB, the third one takes that new record and sends an email…<p>Or, you know, just do related functionality in the same AWS Lambda function. While I would probably do the sending of an e-mail asynchronously as well (as AWS Lambda function triggered by a DynamoDB stream), the indirection over SNS to write something to DynamoDB seems overly complex.<p>Why would you do something asynchronously with a Serverless architecture you'd do synchronously with Ruby on Rails?<p>> […] and random hardcoded configs in AWS console.<p>Just don't do that. A Serverless application will always be a pita if it relies on manual configuration. Ensure all relevant configuration is part of Infrastructure as Code (e.g. CloudFormation or Terraform).<p>> Impossible to replicate production environment<p>If the project is set up properly with Infrastructure as Code replicating the production environment is as easy as it can possibly get. And because it's Serverless, if an environment isn't used, it usually doesn't even incur notable costs.<p>There is no silver bullet and I believe Serverless as well as other approaches have their place, but what I miss are similar posts about great experiences with Serverless applications. I for myself wouldn't want to go back and I'm really happy with the problems Serverless applications solve.
I've been tinkering with Serverless (on AWS) for some client work recently and my view is about the same as this post. Every complaint he listed is what I encountered too. It's one of the most unfriendly dev experiences I've seen in ~20 years of development.<p>OP's post contains:<p>> What started as a simple function, grew into a bunch of serverless functions, SNS topics, S3 buckets, DynamoDB tables. All bound together with plenty of YAML glue, schema-less JSON objects passed around and random hardcoded configs in AWS console.<p>With SAM, it's still a ton of boilerplate too.<p>And honestly, even most simple functions are going to use SNS topics, S3 buckets and CloudWatch so you can see your logs. Probably a datastore too. Or if you want to access the Lambda over HTTP instead of an SNS trigger, then you'll need something like API gateway or a load balancer too.<p>It's even more fun if you decide to write to an RDS instance that's locked down by IP address and inside of a VPC while at the same time your Lambda needs external internet access. The amount of hoop jumping to get all of that to work was unreal. And it ended up costing $33 / month just to have a NAT set up to route all of the internet traffic between these services.<p>The infrastructure complexity was more than anything I've ever experienced in any tech stack. But I thought the goal of Serverless was to avoid infrastructure?<p>Then there's the whole problem of wanting to wire up your main non-serverless service wanting to trigger a Lambda using SNS topics. That's fine until you want to be able to develop the project locally, except SAM and other comparable tools don't mock out SNS. So now you're stuck either having to pay to have your dev environment running on AWS or set up something like localstack to mock out a bunch of AWS services (which isn't free either btw).<p>The messed up thing is, after all that, it was to be able to run about 20 lines of Python business logic. All it did was call out to a 3rd party API service and store the results into a database.
I pretty much just start all of my projects, no matter how small, with Django. Working with microframeworks or serverless is great at first but as soon as you need any more of the typical features that a webapp requires then you start pulling in dependencies or re-implementing half of Django yourself anyway. First you just need a little url router to some basic views. OK that's great, anything can do that. Now you need to validate some forms. Now you need to manage some session cookies. Now you need to let users reset their passwords. Now you need to look at your data and maybe export a csv. It just goes on and on.
You can have the best of both worlds with Ruby Jets <a href="https://rubyonjets.com/" rel="nofollow">https://rubyonjets.com/</a>. Build micro services inside of a monolith. Might not make sense, but you're essentially building one app that deploys to micro services in AWS, in your favorite language and a framework that is essentially Rails.
I like using the “serverless monolith” architecture. You use a catch-all API gateway hooked up to a single lambda. You write it the same as any standard HTTP server and let an adapter handle the lambda bits[1]. During development you run it as a regular HTTP server and connect directly to localhost. To deploy it all you need is a shell script that zips and uploads your binary to lambda. All state is stored in DynamoDB. One log stream for everything.<p>The downside is dealing with AWS events. There’s a few ways to handle it. You can write it into your monolith, toggling behavior with say an environment variable. You can sometimes work around it, for example avoiding the S3 file uploaded event by having clients ping your HTTP API on upload completion. Of course, there are trade offs for all the techniques. You can easily reconfigure a lambda to retry on failure but you’d have to manually implement that client-side. You can also always just add another lambda if you’re ready.<p>To put it another way: you probably don’t need to write that record to a queue which gets written to DynamoDB, whose stream calls another lambda etc etc. Just do that stuff within a regular old HTTP handler until the fanciness is absolutely necessary.<p>For personal projects, I appreciate how serverless scales to zero. I don’t have to worry about axing projects with minimal usage.<p>[1] for example <a href="https://github.com/akrylysov/algnhsa" rel="nofollow">https://github.com/akrylysov/algnhsa</a> or <a href="https://github.com/awslabs/aws-lambda-go-api-proxy" rel="nofollow">https://github.com/awslabs/aws-lambda-go-api-proxy</a>
Understandable.<p>As I wrote in my last article [0], serverless advocates pushed too much FaaS in the last years.<p>FaaS is awesome, but should be the last resort, if you throw too many functions at a problem you can easily end up with a distributed monolith, which is often worse than a regular one.<p>[0] <a href="https://dev.to/fllstck/serverless-myths-56dc" rel="nofollow">https://dev.to/fllstck/serverless-myths-56dc</a>
X as a service seems easier at first because complexity is hidden, but it's not going away.<p>Old boring stacks can still go a long way for small/medium projects.
Also consider giving Crystal lang a look, in particular the Amber and Lucky web frameworks. Amber in particular is designed to feel just like Rails and accomplishes that pretty well in my opinion.<p>Crystal is designed to feel like Ruby but to be "fast like C". I think in reality by adding a type system it manages to be better than Ruby.<p>Small but very welcoming community with a number of startups and companies running things in production. Crystal itself is doing well with the 1.0 release looming very soon.
How are you finding managing infra for rails? Is disaster recovery quick for you?<p>I'm the author of openfaas and hear what you say about the fragmentation for using AWS Lambda. We recently made a rails-esq version of OpenFaaS for users who have a single small app like yourself. I would be interested in your impressions. It's all open source and is a bit more of a more modern stack. On the upside it uses containers and you can write in any language.<p><a href="https://www.openfaas.com/blog/faasd-tls-terraform/" rel="nofollow">https://www.openfaas.com/blog/faasd-tls-terraform/</a>
I’m not sure the issues experienced are due to serverless rather than the architecture chosen. A monolithic app vs services.<p>Why split up the serverless functionality into separate functions connected with SNS etc? You can call the same ruby code from a single serverless lambda endpoint invoked from a http call in the same way you would from a rails process.<p>Rails is great, but you could run Rails on a serverless architecture (AWS) too if you really wanted to, and you could create a multi service architecture of Rails components that would be equally hard to maintain and develop.
Serverless has its place. I am not sure if I'd chose to build a shopping cart on Serverless just yet (Next.js' recent forays notwithstanding), but for something that is stateless (like content distribution, capturing metrics and logs, serving static webpages)...oh, is it a breeze.<p>That said, I see many promising upstarts <i>and</i> incumbents in the space trying to make stateful Serverless easier by the day. Things can only improve and improve they will. I'm bullish.
AWS Amplify[1] actually has neat tooling for serverless projects and lets to deal with just the core of your product and worry less about infra. Admittedly, it helps if you know the underlying connections but in my experience that's true with rails too. Building a blog with rails isn't the same as a more complex product.<p>[1] <a href="https://aws.amazon.com/amplify/" rel="nofollow">https://aws.amazon.com/amplify/</a>
In OO systems, we often talk about "Simple Objects & Complex Interactions" v/s "Complex Objects & Simple Interactions".<p>In my experience, being at either extreme becomes counter-productive.<p>To me, it comes down to finding the "happy middle" for your project.<p>Monolith v/s Micro-services/Serverless are similar. Neither extreme is productive. There exists a happy middle depending on the situation.
One thing you have to realize, is that "enterprise" architectures are as much about workforce management as they are about efficiency, or scalability, or et al.<p>There's a limit to how reduced data, and functions that work on data, and the transports and relationships between it all, can get. Let's call this residual mass "goo". Well, the goo has to go _somewhere_.
For those in this predicament, consider mine -- I'm about to migrate a non-serverless collection of nodejs microservices to Rails via Ruby on Jets, which apparently has full support for running standard Rails apps these days. I can't imagine something more powerful than a Rails app running in a Lambda.
I moved to Phoenix and it is wonderful. Except... Ecto just isn't as easy as ActiveRecord and you can't do things the way you would prototype things in IRB. So, yeah, on one hand, I have crazy performance and LiveView etc, but on other, it is huge hassle just to hack around the way I did before.
Having worked with AWS serverless for a couple of years, I think the architecture is not well suited for replacing a monolithic application. If horizontal scaling is an issue, I think containers are better suited. Serverless seems to be a better fit for ETL/Data Transformation workflows.
Lambda is a product for big non agile companies who want to show they can be agile.<p>If you are a single developer there are barely any reason to use it
I'm looking at Blazor/wasm nowadays and it's causing me an awful lot of nostalgia when I think back to the early days of Rails (if '08 can be called early days per-se), because of the shit show back then with various tech stacks and the grunt work required to get a site up with some DB backed data source and whatnot.<p>And I feel like today we are back to some kind of a point of having to shoehorn FE/BE tech together unless we use some isomorphic approach which, predominantly, forces the use of JS.<p>And I remember DHH commenting on this regarding Java and saying something to the tune of "Why would I write Java when Ruby is so much better?". Back then I thought such a statement was too indignant, like someone getting on their high horse about a particular kind of building material that is better above all else. But nowadays, I see the wisdom behind it all the same.<p>I just want simple bloody tech that treats the browser as a layout and input handling engine and lets me write code in any language I see fit, whether it's Ruby, F#, C#, Clojure, whatever. I'm hoping Blazor or something like it can deliver on that vision.
Seems to me that the ideal would be a heavier-weight convention-over-configuration framework that "compiles down" to Cloudformation + Lambda code.