Log in to watch

Log in or create a free account to watch this video.

Log in
Virtual US 2022
Share

Full Stack Feature Flags with LaunchDarkly

Feature flags have become a core staple of the development lifecycle. Most commonly associated with frontend usage, feature flags enable progressive delivery of new capabilities and simplified rollbacks.



This allows front-end developers to deploy with more confidence, but what about the rest of the stack?



Backend development creates critical plumbing for modern applications. Changes to these structures or migrations to different technologies can have cascading effects, both positive and negative, for front-end services that rely on these backend structures. As a result, backend changes are met with some trepidation and skepticism, after all, if it isn't broken why fix it?



Instead, organizations should look to expand feature flags and feature management solutions beyond the front end.


In this talk, we'll discuss how LaunchDarkly can be used to handle both frontend and backend changes and show a quick demo of the platform in action. We'll cover topics like using progressive rollouts for migrating backend services, the benefits of implementing prerequisite rules for feature flags, and how you can use experimentation data to optimize your releases.


This session is presented by LaunchDarkly.

Chapters

Full transcript

The complete talk, organized by section.

Peter McCarron

Hey everyone. My name is Peter McCarron. I'm a senior technical marketing engineer here at LaunchDarkly. Today I'm going to talk to you about full-stack feature flags with LaunchDarkly, or essentially how we can layer feature flags through every layer of our application.

Before we get started, let's quickly touch our agenda. We'll do a quick introduction of us here at LaunchDarkly and what we believe in. We'll talk about what feature flags are. This may be your first time hearing about them. You may be familiar with them, but you just need a refresher, so we'll talk a little bit about that. We're going to talk about how feature flags are viewed on the front end versus the back end, so maybe how some of our developers might feel about feature flags and how some of our operators might feel about feature flags. Then we're going to talk about our back-end use cases: where do feature flags fit in, where are some of the advantages of using feature flags on the back end, and then we'll put it all together with a quick demo.

Before we get started into the content here, let's talk a little bit about what we believe here at LaunchDarkly. The main idea is software powers the world. Right now I'm recording this for you on my laptop. You're going to view it on the virtual platform for this conference. You're going to communicate with others on things like Slack or WhatsApp. You're going to send emails later. Software really touches every facet of our lives. With all that software comes a number of software releases, and it's in software releases that we start to see this increasing level of risk as well as complexity, and that can create a slowdown in innovation. At LaunchDarkly, what we're trying to do is help solve that software release problem.

To go a little bit deeper, if you think about it from the pipeline process as a developer, the main things that I care about are I'm going to plan, build, and test my application code, make sure that it all works, and then I'm going to push it to my customers. It's in this deploy and release process that we may run into some challenges that can create some really bad experiences for end users. Let's say I ran some code that happened to be working perfectly for me, but when I pushed it to my end users, they start to run into an error page. Now we have to go through this whole process of trying to roll back to a more stable version. We could potentially have an outage. It could cost us potentially money or cost our customers having a bad experience, and they may not want to come back to our software again.

From a LaunchDarkly standpoint, what we're trying to do is help transform the way that organizations deliver software. The way we're trying to address that is in three ways. First and foremost, we're trying to help you achieve release management at scale. Our platform is built for enterprises. We're going to have governance and automated rollout capabilities, which will help you be able to deploy your applications pretty much at any scale.

We are also not only helping with the release process. Once the product gets released, how do you gather insights and information about its performance in order to make improvements? At LaunchDarkly, one of the things we want to do is help you optimize your product by offering experimentation capabilities that let you measure the business value of the choices and the changes that you make to your software.

Last, and certainly not least, we've all heard about this journey to cloud. We're starting to move away from our traditional on-premise systems into more of a microservice, maybe cloud-based architecture. As we're making those changes and we're committing these different pieces of code, we want to be able to have controls in place that allow us to make it a very smooth and seamless journey for our end users. We're going to touch a little bit on that as we move into our demo portion.

One of the reasons that users choose LaunchDarkly is because we try to support all the code that you're writing your application in. We support over 20 client-side and server-side SDKs. If you're ever curious about what is available, make sure you check out launchdarkly.com.

So what is a feature flag, you may be asking yourself? Well, I'm actually not familiar with this, or maybe I heard about it a while ago, or maybe you have a very set notion of what you think a feature flag might be and you're curious to see if that definition has changed at all. If you've read our blog on what is a feature flag, you know the way that we view it is the following: a feature flag is a software development process used to enable or disable functionality remotely without deploying code. New features can be deployed without making them visible to users. Feature flags help decouple deployment from release, letting you manage the full life cycle of a feature.

What that means is that we're trying to allow you to push out changes and control who can see them, when they can see them, and whether or not they remain there. We can do this without actually running a new commit to our GitHub repo. We don't have to package everything up in a new Docker image and deploy out to Kubernetes. We flip a feature flag, we see the changes in action, and we can make our decisions about whether or not to keep it based on that.

If we want to look at an example of what this looks like, on the left side here we have our SDK initialization. In this case, this is for the React client. What we're doing is saying we want to initialize this SDK, pull in the flag values to be able to see what it is going to return back to us, and we need to log in to our LaunchDarkly platform. On the right side, we see that we have our feature flags highlighted here. We have our header, new header, and our logo versions. Essentially what we're doing is assessing the value of those flags that we've pulled in from LaunchDarkly, and we're going to present different code to our user depending on these. For these ones, these are primarily Boolean functions, which is the most traditional use case for a feature flag. I'm either going to show this code or I'm going to show that code. What we're going to show here is that you can really go beyond just that Boolean feature flag, and you can use LaunchDarkly for a lot of other use cases and pass in different dynamic values.

Let's talk a little bit about the front-end side of the house versus the back-end side of the house, not going head to head, but we just want to look at maybe how some of the developers who are watching this feel about feature flags and maybe some of the trepidation that some of the back-end operators might have about feature flags.

From our development standpoint, traditionally they may look at it and say, hey, we can test in production. Operators may have cringed a little bit at me saying that. They may have said, we do not test in production. We make sure that everything is operating perfectly before we push any changes to the production environment. From the front-end side, we may look and say, hey, we can pass in dynamic values. We talked about this Boolean aspect previously, but one of the advantages of feature flags, especially with LaunchDarkly, is the capacity to pass in dynamic strings, so I can make changes based on the value of that flag. From a back-end operator perspective, they may look at it and say, well, we don't use dynamic values. These are static API paths. This is a static database. We're not going to actually make a lot of those changes. From the developer side, they may say we can control access to which users, and from the back-end side they may say, well, we actually really have all the same users, so you don't need to make any change there.

But really the way that we should be looking at the world is: if our front-end developers say, hey, we can test in prod, the back-end operators using feature flags should be able to say, hey, we can too. This is great. We're going to have restrictions in place because prod is still a very important environment, but we have the ability to actually try things out without having to hopefully tear things down in case something goes wrong.

For the dynamic value standpoint, there are dynamic values on the back end, especially as you start to move into more Kubernetes-based environments. There are going to be opportunities where you can replace static API paths with dynamic string values, so I can say, hey, actually I want to reach out to this service depending on the flag.

From the controlling access to users standpoint, back-end operators also have that power. Not only do they have that, they can also control what information or data is available for the front-end developers to present to their customers. The front-end developers can present what code their end users actually see; the back-end operators can control what systems they have access to using feature flags.

Let's talk about these back-end use cases, and we'll walk through each one of them in a little bit more detail. From a back-end perspective, I look at it as there are four main core use cases that you'd probably use here. The first one is user targeting. With user targeting I can control who has access to what API paths, or maybe access to which databases. I can use those flags to define segments or different attributes of a user and say you can see these different values depending on what you present to me.

The next one is this idea of prerequisites. One of the biggest challenges that I see on the back-end side is that I may not want to enable a back-end change until I'm sure the front end is able to support it. One of the things that I could do is say, until I've had my front-end flag turned on and presenting the value that I want it to, I'm not going to allow for this back-end flag to be enabled. We'll show that here in a second.

The other piece is that dynamic values piece that I mentioned earlier: the idea that I have the ability to pass in string values as well as things like JSON objects. I don't have to just do Booleans. It's not just this or that. I have the capability to use my flag to say I want to use this for my database field, or I want to use this for my database beyond. Again, it could be a string, that could be a JSON object. There are a lot of different things we could do there.

The last one is that I can take advantage of experimentation. If I'm using feature flags, I can measure the impacts of what happens when I make a change, and if there's a problem I can immediately identify that problem with our data and remove it without having to shut the entire system down again. I can flip the flag off. I can use the experimentation data to say, hey, this was not a good call, or I can allow the release to move forward.

When you think about the user targeting piece, on the right side here we have an example of what this looks like in LaunchDarkly. I have this individual targeting. This is just a Boolean flag. We're saying true or false, and I have a few different capabilities that I can do. I could set this to where an individual user sees true or an individual user sees false, but it goes beyond that. At LaunchDarkly, one of the things we try to do is allow you to use different attributes about who your end users are so you can present those values. We can add things like segments. We can have something like a development team that is multiple users, so when I log in, they're within my dev team segment, and then that way they all get presented the same changes. I could use the device type or I could use the browser. It's not just based on name. I can have all these different things available to me that I'm passing into the LaunchDarkly SDK.

Now on the front-end side, this is all well and good. That's one of the advantages we talked about using feature flags. But what does it mean on the back end? From the back-end side, one of the advantages is that we can now control access. Not everybody needs to have access to the same API path. Not everyone needs to have access to the same database route. We can change which users have access to those different systems depending on the context that they're passing in to us.

The next piece is prerequisites. This is the idea that if I have a flag set up to say that I want to serve a different value, if that prerequisite value is not matched, I should not serve that next flag. An example of where that could be really important is if I'm making a back-end change that the front end needs to be prepared for. I may need to make sure the front-end flag is serving a certain variation before the back-end flag is allowed to turn on.

The other thing is dynamic values. Most people think of feature flags as Boolean: true or false. But LaunchDarkly flags can also pass in string values or JSON objects. From a back-end perspective, that means I can put things like API paths, database fields, service endpoints, or configuration objects behind a flag and change behavior without redeploying the service.

The last one we touched on was experimentation. Feature flags allow me to measure what happens when I change behavior. If I release a change and it starts causing bad results, I can flip the flag off. If the data looks good, I can continue moving forward.

You may be thinking, especially if you're a back-end operator, that we could do a lot of this with DNS rules or a service mesh. Why wouldn't I just use my DNS rules or something like a service mesh to control how my services are able to interact with one another? Some of the reasons you might want to consider feature flags instead are that feature flags can actually be a little bit more dynamic. When I make a change to a feature flag, usually you see those changes instantaneously. I don't want to rebuild the image and actually redeploy it, like my Kubernetes environment for instance.

The other part is if I'm using something like Kubernetes, chances are I have a lot of different replicas. I have a lot of different instances because that's the whole idea: I'm trying to scale up or scale down based on the demand that I have. If I'm going to roll out a change, I have to roll out a change across each one of those replicas. Feature flags allow me to do that consistently across all the replicas without having to cycle through everything.

The other piece is I have even more granular targeting rules with feature flags. A lot of times with things like a service mesh, I can do it based on the service name, but I can't actually do it based on something like the device. I'd have to do some funky logic to import information about the type of device or the type of header that they're presenting and then make those targeting rules. Ultimately, it's a little bit easier if I can just import it from something like the React application because I can detect it automatically.

We've talked a little bit about what the advantages are, and we touched on some of those use cases. Let's hop into a quick demo so we can show this in action.

All right, so we're ready to go over our demo now. Let's set a little bit of the background as far as what we're actually going to be covering. What you're looking at is my basic front-end application. It's just a React application that all it's doing is it's a to-do list. You type in a value and it returns into a database. Right now it's connected to a Postgres database, but what we're going to do is use feature flags to migrate it over to a different back end, which will be our Mongo database.

Before we do that, just to roll up my sleeves and make sure you know that I don't have any tricks going on, let's run a kubectl get pods. You'll see we have this Postgres application that's running. I've exec'd into this pod already, so I'm actively in it. As you can see, it's the same pod name. We're connected to the Postgres database, so we can actually just run a SQL query to see what information is currently existing in our database. If we run our command select from our todos table, you see we have Postgres task one, task two, task three.

We flip back over to our application here. We can remove these once we finish them off, so let's clear out a couple of these so we just have Postgres left. Run the same query, and you'll notice that now I only have that Postgres. We're communicating with our Postgres database; all is good. But now we're ready to move. We are going to start using MongoDB Atlas. We want to implement this change, but rather than creating a whole new API and deploying everything out that way and setting up a rule maybe in our networking components, we're going to just use a feature flag to be able to switch things over.

Here in LaunchDarkly, we have a couple different flags here. We have one for testing some login functionality as well as the enable access to our new database. Let's go ahead and flip that on. Save our changes. We flip back over, go to our database; if we refresh here, that's weird, it doesn't seem to be working.

Remember we talked about earlier that we can use something called prerequisites. One of the things we want to make sure is that our application is set up in such a way that we can gather information before we expose the entire database. Let's look at that flag a little bit more closely. In this enable access to database flag, what we have is this prerequisite in place where we're saying we need to have that login functionality serving this dev function, this dev mode as opposed to our other value, which is just public, before we're going to allow you to serve this targeting rule. This is good because right now if we were to change this on, it'd be open to everybody. We don't have any other targeting rules in place and we don't necessarily want that. Let's go ahead and add a targeting rule where we can say that Peter is going to have access.

Peter's going to have access to the new database that we're going to try. Now we're going to go back over to our feature flags. Oh, you've got to make sure that we save it first. Go back over to our feature flag page. We'll flip this on. You notice that this is now serving that dev mode. We're going to log in as Peter, refresh our screen, and you'll notice that we have this MongoDB attribute. Just to show this, this is our MongoDB attribute. We have this running in here. Let's go ahead and add a couple tasks just to show that we are actually live. Add task two. Go back over here and refresh our data. Now you see we have MongoDB and task one and task two.

Let's look at the application code to see how we handled this, both on the client side as well as the application side. We're on our application screen now, and what we're looking at is just a basic React component. This is treating all the information of the to-do that I get from the database that I have, and then it's rendering them on the page.

A couple things that we can show here: we're using this client-side SDK and this use flags. I know we're mostly still talking about server-side flags, so you might be wondering, why are we talking about the client side? Remember, one of the things that we set up in our targeting rule is we said we actually want to be able to make sure that the dev mode is enabled before we're going to allow it. One of the things that I have here is a few different options. We actually have this fetch set up so that in case something goes really wrong, I can display a 404 page. Maybe we try out a new connection and the API completely breaks. I don't want to serve a broken image to folks. I want to say, yes, it's not here. You're not able to find what you're looking for.

The other piece that we want to do is we have this login piece. This is that login functionality flag that we had on LaunchDarkly. What we're telling it to do is say that if the login value is equal to public or dev, then we should still serve this. What's nice about this is that, think about if I was doing this from a beta testing standpoint, I could set this up where I could have my public that is always going to display the same page rendering, but I could also have a beta user version. I don't have to change anything on the front side. It's all going to render the same code. I'm just going to enable the beta user capabilities.

Now let's look at the service. We're running an Express API. This is just a Node.js file that is connected to both my MongoDB Atlas instance as well as a Postgres database. This one is just using a Boolean flag, but I don't always have to. I could have used a different string value. I could have used a different API path. There are a number of different things I could do, but just for simplicity's sake we just used a Boolean flag here. What we're saying is that when we have this API post, when we create a new post, what we want to do is assess the value of this API flag. The API flag is what we enabled. If it's true, then it should do one thing. If it's false, then it should do the other. In this case what we've done is said it's true, and so we should run our logic for MongoDB. Because we have this enabled now, we can set this path. This is the command that it should execute when this API gets called.

On the flip side, we have our false value here, which is just our standard SQL query. The nice thing about doing it this way is that I could go back in here, once I've decided to fully migrate over to my new database, remove this old code, this else block here, remove the if logic around this, remove the flag, and now everything is set up and my customers who are accessing this are none the wiser.

Let's say that we are back here on our feature flags. We feel good about our Mongo database, and we're ready to open it up to everybody. What we can do is just remove this individual targeting rule. We can review and save. We're going to change our default rule. One of the things that's great about LaunchDarkly is we have this capability of a default rule: what it's going to serve when it's just on. Usually, if you're using a targeting rule, you want to make sure that it's set to the other value. You don't want to have it set to the new value. In this case, we wouldn't want it to be returning true because we only want true to be rendering for our dev users. But now that we're going to open it up for everyone, we can change this, review, and save.

Go back over to our migration demo. Good news: everything is still working. Even if I log in, let's say, as Alex. Alex has got to log in. We're going to refresh the screen here. Cleared out all of our tasks, and as you can see, we have no query results in here. We can also go back in. We can re-add: say hello, DOES conference. Another task we had was do a demo. If we go back to our Mongo screen, we're now seeing all these query fields available.

The other nice thing is, and we didn't touch on it here, but one of the cool things that we could do is, let's say that we were going to test this with our public, but we don't want to flip everything over because maybe we're concerned about traffic going in, maybe we have concerns about how many people are going to actually access this database. One of the things that I could do is a percentage rollout where I want to make sure that only a handful of people are actually going to get this. Maybe I just want to test a little bit of the traffic on here, so I do like a 10/90 split and go ahead and save this.

What will happen is that when I go open this up in a new tab, this should open up most likely with our Postgres, but we might get that one-in-10 chance. Let's find out here in a second. Create a new private window. As you can see, we're rendering on our Postgres database, so this is working as planned. If I flip the rollout and say, okay, now we're going to do 90 percent of the true and save this, set up a new window, right now we're back on our MongoDB.

Thank you so much for watching this. Thank you for watching our talk earlier. If you have any questions, stop by our virtual booth. Thank you for watching, and enjoy the rest of the conference.