 Five, four, three, two, one, go. So, welcome to our talk. Catching at the edge, CDNs for everyone. So far, the first and most important question. Did you have a great DrupalCon today so far? The other thing that I would like to know, because from the level here, this was said as an advanced DevOps talk. Who of you has used a CDN so far? That's great. Who of you would say they are advanced level? Okay, some here in the front. Intermediate, cool. Any beginners? You'll learn something too. Are there any users of OSCache? Is iModule, perhaps there's Drupal6 there? Okay. Who of you uses static HTML like that, 80%? No one, okay. It's a DrupalCon, that's good. So, at least we're here all and now let's start. We'll today show you what nice and things you can do with different CDNs and how Drupal8 will totally revolutionize what you can do, be prepared. So Fabian didn't introduce himself, he's Fabian Frans from Tag1. I'm Wim, Wim Leers, I work at Acria. And let's get started. So for me, personally, it is actually more than just about CDNs and making a particular website fast. I personally would like to see that the entire web is able to be fast because what we see today and the last few years is that silos are increasingly awesome, like Facebook is very fast, Google is very fast, but many others, many big companies, small sites, local community websites, they're slow or they can easily go down or they're only slow on mobile connections. But why? Is that really necessary? Can we not fix that? Can we not try to fix that? So this is what we try to set out to do. And first of all, a very quick reminder, but since all of you are using CDNs already, I think this is completely pointless, but let's do it very quickly anyway. The Edge, that's what it was in the title. The Edge is service close to the end user, not the origin, which is where your triple site is hosted because for many sites it is true that the end users are very far from where your origin, where your triple installation, where the data center, where your triple installation lives is running. So the latency between talking to triple and the end user is rather large. The Edge is about providing servers to bring that distance down and bring the content close to the end user. So that's the whole point. That's what we gain by using a CDN. And there's two main ways of using a CDN, using it for assets only, so static things, such as CSS files, JavaScript files, images. And I would like to ask how many of you have used CDNs already solely for this? Okay, so like 30% probably. You are definitely going to learn something new then because the other way of using a CDN is to use it for your HTML as well. So your actual content, a dynamic content that is served by a triple. The problem with using it for HTML is that it's much more tricky because you have to deal with invalidation. The contents on the CDN needs to be invalidated so that it is kept in sync with what triple actually contains. The other problem is authenticated users. Very often when a CDN is even used by a site to make the anonymous experience much faster, nothing happens at all for the authenticated user experience. So we will show something for that as well. So the answer to why use a CDN at all because it's close to the end user and we can massively reduce the latency. So this talk is solely about caching the HTML. So well, the entire website really. It's not about just caching it for assets, using it for assets because that is a solved problem. It is simple. This is the real challenge. And this is what can make a sizable change in making many, many websites much faster. And he must know he's also the CDN module for Drupal. Yeah. So yeah, I maintain the CDN module for Drupal which is just for assets but this is completely not about that. And that is simple. This is much more complex and that's what we're trying to solve. So in Drupal 7, the situation was a bit like this. For invalidation, we had two big problems, invalidation and authenticated users. The simple way of going about invalidation, this is a way that most sites do it or very many sites do it, is by using Mac Sage. You specify how long a piece of content can be cached and the CDN respects it just like any other proxy. But the problem is that you then still have still content. And for many use cases that is actually acceptable but is it ideal? I would say not. I would say that it's much better if you make a change on your website, you change a piece of content, you create a new piece of content. It appears immediately for all users, also anonymous users, that are getting a fast experience thanks to it being cached on a CDN. But that was not possible with this simple solution. So there is also an advanced solution. You can purge the affected URLs meaning that when you make or modify a piece of content, you have to know all of the URLs that that piece of content does appear on. But that is very brittle because it is so very easy to miss one URL and forget to invalidate to purge that one URL. So this is also no ideal. And this is kind of the best way, the best solution that we have in Drupal 8, is a screenshot of the Acria purge module. And it automatically figures out which URLs to invalidate and it shows a UI that shows a progress. But let's be honest, it's not ideal that we're showing a bit of UI to show the progress of how the CDN is being updated, how things are being purged. Ideally, this would be completely transparent. And even this sometimes misses some URLs where it doesn't know that the content appears in that place as well. So this is the best Drupal 7 can do, but it's not ideal. So in practice, what we see in Drupal 7 is we have a combination of both. We use MagSage because sometimes it is acceptable. We use purging of specific URLs. But then because that still doesn't always result in a perfect solution, we very often have to do the very annoying and pesky thing of allowing content editors to purge things manually, which is utterly awful. How many of us have used manual purging for content editors? Yeah, a whole lot. That's not great. That's a very bad authoring experience. And so on top of that, what we had is some site-specific hacks, maybe some heuristics to automatically figure out that in some cases, oh, that's special page. It always needs to be instantaneously updated. Let's always purge that. Maybe something like that. So very clearly, this is not ideal. And it's also impossible for less advanced users than the ones in this audience probably to even set up. So for authenticated use, then the second problem, we had also two possible solutions. You could use a separate domain for logging in and doing authenticated user stuff, like creating content and modifying contents, or you could use a CDN as a pass-through. So the CDN would just talk to the origin, not make any changes, not make, not do any caching, and just relay it to the end user. But that is also not ideal because it means nothing is cached. It's just providing some level of benefit, but it's very limited and it's not what we would like to see happen. So in Drupal 8, we set out to solve these problems because we were, the hacks are not nice. We want to solve it by having less hacks and having a better architecture. And so the two things that are key in validation and authenticated users have also very clear solutions. For invalidation, we have cached tags. And for authenticated users, we have cached contexts. And cached tags are data dependencies. They declare, they declaratively state what's a piece of content depends upon. So that when that thing it depends upon is modified, we know which responses are affected because cached tags bubble from the actual content up to the response level. So for a given response, we know all of the cached tags, all of the things it depends on, and therefore we can invalidate by it. Cached contexts are different, but kind of similar in that they also capture dependencies, but it's not dependencies on a particular bit of data. It is dependencies on a aspect of the requests on a request context. So for example, maybe you are logged in as an admin user, maybe you're a content editor, maybe you're a user with elevated commenting permissions or something like that. It is important to vary by those different levels of permissions because they are supposed to get different responses because you have different capabilities, different permissions. And so that's what cached contexts set out to solve. And so cached tags allow you to invalidate a certain tag and when Drupal does that, we can relay that to the CDN so that the CDN also invalidates it. Cached contexts, on the other hand, allow us to know what's to vary by. It may be it is permissions, maybe it is a query argument in the URL, maybe it is the current interface language, it's lots of things, and we need to know the things it varies by. And if it varies too much, because sometimes if something is specific to the current session or the current user, then it's not really worth caching, right? Because we would end up creating a million variations of the exact same response and nobody is actually going to benefit from that. So in that case, what Drupal-8 is capable of doing is automatically extracting that part of the page that is too dynamic, not cached, but put a placeholder in instead, then the entire page is cachable again. Doesn't need to vary by user but can be cached across users. And that allows us to then replace the placeholder at a later stage, and Fabian will be demoing that later. So cached tags and contexts are the two key things that allow us to do very interesting things. And they are exposed on every Drupal response as the extraable cached tags and contexts headers. So let's dive into a demo right away. I'm going to be demoing CDNs plus anonymous traffic, and that uses just cached tags because Drupal assumes, and it's true for probably the vast majority of all websites, that all anonymous users get essentially the same responses. So there is no variation, so there is no need for cached contexts. There's only a need for cached tags so that we know when content has changed. Fabian is going to be demoing authenticated user traffic. So this demo is built using Drupal-8-beta-15, so the previous one, the one that cut out some time ago. The Cloudflare module, which is sadly not yet on Drupal.org, it's currently on GitHub. It will be moved to Drupal.org as soon as the current project owner responds. The Cloudflare SDK, do we able to talk to Cloudflare? And the Cloudflare account. So let's dive into it. So I'm installing, this is really from scratch just to show you how fast it can go. So first off, we install Drupal. I don't think I need to explain much here. If you haven't seen the Drupal-8 installer yet, here you go. Just creating a site, filling out some defaults, and here we go. We have Drupal-8 installed. The next step is to use Composer to pull in the libraries that Drupal-8 uses, using Composer so that we can also require, which is what I'm doing here, the Cloudflare SDK. So this is basically using Composer with Drupal-8 and so all our libraries we have now using Composer. And currently that still requires us to update the other loader with this very minor change so that it uses Composer's libraries instead of Drupal's. That's all of the basic stuff. Next we install the Cloudflare module, which is also nothing new. If you haven't seen the Drupal-8 module installation UI yet, here you go. Configuring it, there's two tabs there, API credentials and zone settings, but we don't care about the second thing, only the API credentials matter. So we go get the API key, copy that over, and enter the email address for the account and hit save and we're done on the Drupal site. This is all you have to do. The next thing we have to do is on the Cloudflare site, go and create a page rule. And the page rule tells Cloudflare how to deal with incoming requests and how to cache them. So in this case I'm using the domain cache tags on demo.wimliers.com. It's important that you add a slash asterisk there because otherwise it will only cache your front page. We wanted to cache the entire site. We wanted to cache everything, so including dynamic content, so HTML. We wanted to respect our existing headers, the headers that Drupal emits. And we wanted to make sure that users can actually log in, which is pretty important. So we go into our Drupal installation and figure out the name of the cookie that this Drupal site uses because every Drupal-8 site, our previous version, uses a unique session cookie name. And so we just have to tell Cloudflare, this is the name for the session cookie that my site uses. And I disable all of the other special sauce, which dynamically and magically enhances performance or responsiveness and so on. I prefer to disable them so that they can't possibly interfere. So here we go, that's all. And the four things that mattered most are the ones at the very beginning. So that's custom caching, make sure to cache everything and make sure that the headers are respected that we send and that's it. And so next we wanna make sure that the configuration is actually working because that's quite important. We have to verify our understanding of how it is working. And right now it shouldn't actually be doing anything yet because we haven't enabled it yet. So let's check and we don't see any Cloudflare-specific headers in there right now. So that's good. We go back to Cloudflare to the DNS panel, our configuration page and enable it. So make the clouds turn orange. That's it. Now it's enabled. And now we can verify that it is doing something. So we still see that the cache control header is bad but the server is saying Cloudflare nginx. But this means currently that it cannot be cached. So we wanna configure a max-h so that Cloudflare, just like any proxy, is told that it is allowed to cache it at all. So in Drupal we wanna go and configure the performance settings page, the max-h for caching in the browser or in a proxy. So right now we can cache up to five minutes. And next we wanna verify that this is working. So we hit save and immediately we see that there is a cache miss and indeed that it's showing up. And so if we had a cache miss, another request should make it into a cache hits and it is. So right now we're already up and running. But let's verify that really everything is working. So let's quickly log in. And yes, Lamas are awesome. And so you could see that I was able to have the log out and log in links and the common form is personalized. So I'm actually logged in. So logging out again for the next part. So we now wanna verify that it actually works well. Now it's working to some extent already but that's not really impressive yet. So let's go and edit some contents and change the llama for an even nicer one. Rainbow llamas are the best. Yeah, and I forgot to enter alternative text. Alternative text is important people. And so now when we actually hit save, it's talking to the CDN and making sure that the cache tag on the CDN is also purged. And if we go to the node page, then we see, indeed we have our rainbow doing something llama. And now we wanna verify that it works very well. So right now we see that we have instantaneous invalidation already. But let's check that it's actually doing what a CDN is supposed to do, which is provide faster responses all around the world. So I went to Turbobytes pulse, which allows me to perform a DNS query or an HTTP query from many locations around the world, 88 currently. So I'm hitting my demo site from this service from 88 different locations around the world. And it's a regular get request to the front page. So right now the response time on average around the world is half a second, which is not bad, but not amazing. And let's take a quick look at the headers in Australia. I was in Belgium, so I definitely was not there. But because of a period previous tests, I already had filled the cache previously, but it had expired. So you saw the expired header. But now when hitting it again, it should show a cache hit. And it should in theory be faster because it's a CDN and it's supposed to cache things. And there we go. It's twice as fast now on average around the world. And it's a cache hit. And now let's do the very important test, which is we're going to modify our view and make sure that it emits something that we can easily detect in that tool, which is we're going to modify the status codes to the most awesome status code there is, which is for 18, I'm a teapot. And hit save. And again, because I'm saving something, the cache tag is being invalidated both on the site of Drupal and on the CDN. Let's run the test again. And let's see whether it's updated everywhere. So we're waiting for the results from all those locations. And there we go. We see that in the middle column, everything is, or most of the things are turning red. So everything or almost everything has been invalidated already. There is a cache miss as expected. And 86% was updated within about a second. So very fast invalidation all around the world thanks to cache tags of just the things that you need to be invalidated and nothing more. So there is no more need thanks to cache tags for having to purge every individual URL. You don't have to figure out the individual URLs anymore. It just works. It's transparent simply because of a tool, a bit of metadata that we didn't have before. And I cannot go out of full screen mode. That's awesome. So this you can do today. It is simple as was hopefully clear in this demo video. I didn't do anything complex. I clicked a few things together. I entered an API key, I entered a few bits of information. It's cached worldwide. And you can do this today with Acura Cloud Edge or Cloudflare Enterprise. But that's today. This is not something that is limited to any specific service, any specific CDN. So in the near future, we should expect this to become trivial as hosting providers step up and make this more integrated, make this even simpler. It should be affordable for all. Definitely for all in the sense that you can replicate the same system in Varnish. So if you have a Varnish instance because you're a smaller website and many sheep hosting providers are stepping up and providing Varnish, then all of this can happen within Varnish. You don't have the global network then, but it's still going to be much faster. You're not hitting Drupal every single time. And that is something that is affordable for all, but for many CDNs are also becoming more and more affordable. So many sites will be able to use a worldwide CDN and make their sites fast around the world, which is something that some years ago was unthinkable. And now you don't have to know, you don't need a whole lot of technical knowledge anymore nor a whole lot of infrastructure to figure out which URLs to invalidate, which URLs to purge, because that was a painful bit. Also for people who are deeply technical, it was just purely painful and that is a solved problem now. So invalidation is now a solved problem and it benefits everyone, small and big sites. And now it's time for something even cooler that Fabian is going to show you. Yeah, so this was unanimous traffic mostly, as Wim said, that's also possible to do this fastly with another CDN, but that's even also working with the Amazon cloud. So there's lots of possibilities and really cash tags are making it possible to do many things. With Wim, a little underestimated was like, he worked two years on Drupal 8 to ensure that everything, every object, everything that's rendered is having these cash tags. So if you're speaking with developers you're working with, tell them if you're developing for Drupal 8, make sure to ensure that everything that is in any way rendered is having the right invalidation information. That is very, very key. On the other hand, if you forget, you will get bugs because caching is so much ingrained in the system that now you'll find the bugs kinda at day zero of development and not when the site has gone live, has performance problems and then you're like, now we need to enable caching here and then it doesn't work. So that's great. So the motivation for authenticated user caching is the following. We have the very common scenario that Wim just showed. We have only anonymous users. We have a varnish or a CDN and it's fast. That looks like this. And we have a web server. Oh, we have a CDN. We have people from all around the world. They are going to the varnish and we have two happy web servers, even better. So everything is great. The company is flourishing, making good sales. Everything is perfect and they lived happily ever. Oh, wait. Because one fateful day, a shopping cart was onto the site. And then it looked like this. So the site is slow. The web server is really, really unhappy and runs away screaming in terror. And the web server ran away screaming in terror and was never to be found again. Hopefully that didn't happen to you. So you don't believe me that that's realistic? Let's test that. I'm gonna show you. So we have triple eight authenticated users. We're using CDN, fast as CDN, but it's only pushing data through to my server because it's not catchable by default. There's no specialties like that. And we'll see how that looks. Again, I'm using here this turbo bytes, which will allow to see that. And here I've put in the host name of that. And here we can see the server and you can see county it's really bored. Shopping cart was just added. And now we are running the test. And yeah, there's going some traffic coming in. And there's coming a lot of traffic in. And now we have like lots and lots of Apache processors. The Lord would go way up. And but what's the most important thing is we have a response time of on average 3.7 seconds. And there's time to first buy times of like five seconds, four seconds, four seconds, five seconds. That's overall not great user experience in that. And we can do an even better test. We can use the AB tool for testing the performance. And again, we had to doing 100 concurrent requests, so 100 different users coming at the same time, 300 of those. And you can again see that the server is really starting to sweat under that with Lord average of 1.12. And fortunately I have enough rhyme and that works. But you can see that's an even worse user experience. Some are getting like maximum of nine seconds. But what you can also see is that the minimum time is 186 milliseconds. So the site should be fast. It's fast, but it's served by Drupal. And that's a problem here in that. That's not the problem of Drupal, but that's just that the infrastructure I've provided here is I could put in five servers, 10 servers or whatever, then I could probably easily hold the Lord. So it's a scalable problem in that. But in this case, we have the shopping cart, and we have a bad user experience because we were relying on our CDN. So the site is fast, around 180 milliseconds, but the user experience is poor. So I don't want that. I really don't want that. So let's ask a question like Dries today in the keynote. We need to talk. Why does that happen? So in general, pages can be split up in two different sections. And the one section is static parts that are seldomly changing or that are maybe changing, but that are mainly variating by the page they are on. Like, if you're reading an article, that would obviously be the article. And then there's this very, very highly dynamic things like dynamic blocks, personalized content, dynamic command forms where the user name is even in, hey, user, have a great experience, please command. And that is what's slowing the whole page down. Obviously, you could now go to JavaScript frameworks, React, whatever the newest password is, and do that in JavaScript, but then you again has a big investment to do that. So, and also pages are way too dynamic. So if you think you have 100,000 pages, no problem, fits and varnish, but then you have 100 users and then you have 10 million combinations. And that means that users have a cache hit is very, very improbable in that. So, so many combinations, bad cache hit ratios, that's not what we want. So, we make the pages less dynamic and the problem is solved. Wait a minute, not really. The web 3.0 is all about the personalized experience. It's all about content directly tailored to the user's needs. It's about authenticated users. It's about product placement. It's about related articles. That's very important, but that is that dynamic content that is slow, that is providing value to the site. And also, I need dynamic pages. I use a CMS or as I'm just going back to the 80% of using plain HTML. And please don't forget about my shopping cart. So, fortunately, Drupal 8 has a solution for that. And it's already in core. This is in core, placeholders and auto placeholder ring. That means no more of this, no more dynamic blocks that are making things bad and static content because Drupal 8 knows your page. When Drupal 8 is rendering a page, it knows for everything that it's rendering that how it can be cached. So, the main content can be cached by user permissions and the URL because it varies on those two things. There's a normal block that just varies on the user permissions so we can directly include that with the rest of the content. It doesn't matter if that's redundantly on many URLs. It doesn't matter. But there's this one shopping cart and that's user cached. It's just for the user. And because Drupal 8 knows your page, it can do something cool. It can just placeholder it. And that's happening automatically out of the box. No configuration needed. You are getting placeholder ring and the rest is cached transparently. So, whenever something declares itself at the moment as max H0 of what is in Drupal 8 had or uncacheable, it's cacheable only by user, then we don't even need to render it because whenever we retrieve it from the cache, we see, oh, we see that's not cacheable. We directly put a placeholder in there. And we've given great tools to the developers that are using that system to be able to specify things. So, performance tuning could be in a way as simple as, oh, let's configure that and this needs this dependency and then Drupal 8 can figure out the rest. So, it's both automatic and tunable. And that means we can now use ESI. And then we can use the ESI 8.x 1.x. That's a fork that's not yet released. Hoping it will come out around the time that 8.1 comes out or maybe it will even be an 8.9. We are still discussing that. There's edge side includes ESI replace placeholders at the edge. So, it's using oscache ESI modules. Now that it just means we have some very special tags. In this case, it's using hashes. And then wherever that placeholder is, it's doing that. So, it says doing the same thing as Drupal did. Drupal created a placeholder. Standard from a standard perspective of what Drupal at the moment does is, it's just replacing those placeholders transparently. So, you never see that except that the pages get a little faster thanks to dynamic page cache. But if we transfer this placeholder ring from Drupal out to the edge, then we can totally cache all those things at the edge as well. And we can use ESI with the CDN2. So, the demo two is authenticated traffic, Drupal 8 beta 5, 15, Fastly module, Fastly account provided by them over there. Fastly is from the community perspective, mostly well-known for powering fdpdrupal.org. So, whenever you download a file that's currently going via Fastly. And Fastly very, very much gave us help in optimizing the VCL, getting all this code written and there will be easy for you. Fastly is very simple to set up. You just fill out those three things, configure your site, the site name, server address, like an IP address, the domain name you wanna use, then you need to set up some DNS as Wim has showed and that it's working with Drupal 8 by standard out of the box. In that you don't even need any custom VCL. But if we want to have authenticated user caching then you need to upload a custom VCL. And that's currently something where you need to raise the support to gain that capability. But they've provided us with that functionality so we were just uploading our Fastly VCL and then it was working. So, let's see how that's working then. So, this is again my server here over there and Turbobytes again and I've put a little catchable one there which is saying to my ESI strategy to actually work and before that just so that it was easier to demo and now we're running the tests. And as we can see, we need a moment to wait for the test results but on the server side, nothing is happening. It's all kind of in the CDN. We have like response time of 248 milliseconds and we have responses that are as low as like eight milliseconds time to first byte. So, there's a huge opportunity in using also indicate user caching at the edge to really not only being able to just use one server instead of many, many, many but also to really put the latency down we are using there. And the other one is again, AB in that. So, also we have a before, after thing and oh, already finished. So, we have 0.443 seconds before it was like something like 14 seconds and we have a time per request of 1.46 476 milliseconds time per request and a total min of 45 time to first byte. So, that's totally great in that. And for that, how that does work is we now have a happy web server again. So, we have the authentication cache per session. So, it's kind of the standard practice we're doing it. We are asking Drupal for all the cache contacts that have anything to do with the user or the session. And because Drupal has not only cache contacts but also a cache context hierarchy we are able to reduce everything to just the user or the URL. There was a very important architectural decision made in Drupal 8 and because we have that we can now cache the cache contacts which sounds a little funny but it means that whenever we are coming into Varnish we are kind of doing a little round trip to the server but because that round trip is cached it takes less than one millisecond. And then we have all the information available within Varnish. We have the UID, we have the permissions hash, we have the roles and now let's say you are building this one of those personalized sites and you have a block that is different based on the user's interests but you have a lot of users like 100,000 millions of them and user interests can overlap so you want them to get the same content. And then it's very simple. You just declare a new cache context user interests. It will automatically get exposed to Varnish. Varnish will be aware of it and when that block is rendered all it says is very ex-Drupal user interests and that's it. Then it works out of the box. So we have the static content, the dynamic content and we have the authentication cache per session and obviously our heavy web server. So yeah, and with that we have a standardized solution for complex problem. It's within reach for 99% still working out the last little details but this could really make it possible to kind of run almost all sites especially those are syndicated. Directly on CDN, no configuration needed. And hopefully some hosting guys will step up using these standard VCL. I always like to see one VCL to rule them all and yeah, with that we have another problem solved. So I would like to call out one thing that Fabian didn't explicitly mention. So the dynamic bits like for example, a block that shows user interests or whatnot those are rendered via ESI. ESI of course uses requests. So it's just reusing Varnish and Fastly which is Varnish as a service essentially. It is reusing its capability to cache a response with metadata in Varnish and that's all it is. So basically Varnish is just assembling several responses. One is the actual response and then the various parts that are personalized that are dynamic, those are separate responses that we can retrieve automatically within the cache of Varnish and that's why it's able to answer within 1.4 milliseconds. So I think we have demonstrated how Drupal 8 can be super fast even for authenticated users and as a previous slide said, as far as I know, this is not matched by any other system. And so Drupal 8 is really the first one that can be properly cached at the edge and it doesn't have the painted other CMSs or other non-CMSs, other web frameworks bring including Drupal 7 which was totally not able to do this. So in order to get to what you just saw what we just demonstrated, it just requires some level of thinking while developing custom modules and contributed modules because we mentioned cache tags and cache contacts several times but they have to come from somewhere, right? So we need developers when they're generating outputs to actually provide that metadata because otherwise we can't know. So the thought process that I would like to teach you in the sense that please remember this and if you remember this, it's just a few steps and it actually makes a whole lot of sense. It is not something that is very Drupal specific, it is just about thinking about dependencies. Dependencies are super important because dependencies are what determine what the end result, what their response is. It depends on a whole lot of things but very often we have not been so honest about the actual dependencies. Very often we pretend, oh we give some input and this is the output, well that makes sense but actually very often we've been relying on global states and there are a few very good examples and Drupal 7 really didn't track any dependencies especially a good example is Drupal at CSS and Drupal at JS. You're able to use these functions to add a CSS file or a JavaScript file to the current page but that's already where it goes wrong is adding it to the current page but what is the current page? It is just being called from somewhere so how can it associate it with the current page? So what it did was it used global state. It just was all the function calls that happened when building a page, those ended up somewhere and then we mapped that to a bunch of HTML statements to import CSS and load some JavaScript and in Drupal 8 we solved that by only allowing to use pound attached and attaching asset libraries so that we know what markup needs which assets. We have a clear connection, we have the dependencies and that's what's super important. Another very clear example of Drupal 7 not tracking any dependencies is the URL function. I'm sure that almost all of you have used that at some points and actually that depends on a whole lot of things including the configuration for what the front page should be, whether the current site is or should be using HTTPS, whether clean URLs are being used, whether the current site is in a multi site and so many more things. So really there were a lot of hidden dependencies that were just actually being implicitly applied and so really actually this was impossible to catch. Well, it's possible to catch it, we can't prevent that so it wasn't possible to invalidate but we still did it anyway because what we did in Drupal 7 very often was clear all the caches. How many times have we cleared all the caches? There's so many places we clear all the caches, it's terrible and in Drupal 8 that's no longer necessary. So in Drupal 8 what we have is these three concepts, these three bits of metadata that are super important, cache tags which are about data dependencies so declaring what data you depend on, cache contexts which are about the request context. So for example, a specific query argument, the current user role or all its roles, the current user permissions, the negotiated interface or content language, those kinds of things and max age which is the time dependencies in the sense that how long can this possibly be used for some things that are very time sensitive. This is one you will probably use the least but it's still very essential for some use cases. So these three bits are the things that matter, stacks, context, and max age and these are bubbled while rendering to the top level of the response so that the response knows what things apply to it, its dependencies, it knows how long it can be cached, it knows when it should be invalidated and it knows what to verify. So in practice all we need is for everybody to make this thought process a habit. First realizing that you are rendering something, when you are rendering something, so creating a renderer array in Drupal, that means you must think of cacheability. Remember that you have to think of cacheability in the first place and then when you are rendering something, you may want to wonder, is this something very expensive? Would this be worthwhile to cache on its own? If yes, use cache keys and that's something that also exists in Drupal 7, this is nothing new. So cache keys specify the, end up specifying the ID that should be used, it's just a unique identifier. So it looked somewhat like this. The next question is, does it vary? Does it vary by permissions, per URL, per interface language, per something else? Maybe something custom like user interests, because you can specify your own cache context to match your site's needs, which is very important for more complex websites. And so if the answer is yes, it varies by something, then we need to specify cache context to capture those dependencies as well. For example, indicate that this renderer varies by user permissions and by URL. And this is very similar to the HTTP very header, very similar in meaning and semantics. And so the next one is, is there something that can cause the thing I'm rendering, the renderer that I'm building to become outdated? Is there some change that should also cause a change in the thing I'm rendering? If yes, the answer is use cache tags. So for example, you can specify that your renderer depends on node five, user three, and exotomy term 23. That's just a bunch of quantities, but you can specify dependencies on a lot of things. And then finally, does this become outdated automatically after some period of time? If the answer is yes, then use cache max age. By default, we assume that it's permanently cacheable because most things are permanently cacheable and tag invalidation will make sure that you can cache something forever, but as soon as it is changed, the cache tag invalidation will make sure that it's invalidated anyway because that's the whole point of cache tags. It should change immediately. And that's very close obviously to the HTTP cache control headers max age property. Now it may seem very painful to have to deal with all of those cacheability metadata bits manually. So to help address that of course, we have an interface that is implemented by very many things that provides that cacheability metadata that says for a given object, this is the metadata that I vary by that this is the dependencies for this object. So for example, it's implemented by all configuration by all entities, every access result has it. Block plugins, context plugins, condition plugins, some of those you may not even ring a bell because they're relatively deep into the Drupal architecture. But the point is everything that you use while rendering something while building something in Drupal already provides the necessary cacheability metadata. So you only have to use it. And this makes it very easy. And that was really the key part of the talk. We've demoed it and we've explained how it's possible and how you can make sure that this keeps working. But an ESI caching on the edge in CDN, anonymous caching is really not the only thing that this cacheability metadata enables. It also enables other interesting things like hybrid alternative render strategies such as big pipe. And we have a session about that tomorrow. So if you find that interesting and if the demo I'm about to show you for that is interesting, then I would say come by because Fabian is going to do a fabulous demo there too. This is a very short version of big pipe. So what you're looking at is a awesome music website, as you can tell. And so I've got some content on the right-hand side and on the left-hand side, I've got a few blocks. And the first block is personalized. It's slow, it takes three seconds and it's personalized per user. This one is also slow and it is not cacheable at all. It's super dynamic, it's live data. And this thing at the bottom is also personalized, but it's not quite as slow. So the two next to each other called caches and voila, that's the difference. The two blocks each take three seconds, but big pipe is still able to send the majority of the page immediately. As you saw, we finished at the same time actually. The final block showed up at the same time, but big pipe shows interesting, relevant, important things much, much faster. Even with warm caches, the difference is enormous. So on the left-hand side was had basically, so Drupal 8 as it currently is or Drupal 7 rendering. It's the same thing, everything is built and everything is flushed in one go. And big pipe is able to flush the non-super dynamic things immediately resulting in so much faster perceived performance because you see something useful, you can actually start doing what you wanted to right away instead of having to wait for the server to generate every single bit, which is a very big difference. Finally, a quick peek at the future. Service workers, how many of you have heard of service workers? Okay, like 5% maybe, 10%. Service workers are still in development, so it links to a spec there. The slice will be up soon after this talk. And what it really is is simply a client-side reverse proxy. You could think of it as varnish on the client side and you could think of it as a VCL in JavaScript because the logic for this reverse proxy is defined in JavaScript. And that means, because it's on the client side, that we can have zero latency. So instead of even having to go to a CDN, you can just cache it locally, right on the browser, right on the client that is trying to visit your site or your app. And it will be insanely fast because there is no latency. Of course, there is still considerable problems then because we have to make sure that that cache keeps in sync as well. So that is then a different problem to solve, keeping those in sync, but having those new possibilities and capabilities is going to be very interesting. And Drupal already has the metadata, as shown by the fact that it can integrate with CDNs automatically, transparently without having to go through a whole lot of pain. That metadata we will be able to use to make sure that those client-side caches stay in sync as well. Currently, browser support looks like this, so it's definitely not close around the corner, but it is getting there. It is being adopted. So hopefully some time from now we will start, we will be able to start using that as well. And this feels kind of strange to say, but I feel it's worth calling out this time because Acvia has allowed me to work on this and everything leading up towards it because as Fabian mentioned, it was a whole lot of work to make every single entity and config and so on specify the necessary cacheability metadata. And Fabian was also given grants in order to be able to work on the ESI stuff that was demoed and big pipe. And so Acvia has made it possible for us to work on those things and it benefits all of us, which is what I think matters most. It's not just big clients, it's everybody in the community. And so that was it. Do you have any questions? The docs are at the bottom. Those are the ones that are most relevant and should be very interesting. Thank you. Thank you for a good presentation. Very interesting. And I have only worked with Drupal 7 for so far, but I made a small module for caching stuff in varnish, small parts, blocks, mini panels, whatever, using Ajax calls. So I can track them across page view, different pages. So for instance, I have a right column that is more or less the same. I just get the same Ajax call on every page. Can you foresee something where this can sort of? Yes, so because we have placeholder strategies now, all you would need to do is you would use an alter hook. You would specify create placeholder true. You would register your custom placeholder strategy for Ajax and it work out of the box. I don't mean I want to keep using Ajax, but... Yes, yes, it would work with Ajax out of the box. Yeah, but I don't really want to use Ajax. I would rather use ESI, for instance. Okay. But I don't want the same, well, yeah. It's completely interchangeable. As long as you have a placeholder, you can use ESI, Ajax, client-side rendering, Node.js, React, even whatever. And those placeholder strategies are already in core. So you would do that for Drupal 7. Okay, for Drupal 7, for Drupal 7, it will still take a while, but we are porting the render caching from Drupal 8. Well, I'm porting the render cache from Drupal 8 back to Drupal 7 using the service container module, which will allow to kind of run most of the same code in Drupal 7 as well. With the exception of cache tags, we need to specify and cache context. You will need some more manual work, but it might be easier than what you need to do with your module now. I think it'll just drop great to Drupal 8. Okay, perfect. Perfect, yes. Oh, you answered my second question. So any timeline on the Drupal 7 render cache work? When Drupal 8's work is done. Just then, because again, porting does not make sense before, probably when big pipe is in, and probably when Drupal 8 is out, that's when work on render cache where we start, so. Okay, my other question was, I kind of missed in the first example. In Drupal 7, you would queue up a whole list of URLs and send out the purge request. What exactly were you sending to the CDN with the cache tag metadata? To the CDN, we were just sending every quest to purge a special key. So in this case, I think when you add a comment, we would invalidate the note and the comment itself. And in this case, we would then just send out something that would invalidate this special, yeah. In a sense, just what we showed the node five and user three. Yeah, so basically you send purge towards the URL with as you say purge URL as in the CDN URL. You talk to the CDN, you just say purge and then node colon five or purge user colon three. You just specify the exact same cache tags and the CDN invalidates that across all of its responses that whose X Drupal cache tags header contains exactly that and that's it. So it just does string matching essentially on all of the responses. So do you need a custom VCL for that or? Nope. Well, for Fastly, they actually provide that out of the box. You just, the Fastly module automatically maps the X Drupal cache tags header to surrogate key, which is what they call it, but it's just a name. It's the same exact principle. But in pure varnish, yes, you need a few lines, like two, three lines of VCL to make it react through those purge or ban requests and that's it. Okay, thanks. Hi, we have a website where the front page has content pulled in from other systems and these other blocks are user dependent content. So for you could imagine, for example, a web shop basket is pulled in from another website. So the content of this block, this HTML, is user dependent. So that comes into Drupal as a piece of HTML. So we have a REST interface on Drupal calling another website and we pass across a user. How would we, because I'd love to kind of then cache that, so I don't have to go back through my REST API every time we call. You would just take the HTML you were getting back. You would put it in a render array and you would add attached cache context users and that's it. So REST Drupal would do automatically. It would make a placeholder. It would be kind of outside of the main page thing and then you would need like this ESI strategy and boom, it would be ESI. Okay, great. The question is about the size of HTTP headers. So because you had a huge amount of information now, is there a way to reduce the size of it or do we just have to take it? So there's two things about that. I don't think the HTTP header matters too much between web server and Varnish in that case or web server and CDN in that. It might matter a lot more for the end user. In there, what probably should be in the standard, new standard VCL, both those for new only anonymous users and those for authenticated users is to just strip those headers out. We actually have an issue to make sure that it no longer emits those headers by default unless you have a reverse proxy setup. So that would actually completely solve that but as Fabian indicated, the header size is only relevant towards the end user because then sending many, many hundreds of bytes in the very first part of the response that is going to slow down the perceived performance on the client because it takes, for example, an edge connection or 3G, it may take a while and that would slow it down but between the server and the CDN, it doesn't matter anyway but we were working on making that better. Does Acquia Cloud Varnish currently or will it soon support cache tag invalidation? We're working on that. I don't know the exact time when it will be available but yeah, it's definitely coming. Yeah, and we are also working on the, I will be working with an Acquia Cloud engineer on the cache context thing so that that's potentially for some customers, first experimental should also be available and then hopefully later be standard. Could you tell us more about the place-holding policy? Sure. What more? Development side? On the conditions of placing a place-holder. Okay, so the auto place-holder currently works in the following way. There's two possibilities. Either something declares its dependencies automatically but then whenever it started to be rendering, then we detect, oh, this is rendered by user for example and in this case, we create, we replace it with a place-holder and we put the actual data that we wanted to render in the attached array. So the same as libraries, HTTP hats, things, et cetera, the place-holders are actually gonna end up in the attached array. So they are additional metadata that's available and transferred and retained from different stages. The other point is the place-holders when you already have rendered it, then we detect after rendering, oh, this was per user and again, we are putting a place-holder but we are saving whatever we have computed so far and then we later have that available for rendering. What is key to that is that the place-holders allow us to cache every page in a kind of like internal page cache called dynamic page cache where everything except the place-holders with the raw place-holder data that can be recreated is stored in this internal page cache and that allows what we have showed tomorrow more to kind of have response times to the first byte of like 20 milliseconds. And so this is auto place-holding. We can continue to make auto place-holding better. I think we have two-thirds or around 50% in-of-the-auto place-holding things. Currently, what is not yet possible is to say this block varied once by users who we wanna always vary it by user but so that it would never be but on the other hand, we have great alter hooks where you can just say, I'm a site builder. I know what I do. I want to optimize this site and you can always declare all dependencies upfront. So as a site builder, developer, performance engineer, you can tune your site very simple to ensure that the auto place-holding is better. And if you want, you can always specify hash create place-holder fold to not create a place-holder or hash create place-holder true to create a place-holder and force creating a place-holder. So it's automatic out-of-the-box, tunable and turn-offable. Great, thanks. And we'll probably deal with place-holders a little more tomorrow too. So another one about our place-holder, let's imagine we have a big render array and a little part of that is a shopping cart and most part of it can be cached for everyone anonymous and now we go through this render array and say, okay, this part should be in a place-holder and then the next request just wants to shopping cart because the rest is already in the cache but the shopping cart was only built as part of this huge render array and at this point we don't know that there's maybe a function or something that took just get the shopping cart. We've solved that. Because we have enforced an API called lazy-builder and lazy-builder means that a block or an entity must not have any external dependencies. If you have that, you just need to say, this is not place-holderable, this is not lazy-builderable. You can kind of opt out of that but your shopping cart needs to be independently buildable and if you don't do that, your site will break. Let's duplicate. It's as simple as that. That sounds a little harsh but these kind of restrictions of ensuring that everything has dependencies, everything is cacheable, everything is independently buildable that needs to be independently buildable is what makes all of this possible. But is this visible in the render array? Is there in the render array some key that says how to make this block? Yes, lazy-builder equals that but all blocks are automatically lazy-buildered. That's transparently in core. Okay, so I see this in the render array, in some sub-array. Yes, you would see that. Yes, he would see that. How to make this thing standalone? It is standalone by default. It is already in Drupal 8 core that every block is lazy-buildered. Yeah, sorry. Did you mean a blocker? I think you meant somewhere deeper. It's not so far as I understood this correctly that most of it just starts with a Drupal render or the Drupal 8 equivalent of Drupal render. Mm-hmm. And so it goes through the render array recursively and then it says this should be a placeholder. Okay, there's two things to that. First of all, there's a possibility to also auto-placeholder things that are cacheable and not auto-placeholderable that I have working in a proof of concept but we've not yet gotten that into core. The other thing is when you want to do something like that, like we had a great example today, you have a solar page and on that solar page you never want to cache those solar things. So all you need to do is you return from your controller, you return instead of the regular content, the render array, you just return hashLazyBuilder equals callback plus some functions. Gonna talk about that more tomorrow. And then you specify like the search arguments and that's it. And then when the page is built, it will detect, oh, this is not cacheable. So it will put a placeholder at that point in the page so it's not only blocks, it can work everywhere on the page as long as you're using a lazy builder. That's a moment of saying, but as a developer you can easily switch that over. So at this point you don't really build the complete error with all the sub-arrays like for the shopping cart and for the search but you just leave this as an empty in there. Placeholder. It's just saying how to get this stuff but it doesn't build the error yet. Exactly, yes. That's a trick. Yeah, that's exactly what placeholders are. All right. Any more questions? It's linked from the slides that will be up shortly but it's 1415 in this room tomorrow. So hope to see you all there and have a great evening.