Summarized using AI

Serverless Rails: Understanding the pros and cons

Daniel Azuma • April 12, 2021 • online • Talk

The video titled "Serverless Rails: Understanding the pros and cons" presented by Daniel Azuma at RailsConf 2021 critically examines the concept of serverless hosting, particularly in relation to Ruby on Rails applications. The discussion centers around the utility, challenges, and implications of adopting serverless architecture for deploying Rails apps.

Key points discussed include:
- Definition of Serverless: Azuma highlights that "serverless" is a misleading term as it implies the absence of servers, while in fact, underlying infrastructure still relies on servers. The term leads to confusion and misinterpretation of its actual meaning.
- Abstractions in Hosting: The session delves into the evolution of cloud hosting, from physical servers to virtual machines (AWS EC2), and then to more modern abstractions like Functions as a Service (FaaS) and container services.
- Trade-offs of Serverless: Azuma explains how while serverless environments offer fewer guarantees (like CPU consistency), they also reduce responsibilities on the developer's part, potentially leading to cost savings.
- Implications for Rails Apps: The rigidity of Rails as a monolithic framework can complicate serverless implementations. Developers need to consider changes in app initialization, resource management, and data storage when adapting Rails for serverless environments.
- Containers vs. Serverless: The speaker discusses the advantages of container services (like Google Cloud Run) for Rails apps due to their closer resemblance to traditional server environments.
- Recommendations for Rails Development: Specific strategies to optimize Rails apps for these environments are provided, including reducing initialization times, avoiding reliance on the file system, and designing more modular applications.
- Future of Rails in New Abstractions: Azuma expresses the need for the Rails community to adapt to new infrastructures and advocates for a more modular approach in Rails itself, allowing better integration with modern hosting solutions.

In conclusion, the session encourages developers to weigh the pros and cons of serverless deployment for Rails applications, while embracing new abstractions and having open discussions to refine their approaches in an evolving technological landscape.

Serverless Rails: Understanding the pros and cons
Daniel Azuma • April 12, 2021 • online • Talk

Serverless is widely lauded as the ops-free future of deployment. Serverless is widely panned as a gimmick with little utility for the price. Who’s right? And what does it mean for my Rails app?

This session takes a critical look at serverless hosting. We’ll consider the abstractions underlying environments such as AWS Lambda and Google Cloud Run, their assumptions and trade-offs, and their implications for Ruby apps and frameworks. You’ll come away better prepared to decide whether or not to adopt serverless deployment, and to understand how your code might need to change to accommodate it.

RailsConf 2021

00:00:05.060 Okay, thank you all for tuning in. My name is Daniel Azuma, and this session is titled "Serverless Rails: Understanding the Pros and Cons." This is my cat. Since we're all at home, our kids and pets demand screen time.
00:00:11.040 So let's get started. We are going to discuss how Rails interacts with serverless hosting. When should you use or not use a serverless product to deploy your Rails app? And if you do use it, how should you write your app to thrive in a serverless environment?
00:00:18.539 These are important questions for us to talk about because serverless is quite a hot topic right now. There is a lot of interest, and to be honest, there's a lot of hype. We've been hearing promises like zero ops and outsourced infrastructure with automatic scaling. While these are exciting possibilities, we also need to understand the trade-offs.
00:00:34.320 This is your app in production, and it's important to approach these questions in a principled manner. This topic is particularly important to me because I work at a big cloud provider; I'm the lead Ruby engineer for Google Cloud. I've worked on some of these products.
00:00:40.500 I've interacted with our customers and have seen the response in our community when we make serverless announcements. It's been interesting. We released Ruby support for Google Cloud Functions not too long ago, and one of the first questions I received was, 'How do I use this to deploy my Rails app?'
00:00:51.360 In all honesty, I wanted to respond with a different question: Do we really want to use this to deploy our Rails apps? Why do we want to use it? What benefits do we really expect, and what do we think the trade-offs will be? Are we even asking these questions, and how do we find answers?
00:01:05.580 In this session, we're going to critically analyze serverless hosting. We'll start by discussing the term 'serverless.' I'm going to come right out and say this: the marketing people at my cloud provider are not going to like this, but we have to be real. 'Serverless' is a terrible term.
00:01:17.700 It's a lie! Everyone knows it's not really serverless; there are servers involved underneath all the frameworks and virtualization. Ultimately, you're still running on physical servers, and what you're paying for is your usage of these cloud services.
00:01:28.860 So let's be real here: 'serverless' is misleading. Additionally, it's imprecise. No one really knows what 'serverless' means. What's serverless, and what's not serverless? This leads to a lot of confusion. For instance, is Kubernetes serverless? Well, not really. What if it’s hosted in managed Kubernetes? I don’t know. It’s not a useful term; it's a lie that isn’t even useful.
00:03:01.260 So, you know what? We're not going to mention the word 'serverless' again for the rest of this session. Yes, you heard me right. I'm going to pull a bait-and-switch on you. You thought you were going to come learn about serverless, but I won't even use the word anymore. Instead, we'll drill down into the real issues and what these products are really trying to accomplish.
00:03:43.440 We’ll also explore how to think about the differences in infrastructure and what it means for a real-world Rails application. To understand this, let’s take a quick trip back to 2006, when I co-founded a startup with some friends. I convinced them we should build our product on a brand-new framework called Ruby on Rails that had just launched its 1.0 version. It was all the rage!
00:04:03.299 Back then, we didn’t have cloud platforms like we do today. There were a handful of hosting companies, and many of us just installed our own hardware. When it came time to deploy our app, we bought rack servers and set them up in a co-location space. I even spent Christmas day in our server room performing upgrades like reconfiguring the network or upgrading the operating system because we figured that would be the least disruptive.
00:04:30.000 We bought hard drives, installed Linux, and set everything up ourselves. I wish I had photos of that setup. If you start a company, make sure to take pictures of everything, or else, 15 years later, you’ll want to tell stories without having any visuals.
00:05:07.380 A few years later, something new came out: Amazon Elastic Compute Cloud, or EC2. This was a revelation. We could log into a web console, spin up servers, procure hard drives, connect them, install Linux, and everything else we did in physical co-location spaces. The fantastic thing about EC2 was that it looked the same as physical servers, using familiar components like CPU, memory, and disks.
00:06:03.780 The underlying implementation was very different, but how you deployed and interacted with it was basically the same. Amazon effectively provided an abstraction of a server, making this virtualized thing in the cloud look like a physical box you would have seen in a server room.
00:06:30.000 Fifteen years later, it’s crucial to understand how brilliant that was! As software developers, we’re quite familiar with abstraction, but this large-scale abstraction of infrastructure was revolutionary. It’s essential to understand what’s happening today, as new hosting products create similar abstractions.
00:07:08.000 Now let’s consider a very different kind of cloud service: functions as a service. Amazon released Ruby support for Lambda a couple of years ago, and Google recently followed suit.
00:07:15.600 These are all very similar products that are based on a common abstraction—that of a function. So, what is a function? In software, a function is a piece of code that takes arguments and returns a result. Most programming languages have this concept.
00:07:52.380 Now, functions as a service are based on the observation that web applications look like functions as well. A web app consumes a web request and returns a web response. Therefore, we can model a web app as a function. This is a simple web app in Google Cloud Functions, where it’s just a block that takes arguments and returns a result.
00:08:27.360 Notice what's not here: in Rails, you have a routing file and controllers, but in this function model, there’s no routing and no controller. The function simply represents an input and an output. More fundamentally, there’s no disk—functions manage data input and output, but disks are not part of the abstraction; neither are CPU, memory, or operating system.
00:09:00.840 Does this mean a function can't access a disk or use memory or CPU? No, of course not. But you won’t have guarantees about the behavior of these components. In other words, an abstraction is a contract, much like a code contract that describes how different parts of the system interact.
00:09:47.280 For example, when you deploy to a physical server, you can reasonably assume that no one will swap out your CPU while your app runs. This is an unspoken contract; once you boot it up, you're set with that CPU until you shut it off. It’s likely that many Rails apps are designed with this assumption.
00:10:28.500 However, in a function-as-a-service model, CPU is not part of the abstraction. For example, many FaaS services can alter CPU allocation while your app runs, which means you cannot write your app the same way—instead of spinning up a fixed set of workers or threads, you can't assume that a constant CPU will be provided.
00:11:07.920 Similarly, the disk management aspect is different. Some Rails applications maybe write files into their directories—caches, logs, or application data—that's expected behavior in a server abstraction because disks are usually stable and predictable. In a function abstraction, you don’t have those assurances, resulting in issues like directories potentially not being writable.
00:11:56.880 You might wonder why you would even consider using this type of architecture, given that the function model presents fewer guarantees about resources. It's true—functions provide less certainty and you can make fewer assumptions. However, the upside is that you have fewer responsibilities. When your app is deployed to a VM, you're accountable for the CPU utilization, whether or not you've used that CPU.
00:12:27.840 With functions, you're not responsible for CPU utilization. Your app is allocated CPU as needed for executing the function, and you only pay for what you use. Thus, resource management becomes easier.
00:13:06.840 Moreover, much of the operational overhead becomes simpler, including telemetry, error recovery, scaling, and security, as the abstraction is more streamlined. So, we see some trade-offs here: fewer guarantees, but also fewer responsibilities.
00:13:44.640 Let’s visualize these differences. Servers are concerned with resources like disks and CPU, whereas functions are focused on application logic. This fundamental shift in concerns leads us to consider the implications of deploying a Rails application.
00:14:21.240 So, is there a less drastic hosting option? Yes, containers provide another important abstraction. Many hosting products utilize containers, including Amazon's Fargate and Google's Cloud Run, as well as Kubernetes. Containers wrap an application process along with all its dependencies, serving as another way to model the interface between a program and its environment.
00:15:03.060 There is some overlap between containers and servers, but they don't concern themselves with low-level resources. For instance, deploying Rails applications commonly involves starting them up during system boot—however, containers are lightweight and components are often started more frequently.
00:15:53.760 As such, the emphasis has to be on app initialization speed. When running in a container, you should watch your app’s startup time. Cold starts must be quick, as they will happen more often than in traditional server setups. Additionally, it’s common practice on servers or VMs to fork several worker processes, which allows for peak CPU utilization. But with containers, the focus is on processes, and the best practice is to run just one worker per container.
00:17:02.520 Now we’ve discussed the new hosting options and their consequences, so let’s address the question we came here for: How does this affect Rails? Rails is a monolithic framework, providing a lot of features and components like model-view-controller structure, active record, and active job.
00:17:40.320 Its tightly coupled setup means that it may encounter issues when deployed in function environments. While functions can work effectively for specific Rails apps, it's essential to understand the trade-offs involved. Saying this doesn't mean functions and Rails do not mix. The reality is that certain Rails applications can benefit significantly from using functions.
00:18:26.520 For instance, Google Cloud Functions uses Rack as an interface, making it relatively straightforward to write a function that wraps around a Rails app. However, integrating with AWS Lambda can be trickier due to different argument types, although projects like Lambdi can assist with that.
00:19:12.840 Getting the basics to work with functions and Rails is achievable, but understanding the infrastructure’s trade-offs is critical. If you're considering serverless, think about which parts of your app need to interact with the infrastructure.
00:19:54.960 What about containers? As we've seen, there's far more overlap between containers and traditional servers, but some differences do exist, especially concerning initialization and handling processes. In practice, Rails tends to work quite well in containerized environments.
00:20:42.840 Given this, I would recommend container-based services for typical Rails apps, whereas functions might be less favorable. These are generalizations based on my views. Your application’s unique requirements should guide your choices of abstractions.
00:21:28.440 This leads us to another important consideration: the inadequacies of server abstractions. While they have been groundbreaking, servers are often too complex and abstract, making operations management challenging. We need simpler abstractions to pave the way for more efficient development.
00:22:03.480 As Rails developers, we should consider how to adapt our practices. This includes improving code modularity and making initialization faster—doing less during start-up and deferring certain initialization tasks until necessary.
00:22:37.560 We should also be web server agnostic. Avoid tightly coupling implementations to specific servers; for background processes, look into task queues or similar mechanisms. Additionally, reduce dependency on the file system as it may behave unexpectedly in serverless environments.
00:23:18.480 For logging, steer clear of file logging and opt for standard out or standard error logs. When interacting with the file system, utilize Ruby's standard library instead of invoking shell commands. This helps to ensure compatibility with the hosting environment.
00:23:53.880 As for Rails itself, while its server orientation is not inherently necessary to change, improving its modularity would facilitate usage without all server dependencies. For instance, independent use of action view could encourage flexibility in function development.
00:24:31.620 In conclusion, we now have a deeper understanding of these deployment options and their implications, especially with evolving technologies and products. We must stay current with best practices and actively engage in the conversation surrounding these new abstractions.
00:25:47.880 As Rails community members, let’s explore these topics further, experiment, and share our findings as we collectively transition to these modern approaches. My name is Daniel Azuma. If you're at the conference, please join the session chat below this video! I’d love to discuss server infrastructure.
00:26:18.120 Otherwise, thank you for watching and have a great day at RailsConf at home with your kids and pets.
Explore all talks recorded at RailsConf 2021
+65