Hassan Saab, Software Engineer, sweetgreen

Scaling Salads: How We Launched One of Our Most Impactful Tech Features for Success

sweetgreen is quickly transforming into a food brand enabled by tech. As part of our mission to connect people to real food, we are one of the first food brands to build a delivery channel on our own platform. When initially thinking through the release process, not only did we want to position the native delivery feature for success, but also every subsequent, "big-impact" feature. Ultimately, our delivery team decided to leverage feature flags through LaunchDarkly, in order to support a canary rollout and take advantage of numerous other benefits arising from continuous delivery. As we started to build out the delivery feature, our team had a variety of business and technical requirements, from geographical user segmentation to a flexible development workflow. Through feature flags, we were able to satisfy these requirements and power a beta launch in Los Angeles. Over December 2019, our beta launch allowed us to gather important customer feedback and implement improvements, which paved the way for a successful fleet-wide roll out in January. Today, our delivery channel is an important contributor towards our overall business, allowing us to connect people to real food, wherever they are. Through building the delivery feature, our organization embedded important practices around feature flags and canary releases, which will support sweetgreen for years to come.

Hassan Saab

Hassan Saab

Hassan Saab is a software engineer at sweetgreen, having been with the company for over a year. At sweetgreen, he contributes across the stack and was a key member of the feature team that came together in 2019 to build and scale native delivery. As part of his responsibility, he architected how the delivery team would leverage feature flags to power a canary release, leading to a successful fleet-wide rollout in 2020. Before sweetgreen, Hassan started his career in investment banking and later on, worked on his own startup called Curiocity, a platform that curates experiences designed to bring people together. Outside of work, Hassan is passionate about producing music + DJ'ing and loves playing  "party" games like Quiplash and Mafia with his friends.

(gentle music) - Hello everyone, my name is Hassan Saab and I'm a Software Engineer at Sweetgreen and today I'm gonna walk you through the rollout of one of the largest digital features at Sweetgreen called native delivery. Before I get into the journey of how that happened, let's just give you guys a quick primer on what Sweetgreen is for those of you aren't as familiar. Sweetgreen started about 13 years ago, and it was started by three college friends who were completely uninspired by the food options surrounding campus. So they decided to rent out this 500 square foot tavern and start a restaurant and the premise was to provide locally sourced healthy foods to the community. Since then we've grown from that one store to close to 120 and even through all that growth, the mission has really stayed the same and that's to build healthier communities by connecting people to real food. While the mission has stayed the same, how we've executed upon that mission has evolved, especially with how technology is starting to disrupt the food industry and here's a perfect example. If you guys look over to the left, you'll see a breakdown of our revenue at year end 2019. About 90% of that came from the restaurant, which purely means people ordering ahead and showing up at the restaurant to pick it up or physically showing up at the restaurant to order. Only about 10% came from more digital channels of outposts and delivery and since we're honing in on delivery, I'll give you guys a quick rundown on what that is in a sec. Now by 2023, we're forecasting that about 55% of our revenue comes from the restaurant and 45% comes from outposts and delivery. All right, what does delivery actually mean? Delivery is the integrated experience of being able to order natively from our app, order an item all the way to the item showing up at your doorstep. All right, now that we've set the stage, how did we actually launch this thing and when did we launch it? So we launched native delivery in January, 2020, which was perfect timing with everything that's happened with COVID and we launched using feature flags and a progressive rollout. We were really excited about native delivery because one, it provided that extra channel for us to engage customers on and then two, it allowed us to own the data on preferences, decisions, purchases so we could leverage that data to more intelligently build things in the future for our customers. So once we got started on building the feature, we had to start thinking about how we might launch and our team came up with a strategy where we'd have this MVP and release the MVP in a small market, iterate on it for a few weeks, then roll out in subsequent markets over time. We hadn't really done anything like this at Sweetgreen before, so we knew we needed some sort of technology or integration to help us get there and the more we learned about feature flags, the more we learned about LaunchDarkly, the more we realized that partnering with LaunchDarkly would make a ton of sense with what our goals were for this particular roll-out. Now as an engineer, one of your first reactions when knowing you got to integrate with another API or third-party, is how difficult is this gonna be? Is that documentation gonna be readable? And I'm very happy to report that the documentation was very crisp and clear. Any time that I had a question so the support team would sometimes respond back to me within minutes, which is probably like a world record for email tickets. So shout out to that team for making us get acquainted very quickly and once we did the first goal we had was creating this front-end feature flag service, which would hold live flag values. If you look over to the right, you'll see a basic diagram of how it all was supposed to work and because our front-end is built upon Ember, which is a JavaScript framework we integrated with. LaunchDarkly's JavaScript SDK. So the user would log in, the front-end feature flag service built in the client would then initialize a connection with LaunchDarkly we'd send some information on that user for segmentation purposes, and that'll be important in a bit then we could start requesting and caching flag values and then we could also update these flag values through a listener event if there were any updates in the console or the dashboard. And the goal was to have kind of the freshest or the most live flag value within the service so that we can then inject that service within our app at the page level, and then pass down flags as needed by smaller UI components. Now, I know I just threw a ton of technical jargon at you guys, so what does that actually look like? On the left, you'll see a version of our iOS app with the delivery flag off, and that's purely just a pickup experience where you'd order and then pick up at the store and take that home. Over on the right, you'll see a version of our app with delivery on, and there are a few different UI changes. Up on the right, you'll see the delivery tab which allows you to access the delivery flow and down below is a delivery card where when you click through that, you're able to access that new delivery ordering experience. All right, so we had built this service now we had to optimize it for efficiency and the question we were trying to answer was how can we maximize productivity and enable multiple engineers to develop against multiple different flag values. And the reason we needed a solution to this was because of kind of a hairy problem, where we had this group of engineers that were working towards delivery and they needed the delivery flag to be on to maintain that work, on the left or on the other side, you had all these groups of engineers who are working on other features, not named delivery, and they needed the delivery flag to be off. Now through LaunchDarkly's API, you get served the same static flag value for a certain flag across clients. Now that wouldn't work for us because if you send a true or false statically to these two groups of engineers, it's very likely one group of engineers is not gonna be very happy because they don't have the flag value required for them to be most productive. So we needed to come up with a kind of a dynamic solution that allowed engineers to set flags as they needed for their own track of work. And if you look over to the right, you'll see our solution and this is from the function that ends up grabbing flag values from. LaunchDarkly ultimately that's the LdClient.Variation. Our solution was really just an if statement, very simple if statement where if there are any flag values defined locally, pull those first, use those first and very simple solution, but allowed us to support multiple tracks of work at the same time. On a lighter note, it also helped us avoid hairy, tricky situations like this that's represented by the Spider-man famous fingerpoint meme, where the devs would be pointing at each other or QA would be pointing at each other for turning flags on or off when they needed the opposite value. So this hotline mechanism really provided a feature flag playground, if you will, for devs or engineers to, to set flags as they needed for their own track of work. All right, so now we have that service down, we've optimized it, now we were getting much closer to launch and we had to start thinking about how we might power this progressive rollout and our solution really predicated upon sending a custom attribute. If you look over all the way to the left, you'll see kind of the payload we used to initialize a connection with LaunchDarkly and this corresponds to a specific user. You'll see something called the launch group ID, and that's purely something that's a geographic representation of where that customer is and that'll be important in a sec. Now onto step two, based on each customer, sending that launch group ID, we could then create segments of users that targeted a specific launch group ID, right? So LA launch group might be all the users with a launch group idea of five New York six and so on and so forth. The last step was going to the feature flag homepage and targeting specific values of the feature flag in our case, true or false to specific segments so we could power that rollout by market. And creating this centralized launching process really facilitated these quick snappy launches across markets. All right, so by now we were ready for takeoff. So the big question was, how did the rollout actually go? Overall, it was a success and I made this big, beautiful step function chart to walk you through the journey. We launched in Brentwood with an MVP on November 18th, we iterated on that MVP for a few weeks and then launched in L.A.,. New York, D.C., Maryland, Virginia, Philly, Chicago, Houston, then all restaurants in. January 15th of 2020. Was it a completely perfect launch? No, it's hard for any release to be completely perfect, but it was in those bumps and bruises that we learned a ton and we also had a lot of technical key wins through the process. One being able to build this scalable feature flag service was crucial and allowing other features to leverage the power of feature flags. Two, being able to have that bait a launch group period in Brentwood was crucial and finding these critical mistakes and bugs that we needed to fix and that really ensured that launching and each subsequent market would go smoother and smoother. Lastly, continuous delivery. So we had, as I mentioned earlier, we had delivery, which was this big transformational feature, but we also had all these other UX improvements, bug fixes that we needed to deliver against now we're ready to go live into the wild. So we needed a way to launch all of these features sets at the same time with some of them being often, some of them being on and feature flags really allowed us to do that and maintain momentum and the business and against product priorities. All right, so this was us after launching native delivery, we had clearly gone through a lot, but just like Kobe and Shaq after their first championship, we knew that the work wasn't done and while we have used feature flags for many of our features since native delivery, we've yet to really scratch the surface at the full LaunchDarkly toolkit, especially when it comes to things like experimentation and AB testing, so I'm personally really excited to learn more about that and continue to leverage that full feature set so that we could more intelligently power releases in the future. Cool, thank you so much for listening, thank you to LaunchDarkly for having me and thanks to my team for giving me this cool feature to talk about. (gentle music)

Ready to Get Started?

Start your free trial or talk to an expert.