As I near the milestone of two decades writing code, it strikes me that the software development industry is intensely cyclical. It always has been, but now I've been around long enough to start seeing the cycles. Don't believe me? Well, take that newfangled functional programming. It's actually been around in practice since the 1960s and in concept as far back as the 1930s. Today, I'm going to talk about a couple of relatively avant-garde concepts in software development: feature flags and serverless architecture. But make no mistake. Both have existed as concepts for a long, long time. And to understand the best way to use feature flags for serverless architectures, you need to understand the backstory of both techniques.
What Do We Mean by "Serverless"?
First, let's get somewhat specific about defining "serverless." If you've never heard this term in its modern context, you might just think, "Oh, old-school desktop apps!" But that's not the idea. In the year 2017, just about no application comes and runs in a vacuum. Even something like a solitaire game probably phones home to check for updates and patches. And that logic and those patches sit on, you guessed it, a server. The modern software development world is intensely interconnected and everything relies on some always-on, always-available service of some kind. So when we talk about serverless, we don't mean no servers. Rather, we mean no servers that are your responsibility. Historically, enterprises built applications soup- to-nuts, starting with a database and working up in layers of abstraction to the finer points of the GUI's markup. Of course, when you build applications this way, you have a large maintenance footprint. You stand up and maintain a database server, a web server, an application server, etc. Then you manage all of the building and deploying to those things. Unless you go serverless. When you go that route, you make the backend infrastructure someone else's problem, thus reducing your maintenance footprint. Imagine, for instance, writing a "random photo" app. You could build and maintain a giant database of photos and write an application that showed them to people at random. Or, you could just write a little randomizer utility and have it call out to a public photo-sharing site.
The Nature of the Serverless World
I led into this post with a bit of old-man, "get off my lawn" language for a reason. You could look at serverless as a cool new trend, and justifiably so. But you could also look at it as something that has been around for as long as I can remember: writing glue code. Sure, a lot of the technologies involved these days are more sophisticated, particularly the ones involving cloud platforms and containers. But at the end of the day, we're still talking about writing an app that serves as the go-between for someone else's data and yet a third party's GUI or service. Call it glue code or call it serverless architecture, it's something developers generally understand for inherent, important properties. This sort of code tends to be stateless or at least to encapsulate a relatively minimal amount of state. You're mainly just doing transforms and putting abstractions over others' data. These serverless apps will also have an enormous dependency profile, creating risk and churn. If you want to write a random photo app and have it depend on Photos 'R' Us for publicly available photos, then Photos 'R' Us becomes pretty vital to your app's success. If that service shuts down or boots you, you kind of don't have an app anymore. So understand serverless architectures the same way you might understand glue code. They're relatively inexpensive to develop and also relatively inexpensive to maintain. But they're risky, volatile, and dependent on your ability to react quickly for success.
The Role of Feature Flags
Because of these downsides, feature flags make for a natural pairing with serverless architectures. Feature flags aren't new either. Not exactly, anyway. They've existed since someone first paired an if statement with a configurable setting. But taking a systematic architecture approach with a feature flag management system is a relatively new development. And it's one that should form an important part of your strategy if you go the serverless route. When you think of feature flagging, you probably think of sophisticated systems like Facebook's. These allow granular and low-risk rollouts of individual features. But think more philosophically of what they're doing. They're taking decision logic about their application and intentionally externalizing it. They're deferring decisions from build time until run time, when they'll have more information. Should we have this new "I hate this" button turned on? Dunno yet. Let's roll it out to a fraction of users, see how they respond, and then decide. For Facebook, that's the killer application. But for a serverless architecture, you're deferring different sets of decisions in order to thrive. Let's take a look at those decisions and how feature flags help.
Use Feature Flags for Testing
First up, think of testing. If you're building the photo randomizer, you're going to want to test it before you actually roll it to production. But that sort of testing can become pretty hard when you're so reliant on a third-party service's production situation yourself. Some of this you can address with extremely granular unit tests. But you're going to want other kinds of tests as well -- tests that cover the overall behavior of the app but stop short of going out and banging against some third-party API. Feature flags can help with this for your serverless app. You can, in essence, create a configurable setting. In one style of configuration, it points at the real thing, and in another, it points at a mock of that system that you've created for testing purposes. This style of mocking is familiar to anyone with a lot of automated test experience, but it's really critical in the serverless context, where your application integrates so fundamentally with third-party software.
Feature Flags Can Guard Against API Quirks and Limitations
Because of this tight integration and this outsize dependency, you also have risk once you get to production. You ship your code to production, set the flag to point it at the third-party stuff instead of your mocks, and sit back to watch it work. But what happens if it works erratically or awkwardly? This isn't as pessimistic as it sounds. Think of our random photo app example. What if the photo service you're using imposes an access limit on your account or throttles you at some point? What if it segments its library somehow? There are all sorts of contingencies that you might need to consider when depending on a service like this that didn't necessarily design itself with your use case in mind. Feature flags can help you here too. At the bare minimum, they give you the ability to switch from normal operation mode to a "please try again" that doesn't involve weird call stack exception messages. But you can get more sophisticated as you learn the nuances of your partner service. Maybe you have a few access accounts that you switch between, or maybe you get an account with a second backup photo service and can switch over to that one if need be. You can implement flags as guards around any API peculiarities you learn about.
Feature Flags Protect You From Volatile or Short-Lived Services
And speaking of peculiarities, it doesn't hurt to guard yourself against more drastic situations as well. API limits and throttling aren't the only situations these third-party tools might throw your way. What if they change their pricing structure to something you can't tolerate? Or what if they shut off public access? In fact, what if they just close the doors and go out of business? You could find yourself in pretty big trouble. Using a feature flag management approach from the beginning lets you hedge your bets. You can have a preferred service and then one or two backups. And the flexibility of deferred decisions allows you to adapt as you go. Maybe you alternate consistently between all three, so one folding doesn't matter too much. Or maybe you have a preferred service and a couple of contingencies. You want this flexibility in case the things fail or in case something better comes along.
Taking Full Advantage of Serverless
I can't possibly enumerate all uses you might have for feature flagging with serverless apps. I've covered a few important categories here, but your specific situation will depend on your own needs and preferences, as well as the properties of the services and data stores you use. But that's the beauty of the feature flagging approach. It lets you defer decisions while you learn and observe. You don't need to know exactly what you'll need as you write the code -- only that you might want to do something different later. If you at least know that, you can add a flag as a seam for future changes that you integrate easily. The world of software moves in cyclical fashion, but principles stand the test of time. If you're going to keep your costs low by relying on third parties for services and maintenance of those services, you need to insulate yourself against the risk that approach creates. And feature flags are all about insulating against risk.