 Hey EmberConf, it is good to be here. So, let's see what we got going on here. The art of Ember app deployment. My name is Luke Milia, for those of you who I don't know, I live in Manhattan with my wife and two daughters. I write a lot of Ruby and JavaScript, some Objective C, and when I'm not doing dad stuff or coding, I love to play beach volleyball. I'm the organizer of EmberJSMYC. You might have seen some footage earlier in the day. Please come and join our community. We'd love to have speakers from out of town, so don't hesitate to reach out and schedule something. I run a fun kind of hybrid business where we have a product as well as do you Ember Consulting? If we can be helpful in any of those sides, let me know. Let's jump into it. So, how we deliver software has evolved over time. I would say this is kind of a fair way to say that it started, and it evolved. Cassette tapes, this is really where I got started playing games on Balditari. Spent a lot of time with these guys, and then if you looked in your gift bag today when you checked in, you probably had one of these guys in there, actually looked a lot like those. And then finally came our beloved internet, and with that came the browser which has become the most ubiquitous app run time in the world. And it didn't start off kind of that way, but once it got going, it became pretty amazing. And so delivering software for most of us became how do we deliver via the web? And in the beginning, we just static HTML sent from a fairly low powered server to the browser. Eventually that became dynamic HTML sent from some more powerful servers to the browser. And then came the rise of the server side app frameworks. Again, delivering representations, HTML representations of that app state with each request to the browser. And finally we came to today with Ember Comp where we're delivering an HTML and JavaScript payload and then interacting with an API but really having the entire run time in the browser. And we may take what I just said for granted, but of course, William Gibson said it best that the future's already here but it's not evenly distributed. For as many of us as are here in this room, there are many more people out in the industry who have yet to arrive at this kind of browser app paradigm. And for many of us here in the room, we are still holding onto some of our deployment techniques from these server app days even though we've moved to this new paradigm. And that's what I wanna talk about today. Because after all, we no longer use CD-ROM duplicators to deploy software. This is kind of a funny picture and the reason I included it even though it's a little blurry is that in my very first software company which kind of started around the dawn of the web, this was getting one of these was a game changer for us. I mean, it changed our lives. But we also no longer deploy FTP files individually. Anybody recognize this program up here? That's awesome. Somebody at least as old as I am. So what is the web server, the server web app deployment approach? Simplified it's copying all the files to servers, restart the server processes. Pretty simple, for bonus points, you can do that copy files step more elegantly. Get push, if you're Twitter, BitTorrent, Docker containers, if you're hip. And you're probably gonna wanna do a rolling restart to avoid downtime. So the question is, is the server app deployment approach right for Ember apps? And you can probably guess by the fact that I'm up here talking to you that my answer to that is no. And so let's look at why. Let's start with the real basic flow here. So browser makes an initial request for your Ember app, request index.html from your server. Your server comes back with an HTML response. And that response contains within it a script tag that points to a fingerprinted JavaScript file. So in this case, app-abc123.js. So the browser parses that page a short time later, makes the request for that JavaScript, comes back to the server, server says, yep, got it, here you go. Ember app boots, all's well. But during deployments, this doesn't necessarily go so smoothly. Because there's a moment in time during a rolling deployment where that request for your HTML comes into the server, gets back a reference to app-abc123. The request is made, and right at that moment before the request is made, your deployment infrastructure has flipped over traffic to the new server. And so the new server comes up and in that new deployment, you now have a new fingerprinted JavaScript package, app-def456. And when it gets the request for app-123, you get 404 not found, user gets a hiccup or your QA team, they refresh the page and they're like, oh, everything's fine, we'll just ignore that. But obviously not a great experience. And so the lesson in here is to keep static assets working during a rolling restart, if you're using this traditional approach, somehow you gotta keep both the old and the new versions of these assets around for at least a few minutes during the deployment. One way to do this, which many of us probably do, is deploy these assets to a CDN and just don't remove the old ones for a while or maybe never, considering storage costs these days. So another aspect to think about is how users interact with our apps in this browser app paradigm. Because today it's not uncommon for a user to be on your site for five, 10, 15 minutes in this one kind of page load, if you will. And so what happens during this when you're doing a deployment? Well, the app boots, gets its HTML and JavaScript, user starts doing their thing, requests some JSON from the server, and then around that point in time, you decide, hey, I've got some nifty new feature I'm going to deploy, you deploy some new JavaScript and an API change to go with it. And of course this user who's on this yellow timeline up here doesn't have the new JavaScript, right, because they didn't refresh the page. And so when they next try to make a request to that API, assuming that you have some sort of breaking change there, they're going to get some sort of error. And so the lesson here is that whether we think about it this way or not, we have multiple versions of our Ember app in use at once. You have the new version that new users are getting and you have the previous version that users who have been on the site for a few minutes are using. And so we somehow need our API to remain backwards compatible for at least the length of a user session. And so what I'm going to submit to you based on what we just looked at is that the idea of versioning your Ember app and your server API app together as a single version number with a single release process is a lie. And we can embrace this fact, choose honesty and give our Ember app a separate repository, a separate versioning scheme and a separate release process. And we can learn some lessons here from the way we think about the native app ecosystem here. It's kind of taken for granted that you're going to have multiple versions of a native app out in the wild talking to your API. And what you need to do is to keep your API working for those older clients. For some period of time, you're probably going to decide to end of life them at some point, but you certainly don't want to do that kind of each release that you go from the app to the app store. And you would never consider, for example, trying to time the release of your API change with when your app gets approved by Apple or gets through the Android submission process. That would be pretty silly. So we can learn from these native apps and see that this requirement buys a certain amount of freedom and a bunch of decoupling. So for example, you might have multiple apps in the app store talking to a single API. You might have beta builds that are out being tested running against your production API. And we can learn and embrace these things. We can and should do the same approach for our Ember apps, assuming that we are versioning and deploying these things independently. But there is a big workflow difference between native apps and Ember apps. And that's how apps are launched and how they're updated. And the key difference here is that instead of an app store in the OS being responsible for updating and launching, what's responsible here is HTML. HTML you can think of as the bootstrapping engine for your Ember app. And this probably seems pretty obvious, but when you follow through the implications to what does it mean for your deployment, turns out there's some pretty serious implications. So what do we need to think about for these HTML pages? HTML pages that are bootstrapping our apps need to point to fingerprinted JavaScript and CSS, but they can't be fingerprinted themselves. They need to be at a stable URL. They have a certain amount of order significance, so you wouldn't want to load your, say your app bundle before your vendor bundle. And if you're using a strategy bundle and strategy like that. And they're also a really good place to provide kind of environment-specific configuration to your Ember app that you don't necessarily want to bake into your JavaScript. In addition, if you can serve up this HTML on the same domain as your API, you get to sidestep all of the course complexity that comes along with having separate domains for those. Finally, caching should be minimal to none so that when you do want to deploy a new version, you're delivering it to new users ASAP. So the conclusion here is that HTML should be managed and deployed as part of your static asset build. So that's really part of your Ember app repo and build process, but it somehow should be deployed to your API server, your app server. And ideally, importantly, updates should not require redeploying the server code and it shouldn't require restarting server processes. And back when we were first building Ember apps, we were deploying our API and our Ember apps together and making a small JavaScript change or even a CSS change meant a five to 10 minute deploy process for what really amounted to static assets, which is kind of insane. So here's the kind of a sketch of the idea. We're deploying our, on the bottom here, we're deploying our JavaScript, CSS, and images, our static assets to a static asset server, serving those out to the browser. And then on the top, we've got our API server deploying, serving up API requests, any kind of non-Ember dynamic pages, as well as the HTML for a JavaScript app. And so the question is, how do we get our HTML from our Ember kind of diverse CI environment onto that API server? So one possibility is we could simply copy it up to the file system. But in a lot of modern deployment environments, this is ephemeral, so that's not really a great approach. We could deploy to S3 and have our API server kind of read that HTML out of S3 and serve it up. And that's viable, but S3 reads can be pretty slow and we certainly want this page to be fast. And like we said, to have a very small amount of caching in the mix so we can deploy quickly. So what's a good kind of low latency, persistent place to put this? So we already had Redis in our environment and that turns out to be a pretty good fit. It's not the only fit, but for us it was a good one. So for example, as an example of how this looks as a full environment, this is YAP implementation with the Rails backend. We've got our HTML being deployed into Redis, our Rails server reading that HTML out of Redis and serving it up. Our static assets go to S3 with CloudFront sitting in front as a CDN. And this process turns out to work really well and not only does it solve the problems that we looked at earlier, but it also opens up a huge world of emerging possibilities. So what are some of those? Well, one of the things that we realized really quickly that was possible here is that we could preview before activating. So when we deploy a new build, so a new batch of HTML pointing to these static assets into our server environment, we don't necessarily have to start serving up that immediately to our users. Instead, we can kind of keep it there and serve it up only given a particular query string. So for example, a release query param, identifying a particular release that we wanna preview. So here a developer can look at their new code running in the production environment talking to their production API server before any user sees it. And so the level of confidence that you have when you actually decide to flip that switch is pretty substantial. You're pretty confident that the world is not gonna blow up at that point. And certainly when we talk about deployment, we like to take those steps with confidence. So we can also do something really interesting which is because we have this HTML passing from Redis through our API server or app server to the browser, we can take advantage of that moment and do a little HTML rewriting if we wanted to. Now, why would we wanna do this? Well, here's an example. This is an example of Rails controller. Obviously works in any kind of backend. On line three, we're grabbing the HTML. And on line four, what we're doing is we're serializing the JSON representation of the current user. And then we're sticking that into a meta tag that comes down with the HTML. And what that means for our app is that as it's booting up, it doesn't need to kind of wait and do an Ajax request for information about the current user before it can make some initial decisions about routing. Do I show a login screen or do I route immediately to the content that the user's looking for? And this is just a nice kind of boost to that initial experience. And there's a bunch of other use cases where doing a tiny bit of rewriting here can be really powerful. Adding CSRF tokens perhaps, including dynamic analytics params for things like Google Analytics, Kismetrics, et cetera. As well as embedding dynamic configuration to control things like feature flags. That might simply be setting a global that you're consulting to determine whether a flag's enabled or disabled. Closely related to this is the ability to easily do AB testing. There's two styles. There's the one using the kind of feature flag style I just described, where you can bucket users into an A or a B, turn a feature on or off, depending. The other one we used when we did a kind of full-fledged redesign of our Ember app, and we said, man, it would be nice to A-B test this before we cut over, because there's some dramatic differences. Well, so what if we deploy into two different Redis buckets, so have two kind of current HTML paradigms. Bucket users into an A-B test using our A-B framework, and then serve one up and one to one group, one to the other. So by the time we actually did fully cut over, we felt really confident that our redesign was indeed an improvement. And finally, I don't love this as a paradigm as a UI, but sometimes it's appropriate. You can use the fact that your server's being notified when a new version of your app is deployed to communicate via WebSockets or whatever your push infrastructure is down to your browser to say, hey, there's a new version available, you should refresh now to take advantage of it. So all this stuff, what I just described to you is some ideas that I've been talking about for about a year now, kind of in public first at RailsConf about 11 months ago. And since then, a bunch of people have stepped up and run with a lot of these ideas and created open source implementations around them. So I wanted to take a look with you at some of those open source implementations today. Now there's a bunch up here, not gonna go into depth into all of them, but the first thing that I did to kind of start to filter these out was to say, look, we want to be developing apps in Ember CLI and it makes a ton of sense to be building our deployment tooling on top of what Ember CLI already has to brings to the table. So let's filter this down to just the Ember CLI based apps. Now out of these, there were three that really embraced this kind of assets, HTML distinction that we talked about earlier and those three were Ember Deploy, Frontend Builds, and Ember CLI Deploy. And so I started doing some research and kind of looking at the implementation of each of these and it turns out that Ember Deploy and Ember CLI Deploy share the same kind of idea of having a core plus plugins architecture. And so for example, if you remember the slide where I talked about deploying to Redis, you may not have Redis in your environment and you certainly wouldn't want to put it in just for this. Maybe you have another low latency store, Mongo or Cassandra or even a Postgres or MySQL will do the job fine for this. So turns out that both Aaron Chambers and Michael Klein who developed these two projects came to that same conclusion like this should be really should be pluggable. And it turns out that Frontend Builds started life off as a fork of Ember Deploy. And Frontend Builds is an ambitious project that has both the client side deployment infrastructure as well as a full kind of Rails Engine implementation on the back end for implementing the server side piece of this. Ember CLI Deploy has the best name in my opinion, right? Kind of makes sense. That's what it is. That's what you would expect it to be named. And so the Ember Deploy has the biggest ecosystem out of these and it has about four well put together plugins to do different types of deployments. Deploying your HTML file to S3 instead of to Redis. The folks, a gentleman from Microsoft contributed an Azure component. And so, because of some good momentum around that. And so what we did just last week is we pulled together a conference call. We were able to pull it together in about 24 hours thanks to Twitter's new group DM functionality. And on that call, we decided to merge these three projects. So instead of three awesome projects, each with one or two maintainers, we now have one awesome project with a team of now six people because in addition to Michael Klein, Sam Selikoff, Ryan Toronto, and Aaron Chambers who were the maintainers of the projects I just described, somehow just as open source luck would have it, Dan Schultz has jumped in and been an enormous help. I don't even know how he found out that we were doing this stuff. So the team is tremendous and we're really excited about moving forward. And we've moved the project from Michael's domain, Michael's GitHub user underneath the Ember CLI umbrella thanks to help from Steph. And so we're really excited about making this a well polished, kind of well oiled machine that's going to be kind of the one stop shop for getting deployment set up for Ember apps. And this experience to me is what paving the cow paths is all about. It's going from an idea to a few different implementations where we're experimenting with concepts as far as how best to approach it to now kind of coalescing under one kind of Ember approach to the problem. So where are we going from here? The roadmap for the next release is 040. It's relatively a small step. It's making sure that the ecosystem that had grown up around Ember deploy gets moved over successfully to the new name and the new infrastructure. And this is pretty straightforward. We want to provide migration instructions for users of the old Ember CLI deploy. We're also deprecating JSON based configuration in favor of a JavaScript file so that you can easily consume environment variables for sensitive credentials and so forth. Timing for this is we're hoping to have this released by the end of this week. The roadmap for, awesome. The roadmap for 050 we're really excited about and we're looking for input on this too so you can visit the repo and look at the deployment pipeline issue and chime in. We're looking to move to what we call kind of a pipeline hooks and plugins architecture. And it's taking the plugin approach that currently was evolving around Ember deploy and moving it to be modeled really after the Ember add-on approach. And these plugins indeed will be Ember add-ons themselves. They'll get to leverage all the Ember CLI infrastructure that already exists there. We're gonna be adding a post deploy hook so that we can easily communicate to Slack or your IRC channel with each deploy. Some nice details, who did the deploy, what time happened, et cetera, et cetera. And we're looking to provide some great documentation for plugin developers so that this ecosystem can flourish and we'll be providing a lot of support to the people who are looking to add plugins here. And finally, Ember CLI front-end builds, which as I mentioned is one of the most ambitious kind of takes on this, is going to become a plugin for Ember CLI deploy. And so that's gonna really help us exercise our API early to make sure that we're arriving at the right ideas. And the basic architecture I kind of alluded to just now, Ember CLI deploy plugins will be Ember CLI add-ons with an additional keyword. They'll be auto-discovered, auto-wired up. You'll obviously need to provide some of your own configuration for to be able to successfully talk to these, the backend services involved in your deployment. The goal is that you'd be able to deploy from either your development environment or from your CI environment. So there'll be both some nice interactive tools to work within the command line as well as kind of silent, headless tools. And the plugin kind of hooks that these plugins can implement are listed here. We'll deploy, build, update assets, update index, activate and did deploy, as well as list, which lets you look at your most recent deployments and choose to activate a particular one, roll back to a particular one. So the basic usage pattern will look like this. You will have configured one or more deployment targets, be able to say Ember deploy staging. That will deploy your assets and your HTML to the configured staging deploy target based on the plugins that you've got in. You'll activate the release and notify your group chat. Made a mistake. You can use Ember deploy rollback staging, rollback to the most recently activated version, also send a notification. Want to consider what you should be releasing. Ember deploy list is going to give you a list of recently deployed things for that target. It's also hopefully for most plugins going to be able to give you a preview URL like I described earlier. So as a developer, you can grab that, take a look and have once kind of sanity check before you decide what version of your Ember app to activate. To actually perform the activation, you'll pass this identifier to Ember deploy activate. And that usage, what everything I just described is not something, some of it exists today in zero, three O and will exist in zero, four O. A lot of it is going to be changing somewhat for zero, five zero. So again, looking for input, those of you who have implemented deploy solutions yourselves and I know everybody in this room who has an app in production has done that. Talk to us about what you would love to see. Beyond zero, five, zero, we would like to support deployment to named buckets to support the kind of A, B tests and beta testing things we've talked about. I'm sure that you've used apps where they allow the end user to kind of toggle between classic and beta, right? So that you can get people starting to experience a new version without necessarily putting them at risk because it doesn't have all the features that your initial, your current version does. We would like to be able to support that scenario pretty cleanly. And then beyond, can tell you also beyond zero, five zero. I've talked to some folks where deploying the HTML is not a great fit for them. It makes more sense for them to have, let their servers continue to kind of render the overall HTML, but instead we want to be able to deploy configuration information. So what are the JavaScript assets? What are the CSS assets? What are the configuration options that I'm taking kind of from my static build and then letting me and the server merge them with the configuration options that my server is driving to be able to produce this page? Cool, somebody likes that one. And let's see, we just talked about this one. Did I miss one? No, that's the same slide, say Levy. So in addition, as I said, your use cases, your ideas come talk to us. To me, this experience over the last year and then in the last week has been really emblematic of what I love about this community. When we got on the conference call last Tuesday, we had five people on the call that most of whom didn't know each other, hadn't had a ton of conversations together because we have a common mindset from what we've learned by watching the Ember project evolve. We have a common set of tools that we've become good at using from Ember CLI to GitHub to Slack to IRC. We basically were able to make some decisions together that this merge was the right move and be productive as a team in literally a matter of minutes. It was a pretty astonishing thing and really kind of this paradigm, which I know a lot of you have experienced in open source already, is unparalleled in the history of humanity. So without getting too high fluting on it, it's pretty awesome stuff. So one last idea that I wanted to just throw out as stuff that we can talk about later. How does this work with Fastboot? And so I don't have all the answers to this. I've thought about it not too long, but one possibility is that in this scenario is that your Fastboot server could sit in front of your API server. It could be reading HTML from that API server, proxying API calls back and caching your JavaScript locally. And so there certainly is a simpler scenario for a Fastboot server, but if you wanna take advantage of all the possibilities that I described earlier, we may wanna consider having a relationship between our Fastboot server and our API server that's a little bit more robust. So anyway, this idea is something that I would really love to talk about at the party or later today with folks, so be thinking about it. And with that, this is attributed to Steve Jobs. I don't know if it's true, but real artist ship, real artist deploy, and thank you to everybody who's kind of helped make this particular journey possible. It's a small story and kind of the overall arc of the Ember story, but it's an exciting one and one that I feel really lucky to be a part of. So keep in touch, join the fun if you're interested in this stuff, and if not, just get ready to take advantage of a nice new convention for the community. Thanks.