localStorage.setItem('theme', value ? 'dark' : 'light'))" :class="{ dark: darkMode }">Judoscale on Tour: Render Has the Pieces, Not the Workflow
Tl;dr:
The Mental Model
Render: Shipping Friction
Render: Debugging Friction
Render: Infrastructure Friction
Render: Organizational Friction
So.... Render?
Judoscale ‘On Tour’ Series
“The Friction Model” & Heroku
Render (This page!)
Railway (Coming soon…)
Fly (Coming soon…)
Northflank (Coming soon…)
Digital Ocean (Coming soon…)
Amazon ECS Fargate (Coming soon…)
After about a month of migrating, tweaking, and configuring, our opinions are in! We successfully migrated our full production and staging application stacks to Render. We tried as many bells and whistles as we could, let things run for a non-trivial amount of time, and have some interesting thoughts to share with you.
👀 Note
The “Judoscale Tour” is our exploration of today’s PaaS offerings via deliberately migrating our real production app, our staging systems, and our development workflows to each of said offerings in sequence. It’s a big endeavor, but we want to know first-hand what each PaaS service on the market truly feels like. And we want to relay that information to you with receipts! We outlined our strategy and rubric in our first edition, the more-reflective, “An Ode To Heroku”.
Tl;dr:
There’s no need to make you wait if you want a quick conclusion: our thesis landed a little differently than we first thought, but in the same ballpark… Moving from Heroku to Render means you’ll probably save a good chunk of change (likely 30-40% depending on what types of Heroku Dynos you currently pay for and run), but Render isn’t as simple or easy as Heroku. You will trade some of your development and maintenance time for those infrastructure dollars. You will own more. Render has a few neat features, but it simply doesn’t nail the simplicity that Heroku’s always had. That’s our tl;dr. But there’s a lot of nuance there, so we’d encourage you to read on.
The Mental Model
Since The Judoscale Tour is all about exploring potential alternatives and migration paths away from Heroku, we want to preface our thoughts and results with a quick sidebar of how the mental model for a given platform might differ from Heroku’s. In the case of Render it’s… tricky. Heroku’s primitive object upon which everything is built is the “app” — a collection of processes which are themselves distinct (web, fast-worker, slow-worker, clock, etc.), but which collectively act together to make up an application. Render, on the other hand, took the path of the processes themselves being first-class citizens; top-level constructs they call “Services”. For sure, that allows for greater flexibility and control in how things operate together, but it also means that certain app-level lifecycle events are overlooked and have to be built / coordinated yourself. You’ll see what we mean as we go over some specifics here, but just understand that a collection of disparate services (which have no workflow connection to one another) can be annoying.
This image may be a little over-emphasized… having separate services isn’t as bad as it looks, and having a cohesive app isn’t all harmony!
Render: Shipping Friction
At the very outset, getting your first Render service configured and deployed will likely be pretty easy! The git-connected, just-pull-from-Github/Gitlab/Bitbucket flow feels very familiar. Render has prefab buildpacks, configs environment variables from the web UI, and takes you right to a metrics dashboard. Sounds very familiar 😆.
✅ Tip
Even though it’s not documented anywhere that we could find, Render’s Ruby buildpack does luckily include Jemalloc. Just use the super intuitive environment variable LD_PRELOAD = /usr/lib/x86_64-linux-gnu/libjemalloc.so.2. Duh! 🤦♂️🤦♂️
But your application is more than a single service! Building out additional services via the Render web UI is, again, straightforward, but you might shift toward making a Blueprint: a YAML file that declares the shapes and basic configs of all services within your repository (*cough* app). While it can feel nice to have many basics configured in code rather than freely changeable web UI, it introduced some confusion for us. Mostly anything we can configure in a Blueprint, we can also configure in the web UI… even though we made a Blueprint. For example, our Blueprint for our judoscale-prod-clock process contains a buildCommand of bundle install. And when I open that service in the web UI, I see the corresponding build command:
And you might say, “Well yeah, it’s just telling you what’s in your Blueprint!” But you’d be mistaken (as we were)! And you’ll also note there’s an “Edit” button. Yes, you can open that field and edit the build command from the web UI! So then which one actually runs? The Blueprint command or the web UI command? That’s a great question! 🙃
Nonetheless, the zero-to-running-in-prod workflow...