 Okay, we're gonna start now. Hello and welcome to our talk, Making Drupal Fly the Fast Drupal Evers Near. It's presented by Vim Leers here from Acquia and by me, Fabian Franz. And we'll today show you the master plan of Drupalight performance, or of performance in general that we've been working tirelessly on. And I think, let's start. So, that might be a little provocative question, the fastest ever Drupal. Are you serious? You're kidding, right? But I saw Drupalight was so slow. Everyone told me that. So it must be true. And besides that, I read that blog post by Vim that PageCache is now enabled by default in Drupalight, but that's no big deal. PageCache was already in Drupal 7. That does not count, except it does and we'll show later why. So, just to prove you what I mean and what we've been working on, let's take a look at a short demo to show you that. So, this is our little demo site and we'll have to do some playing around just so that it all fits on screen everywhere. And for your convenience, I put in some meta information at the top of the page. So, this is one of those complex sites that Rhys talked today about. That's very dynamic and yesterday about in his keynote, that's very dynamic and that has a lot of dependencies and content, et cetera. And now it's your task to make that site fast. But we still need to retain it dynamically. And Rhys yesterday said in his keynote when he had this slide with the loading blocks and also the mention of big pipe that it's not in core yet. So, but what he didn't say is that we actually have a patch already in the queue in core and this is kind of the patch that I will present you today that could bring big pipe to core if enough people help review the patch and if you get it in. So, here we have a very dynamic site branding block. It has a username, it has some dynamic information like timestamp and it even has the same pass. So, it's about as complex as you can get and while that is now an artificial example, let me tell you that on many clients site I've seen similar scenarios that are really where that block took three seconds to render and where it was just some different logic. So, this is just a simplified example but you can very, very well reuse that in the real world. So, as I said, we are loading this page and we're waiting, waiting, waiting and it's three seconds. So, this is a problem. So, let's take a look why this page is slow. Let's say by some testing out we found out, well, it really is this site branding block that's making things slow. So, Wim here has written a very, very neat tool of how you can analyze such a site in terms of how we would be able to cache that and so what we can see here is so-called cache contacts which is the variation of the page on what it variates and there we have a problem it variates by user. That means even if you try to cache that page for the next user it would again be slow. And also we see that this cache variates by URL and then we also have this very dynamic timestamp that whenever I'm refreshing that after it comes back is actually here and increasing dynamically showing the time. So, with this tool called RenderVis what we can do is we are setting like we want to find everything that's not cacheable on that page. And now Wim's tool automatically detected that it's this timestamp that makes the whole page uncacheable because we can see that this timestamp is kind of going up to the tight branding block to the region to the site and at the end to the page. So this is why it's not cacheable. This is why we have problems caching that, isn't that cool? But it's just still a prototype as you can see because he's fudging in the web developer tool so if anybody of you is interested in helping out with this, especially with a fancy 3D CSS in which I am no expert at all please come talk to us because this could be really, really cool triple eight. The other thing is we saw this user context so we want to find out what is actually making this site dependent on the user. So what we put in is this RenderVis context user and we see, okay it's again this site branding block in this case the whole block that deviates by user it bubbles up this information so we have a problem and then we have said URL and it automatically directly detected that this is a reason why this thing again is not cacheable and even if that big pipe demo block now could be cached by user because it includes this very dynamic URL it would be different on each page again. So we have problems in a real world scenario that would be a smart cache where we are trying to even for authenticate users cache all the pages. If you have something that deviates by user or variates by user and you have 100,000 pages you have 100 users and you have like 10 million entries in your cache which is obviously not very workable. So the way how we are fixing this is by using placeholders. So now that we've now that Drupal kind of has this information we have this information of a user we have this information of a URL we have this information of a max H zero we do some little trick which I've compromised here into this demo but we are telling Drupal what we want is a single flash rendering strategy which means that it should use placeholder ring but still in the end serve a whole page to the same and we'll see how that works. What's cool about that is that Drupal is able to determine from this information that you are seeing on screen automatically what it needs to placeholder how and this is what we're gonna activate now. So we're putting the render strategy single flash in and we are reloading the page. The first time it still takes 3.1 seconds but something has changed. So if we again take a look at this render this and we take a look at the max H what we now see is the max H is actually still detecting this is a dynamic thing but there's no more red borders around the site branding block there's no more red borders around the sidebar there's just one red border around the whole page because we are still doing it in the same request. So in this case this branding block now becomes cashable. The other thing is the URL thing this has been placeholder as well because URL is something that deviates much so it doesn't go up to anywhere because the page is obviously already by URL so this is nothing that bubbles up in that. And now for the user thing we can see that that whole block is still per user and also then the whole pages per user but the the sidebar region if you want to cash that differently we could because it's no longer bubbling up to that region. Now if you reload that some magic happens because now this page only takes 0.58 seconds instead of three seconds and that is because actually we are now caching this block and I think that yep it can tell that even that this block is now cached and then we still have our two placeholders in here which is that one which doesn't bubble up in the max age one. So this is kind of the magic of this placeholder ring and but still there's still some delay feelable and there's kind of this rule of some of having this below 0.5 seconds and we are above that we can do better and this is where big pipe comes into play. With big pipe we are enabling just another render strategy. We are reloading that page and whoa, what was that? So now this page, let's do it again. So now this page just takes like 0.07 seconds to render to be completely there and if you have a fast server connection it will directly be there and it says conveniently there's this render strategy big pipe and then what you can't see because that's a little too long on the screen, okay. Okay, there may have some tricks. There's the time to stream the rest of the page and this is actually the 0.5 seconds. So let's do it again. We didn't do that because of the responsive thing here but yeah, you can see we're clicking on a home and after the 0.5 seconds it tells you then that it's streamed the rest of the page. So and if you take a look here, I think we need to... Yeah, resize again. Okay, here we go. And if you now click on the home and if you click on the home then what we're actually seeing is this timestamp just coming after the fact. So it kind of has everything already streamed but this dynamic timestamp that works takes so long so it can even help you find performance problems by just place holding something and seeing how long it takes. Actually, that even works in the real world when I was checking how long kind of like for a node if you have this action links like edit, et cetera how long that takes to render or the common render form. Once it was place-holder and big pipe it was kind of immediately visually visible how that works but yeah, we have a page that's really, really fast to be and we are streaming the remainder automatically here so this is big pipe in Drupalite Core. What we also now see is if you take a look at the render this again then we can see we still have that same place-holders here but the maxH0 doesn't even bubble up to the page anymore because now we are rendering it after the page so even the page cache could cache this now because the place-holders are just afterwards replaced so there's no longer even a red border around the whole page and this one is still cached so our page is still per user but that's a problem we don't wanna have this page per user we really wanna have that like that and now what's really cool about surrendering place-holder strategies is place-holders have a name like a unique ID or you can even define a name and in this case I've called this place-holder some special name and if I'm and I see that pretty much what this is doing we could totally do in JavaScript so what I did was I was adding some little cookies here that are available for JavaScript of course if all your pages are cached you need one Ajax request to create those cookies but that's a technique we actually use for some enterprise clients attack one so we have the username tester we even have the user roles here which we need a little later and so in Drupal settings actually there's all information for the current pass or not, oh it's dot pass yeah dot pass dot current pass there we are and then there's also the base pass it works in the code so let's quickly activate the JS and single flash so all that does is kinda take this site branding block which we now is already a place-holder and instead of rendering it on the server we are rendering it completely client-side we refresh that page we still have a very fast page delivery time we have no more streaming time so there's nothing that is streamed now and this place-holder is now completely rendered client-side and with that we have made the page fast but what's really cool about that now is that by now if you take a look at the context there's nothing anymore that deviates this page by the user context so if you take a look here at the cache context there's only user roles which is by now in Drupal 8 core user permissions but that's not so important there's no more things from that site branding block at all so let's take a look at what all deviates by user roles and that's pretty much a lot so what you could now do and that was unfortunately out of scope for because we still wanna get you some more information in how this all works and how you can do it yourself but it would totally be possible to just cache this whole page and vanish now and you would have a fast site in that and that is why I'm saying this can be the fastest Drupal ever because if you give Drupal the information to make things fast, Drupal 8 can make very smart choices about that. Oh and there was actually one little thing I forgot let's quickly switch back to big pipe because there's something else which is called how do we remove that again? He's great at shortcuts so it was a big pipe so we see here this is the timestamp is coming but what about if that whole branding block was not cached for that user yet? You know it's cached by user and new user logs in what happens or if there's this path information in there which is cacheable but not dynamically recreatable in this case so what the system can do is something called progressive enhancement which means if you click now on the test article one you see there's no site branding block yet and then after a while it comes so similar to Facebook where they use big pipe all the time we've now had a streaming time of 3.02 seconds but our page was still really really fast and Facebook if you tried out this single-flash strategy it's a website that takes three seconds to load 3.5 seconds to load and without all the crazy speed tags for PHP or the new hack language they would even take seven to 10 seconds to load so a complex website takes long to load but we can be smart about how to render it how to cache it, how to do those things and the next time I'm going to this article once I have that already cached it's in there and it's immediately fast so yeah progressive enhancement too so what you just saw is part of the mission to make the whole web fast it's a challenge by him, by Wim Lears and I've designed to take it so if you want to read that that's a very great read I originally read it without knowing that it's by him so I just later realized he was also and he was kind of pitching well if you want to make the web fast we need to make Drupal fast, WordPress fast, Joomla fast then all pages will be fast and what you just saw is a huge chance that everyone could profit from so that really the whole web could be faster so that's a really ambitious goal so let's see what fast means it means for one user it's fast it means if there are many many users coming to the site it's fast and overall as a speed of how something like that loads is always the time to first byte which was kind of the first number you saw plus the asset loading the rendering of the page JavaScript execution time and we want to minimize that so how do we achieve that in general? It's very very very simple you use static HTML pages use no CSS, no JavaScript, no images and just text and links Seriously? No! Of course not so there's some truth to that too performance optimization means to do as little work as possible we really want to do as little work as possible when a user visits our websites if you can do that don't do it while the user is visiting your website do it in the background, do it somewhere else but don't do it when the user is visiting your website use as little resources as possible not so many images, not so many scripts not 20,000 megabytes of whatever so the critical path which is when the user visits your website and it needs to be fast for him the process is can we avoid doing the work at all? Can we avoid doing that? Can we improve the algorithm that it's just fast out of the box? Then if that's not possible because we've already tried everything can we avoid doing this work even during the critical path for some Drupal 7 examples that would be for example to create a field that's permanently storing some aggregated information like some counter that increases so yet that you don't need to ask the database for how much to count now is of something so do it in an update hook, store it permanently but often that is also not possible so is it possible to cache it permanently? Is it possible to write smart invalidation which we'll see later to cache it permanently and never have to invalidate it and if that's not possible could we cache it for 10 minutes? Could we cache it for 10 seconds? So you can't imagine how much stress you can put off a web server that's heavily loaded if you just put in a cache for 10 seconds. It's amazing and then no content editor will say well if it's an hour after the content shows up it's a problem but after 10 seconds usually not. Or defer and that was kind of what you've seen with the big pipe executing it after the main content has been rendered. So remember this acronym I've created here avoid cache defer if you remember that that's kind of the process for all performance optimization if you're doing it in that order you're doing it right. But caching which we are now talking about has problems. The content should be as current as possible it should have a high cached ratio and it should have low cached invalidation complexity. That means you don't wanna have much work with that. You want that if the editor publishes an article they directly wanna see it and if that article is in the sidebar on 100,000 pages and the title is wrong and the CEO of the company says this title is wrong we need to change it immediately all those 100,000 pages should be current directly. But on the other hand it doesn't help if you only for example cache for 10 seconds then your cached ratio won't be as good as it could be. So choose two, you can't have all three. As examples for low complex cached invalidation is what I've now already talked about the time-based invalidation. So you can cache the pages unconditionally for a year. The content is not really current but the cached ratio is really, really great. Or you decide to just cache the pages never. Your content is always current, CEO is always happy but cached ratio is 0% and probably performance will suffer a little and yeah and a lot of troopers have insights work of that because either they don't even know there's a page cache, page cache, what's that? That's checkbox? No. Or because they have this problem, well my content was not current, okay let's disable that caching, it just makes problems. Or you're going into a kind of like a compromise, you're cached it for six hours and it's quite current and the cached ratio is still acceptable. But for some case even that might not be enough because then you have that first user problem. Six hours have gone by and the user comes and then it's like. And that's obviously also a big resource problem because when we're talking about costs that also directly shows in server costs because you just need more webpads for when your caches are stale, when your caches are out. So another example for the low complexity and validation is a clear all invalidation. When a page changes, clear the whole page cache. That's what Drupal 7 did. Kind of like. It is an easy way out but it's not really that nice. High complexity cache and validation, for example from Drupal 7 Contrib now is to clear only what has cached, the expire varnish module in D7, the akmi module and other possible modules in that. So you need to, for example, purge expire all that 100,000 URLs you have that have this wrong title. And in akmi that can take from four minutes to 30 minutes, for example. It can put a lot of stress on your varnish server, et cetera. So there must be something better like that. But this is a very high invalidation cost and also very high complexity. If you take a look into what lands, for example, the expire module goes to find whenever a node or a node reference is somewhere embedded in that, et cetera. That's very, very complicated and also prone to error bugs. It works, but there's something better. So Drupal 8 shows high complexity so you can have high cache adversarial with the content being as current as possible. The content is invalidated instantaneously and cache permanently for most cases. And the solution we have invented for that or we have used for that and proven it works for as CMS is cache tags, which Wimbled explain later. But caching even has more problems. The content should be varied by user, a group, a special permission, or our favorite example, the face of the moon. So you have a granularity. You still wanna have a high cached ratio and that was kinda exactly that problem I was talking before. 100,000 pages, 100 users, 10 million cache entries, that's not workable. You should have a low complexity. So you just don't want to have much logic to ensure those caches are granular or varied. And again, Drupal 7 shows a very easy way out in that it provided some granularities for the blocks and then you could set some up. There was block cache all the way, could do it dynamically. You could use some of that in panels or somewhere else so there was some constant, it was all pretty simple. So again, choose two, can have a three. What again? Yes. Okay, and Drupal 8 shows high complexity again. Everything in Drupal 8 declares what it varies by. Whenever you write an if statement somewhere, and it depends on anything that is outside of your current domain, of your current object, of what you are currently dealing with, you have to declare a cache context that is very, very important. Wim will explain the sort process in a little more detail but just in that thing, you have to do a little work to be able to enable Drupal to do what I've shown you in the demo before. This allows for the first time ever to cache authenticate user content securely with access check, without having to worry about that. And it can work out of the box. Many things like OSCache, ESI module, et cetera, that are hard to set up that have error tricks, et cetera, because Drupal 8 is designed that way, can work out of the box in that. And the solution for that is cache context and as you've already seen, there's kind of automatic place-ordering magic. So, wait a moment. Now the critics come. So, what about KISS? Keep it simple, stupid. You're creating this very complex system and yeah, we should be keeping it simple. Counter-question, who of you uses a database? I don't know what the others do, but... So, database actually are beasts of complexity. They're just hiding it from you. They're hiding all the complexity they are dealing with from you. There's some people that sort, well, database are so easy and they've used this Neo SQL things. But then you suddenly have to deal with all that stuff that the database hides from you yourself. And some Neo SQL users in the end did go back to the database because in the end they had all that logic that before was taking care of them for them in their app and it was like such a big app but before would have been just a little query. So, you don't see any of that complexity. You give it hints, like you give it a schema, you give it indexes, you give it information of how it can work best and then it just, it's magic. And more often than not, very, very nicely. And this is the same here for you. Drupal 8 makes it as simple as possible for you. And this is a huge opportunity, a very, very huge opportunity in the first time ever in Drupal in that we are doing all the caching logic internally. It's complex, yes. We have cache redirection. We are not talking about that today. We have place-holding. We have cache context bubbling. We have a render stack. And you don't need to understand any of that because it's all internal to Drupal. And it's all inside the renderer. It's all inside the render cache logic. But if you give Drupal the information, then it can be smarter about its decision and it can empower you to build the fastest Drupal websites ever. So, Drupal 8 formalized those things in a kind of language which is those cache context, cache text, makes it to make your site fast. And, yeah. And as I've promised on my slide, Drupal 7 can do the same. Yes, Drupal 7 can use the same language. I've been working in parallel on a render cache 7x2x module. There's even a proof-of-concept already in directly using Drupal 8 code. Directly the same code base. So in the end, you will have the same implementation. You will be able to use cache tags at a more limited scale, but in ways you can do it. You can use cache context using the service container module. At the moment, it's frozen because I'm concentrating on Drupal 8. That's important because Elsa would just be porting stuff back and forth without having one API finalized. So I'm at the moment concentrating on finalizing these APIs in Drupal 8, making them nice and back porting it to Drupal 7. Oops. So, but how do I give this information? And that's what we're going to show you now. Yeah, that was quite a demo, right? I hadn't seen it myself completely up front, so yeah, very cool. So Fabian has been really instrumental in making the big pipe stuff work at all. I honestly wouldn't have been able to figure out all the details on how to make that work, but as Fabian said, the complexity is hidden from you. So not everybody needs to know all those details just like databases. And so I will take a step back and look at the things everybody will be interacting with. Hopefully all of you will be interacting with in Drupal 8. And the things, the thought process that you apply while working, which is slightly different from Drupal 7, but hopefully you'll agree that it actually makes a whole lot of sense. So I'll get started. What everything is about in Drupal 8 and what is enabling the things that Fabian has demoed is dependencies. Dependencies, dependencies, dependencies everywhere. Because the reason behind that is that without those dependencies, we cannot possibly know which things we can cache when they should be invalidated, when they should be varied by something. But it's not just about cacheability. Another thing that was problematic in Drupal 7 was the fact that, for example, assets, we didn't do assets dependency handling. We just were calling Drupal at CSS and Drupal at JS from various pieces in the Drupal code base in core and contrib in pre-processed theme functions, but also in page callbacks that build render arrays. The problem with that was that we were putting all of those assets that we needed to be loaded somewhere in a global state, but then we couldn't possibly know which pieces of markup that was associated with. For example, if you were adding some CSS that actually was there for theming your node, for styling your node, how could we possibly have known that some Drupal at CSS calls somewhere in the code base was actually targeting that node markup? It was impossible. So in Drupal 8, what we are doing is making sure that you aren't calling these kinds of functions anymore and aren't putting stuff in a global state anymore, which only allowed for things to be cached at a page level, because global state corresponds to a page and doesn't allow us to know which things it actually belonged to. So it was really impossible to cache. And simply using pound attached and attaching libraries, which actually already existed in Drupal 7, but it wasn't enforced by just consistently using that. We, for example, are able to make sure that big pipe does load to the proper assets, because that's pretty important too, right? It's nice that the markup can be sent correctly and fast and isn't validated when necessary, but without the proper attachments, without the proper assets, we would be looking at essentially a site without CSS and JS, which of course isn't nice. So this is something you can actually already do today. So start using pound attached and stop using individual CSS and JS assets. Always use libraries that will slightly easier way to Drupal 8, because it's one thing that you've already grown accustomed to by the time that you start using Drupal 8. So that's one area of dependencies, but it wasn't just limited to this kind of rendering. Really, Drupal 7 wasn't tracking dependencies anywhere or almost not anywhere. So a good example that is actually kind of independent of rendering, but that just very clearly shows Drupal 7's earlier versions because the URL function basically dates back to Drupal 4.6. I looked it up this morning. The things that depends upon is quite scary when you think about it, because all you feed into the URL function is basically a path, right? You give it node one and it gives you back something like example.com slash FR if the current language is French, slash node slash one, or maybe even the URL alias. But just giving those examples already is giving it away slightly because the things that the URL function depends upon is which page is your front page? Which path is your front page? That's something you aren't giving to the URL function, but it somehow is getting from somewhere. Whoa, I'm not sure what I did there, I think. Okay, there we go. The HTTPS configuration, whether your site is enabled to support HTTPS as in should the URLs pointed to the HTTPS version? Yes or no? Clean URLs, are you using the index of PHP query string Q equals the path or are you using clean URLs? Is a current site in a multi-site? The current host name because usually a site can, or quite often sites can be accessed via multiple host names, so for example, Drupal.org or www.drupal.org, which means that if I'm accessing it through one, then all URLs should be using that one and vice versa. Path processing, another one, so that's where, for example, the negotiated interface language is coming from, but you could even configure it so that the URL language was independent of the interface language and whatnot. Different path processors could be added as well, so as you can tell, the list is very, very long in the terms of things that it actually depended upon but that you didn't give it directly that was getting from somewhere, so you weren't actually considering those dependencies. And because of that, things are becoming uncacheable because if we give, if we call the URL function and give it a path and we get back something that dynamically depended on so many things in the current context, how could we possibly have figured that out? There was no way and so Drupal 8 is really about making sure that it's no longer impossible to cache, well, it was actually possible to cache, but it was impossible to invalidate correctly. So the problem in Drupal 7 was that we chose to cache anyway, despite it actually being impossible to invalidate correctly. And so that's what Drupal 8 is all about, correct invalidation. And the language that Fabian was referring to earlier, so the equivalent of SQL indexes, primary keys, constraints, whatever else is in SQL, the equivalent in Drupal in terms of cacheability is on cache tags, cache contacts and cache max age and I'll go over them right now. So cache tags are about data dependencies. Declaring which things, which data in Drupal you depend upon. Cache contacts are about the context that the thing is being rendered in. We'll talk about more about that in a second. And max age is about the time dependencies, basically saying how long is this thing valid, how much time is this actually valid for and maybe it is permanently cacheable, maybe it is only a limited period of time, maybe it is a long period of time, but it's important to declare if at all there is a time dependency. And so these three things are really the only things you need to be worried about. This is what you need to be thinking about every time. But under the hood and Fabian already alluded to this and this is the only bit of implementation detail that I think is important to have a vague notion of and if you want to you can dig into it deeper. But basically these three things, tags, contacts, max age are bubbled, just like for example in JavaScript events bubble. So everything from deeper in the tree, deeper in the DOM tree bubbles up higher to the DOM tree and equivalently in Drupal, deeper into a Drupal page. For example, a field in a node that node is in a view, that view is in a block, that block is in a region, that region is in the page template. That's the tree and we bubble up along that tree so that at the highest level we have a complete understanding of which things, which dependencies we actually are dealing with. That's also why in the demo that Fabian gave, the red outlines, the red borders and the marking as red, those things, we are only able to mark those things as red. We are able to know those things to be the things that I have, those cache tags or contacts or max age because we are bubbling it from the deeper levels of a tree to the higher levels of the tree and that's also why for example, when he was highlighting the URL in the block on the left-hand side or the user, no matter which one, first you saw that that thing was completely marked as red because that was a thing that where the dependency was originating from, but then the things that were containing it did have the red borders. That's the tree bubbling that you are seeing there. So, in practice to make this more, to take it from concept to practice basically, try to make this top process a habit, please. So, whenever you are rendering something, so when you're building a render array, just be actually conscious that you are rendering something because that means you have to think of cacheability. If you aren't, then there is no way that we can make things cacheable automatically, that we can invalidate correctly, then we can vary correctly. So just as soon as you're dealing with render arrays, remember, oh, I'm rendering something that means that maybe there is something dynamic in there and then, of course, I must think of cacheability. Second step, is this something expensive that I'm rendering? Therefore, is it worth caching? If yes, use cache keys and that's exactly the same as in Drupal 7. Remember, if you had a render array or maybe many of you haven't used render caching in Drupal 7, but that existed in Drupal 7. So basically, if you had a render array, you could set pound cache and then within pound cache you set keys and the keys are concatenated to form the cache ID that will be used for caching that specific thing, for identifying the address of that thing so that we can retrieve it later on and don't have to re-render the entire thing again. So whenever you are doing something expensive, like for example, rendering a node, a node consists of fields and those fields maybe contain references to other entities and so we have to do a whole lot of things to figure out what should actually be displayed, take into account access checking as well. That is pretty complex, right? So we do want to make sure that we don't do all of that work on every single page load. But if it's something tiny, like maybe just a single field, do not bother caching because if we're caching every single bit on the page individually, we'll end up with hundreds or maybe even thousands of cache requests, cache retrievals on every page load. That doesn't make sense. So choose the things that are expensive to be cached individually. So pound cache keys and then specify keys. Now comes the actual cache ability metadata. We had cache keys just now, but maybe there are different representations of that same thing. Maybe it is varying on a combination of permissions or maybe even URL or interface language or something else. If the answer is yes, I am varying by something, no matter what it is, then you should use cache contexts. So basically in the example of a node, let's assume that maybe some field in there was only accessible to users with a certain permission. In that case, you would specify pound cache contexts and then user.permissions. And that would then make sure that we don't have one cache item. No, we have one per combination of roles. So if I have permissions A and B and he has permissions B and C, we would be seeing different things. If we both have A and B, then we would be seeing the same thing. So one cache entry or two cache entries would be created. And this is very, very, very, very similar to the HTTP very header. You specify in the HTTP very header, whether it varies by cookie or by accept header or by whatever. This is very analogous. You specify which things in the request context you vary by. The next one is the one that you'll probably be seeing most often. If you're rendering something, quite often you're depending on something else. So basically what causes representation of the thing I'm rendering to become outdated. If there is some such thing, then you should use cache tags. So for example, if you're rendering something that uses maybe the title of node five, then you specify the node five cache tag. If you're also showing the author, or maybe just linking to the author, but not even showing the name of the author, just something of the author that might change because maybe the URL contains the URL alias as in the username, so user slash whim, for example. If I change my nickname, then that's also something that should be invalidated. So tag it with that. If I use a taxonomy term, tag it with that. So the data dependencies must be specified to Drupal. And then finally, if there is a time dependency, so if there is a chance that this thing could become outdated, then you should use max age. The default is caching permanently, which means this never is going to become outdated unless invalidated by a cache tag, meaning that for example, user three had changed, I've changed my username, so then it should be invalidated. But other than that, other than data changes, this thing will or should remain unchanged forever. So then in that case, say, hey, this thing is cacheable forever, permanently cacheable. If it's not, then you can specify a number, an integer, which is just a number of seconds that it's valid just like HTTP, because this is again very similar to the HTTP cache control header, the max age value that you specify there is exactly like this. So given those five things that could seem overwhelming to have to think about all of those things, you don't want to go and specify these cache tags manually like node colon five. It's too easy to make a silly typo and then have it not work as you would expect. But usually you are working with objects. You're usually working with a node object or a user object. You do a node load in Drupal seven, similarly in Drupal eight. And whenever you encounter something like that, if you are building a render array and you're using objects to fill that render array with useful information, the renderer, which is the class that represents what Drupal render does in Drupal seven, it has a method called addCacheableDependency, which basically says, hey, my render array, it depends on this thing, but that thing is actually cacheable. Please adopt and absorb that cacheability metadata into the render array so that my render array is actually varied automatically by those things. So it's as simple as specifying, as calling that method. So for example, if you're using, so in Drupal eight we have config objects and those have cache tags as well. So whenever the configuration changes, for example, if my site's name is changed, because I had a typo in it, then I want that markup, which says welcome to the website, where the website is and the name of the website. I wanna make sure that whenever the configuration changes, that actually the markup is changed as well, as in everywhere that appears, whether it be on one page or a million pages, that only those pages that have it are invalidated. Just calling that method, that makes it so that you don't have to deal with the cache tags manually. So talking about it at a higher level, what Fabian has shown you is something akin to this. Basically, Drupal pages are nested, have lots of things, have lots of data. It's a graph of things basically that you are dealing with. But any of those things may have cache tags, cache contacts, and so on. And the problem was that basically if any one of those things, let's say that the blue note on the right hand side, that it has a access check that is so dynamic, so complex that it cannot possibly be cached. So therefore it says, hey, this note should actually be rendered with maxH0, because the reason for showing it is so dynamic that I cannot possibly invalidate it at a future time. So please don't cache it at all. That used to mean and still means in Drupal 8 heads today, that the entire page is infected by that maxH0. It cannot be possibly be cached because there is something deep down there, even if it's just a silly single character thing, if you will. That means that the entire page cannot possibly be cached. And so detecting that, detecting that maxH0 and deciding, hey, this thing is too dynamic, let's not infect the entire page with that. Let's put a placeholder instead, so that big pipe or single flush plus JavaScript, or maybe even another render strategy because Fabian has shown several, but it's possible for you guys to come up with more. ESI could be another possible example. It then allows us to cache the entire page, but just not that dynamic bit and avoid that infection and then ensure that we have a decent cache head ratio and then that does make the website fast again. So taking a bigger step back again, remember that I started with dependencies, dependencies, dependencies. The problem was that Drupal 7 didn't do that. So if we compare Drupal rendering a page to building a ship, and this could be Drupal 8, a nice clear ship, the structure is clear, assembled from components, the dependencies are clear. So this kind of makes sense, you would probably build a ship this way, right? You wanna think about the dependencies, you don't want it to sink, you don't want people to suddenly die because the engine compartment isn't properly isolated from the rooms or whatever, which Drupal 7 isn't that good at, then this would be kind of like Drupal 7. It is still a boat, it is still a boat and it will probably be able to get you from A to B and it worked this way, but the problem was that we weren't aware of the dependencies. It was seemingly randomly constructed. Every single bit in a Drupal 7 page or almost every single bit was gathered on every single page load for no good reason. It was just because we weren't thinking about dependencies and in Drupal 8 we are and the consequence is that we can make things much faster as Fabian has demonstrated. So that's kind of the message I wanna give dependencies, think about it. And so looking at a few common scenarios, if you are depending on configuration, as I mentioned, don't forget to add its cache tags. Use that handy method, give it the render array that you're working with, give it the object that you're dealing with, a config object and it will take care of it for you. If you're using an entity, even if it's just a tiny, tiny little bit, even if it's just one value of a field or if it's just a title, no matter what, don't forget to add its cache tags using the same method, give it the entity object. And even if you're using just a value of a field, don't think that you need to not specify a cache tag because it was just a value of a field. No, that value of a field was actually part of the entity. The entity object is where it's coming from, so specify dependency on that entity. Just pass the entity object again because that's where you were getting the field from in the first place. If you have uncacheable data, just specify maxH0 or if it maybe is considered by you to be okay, to be outdated only 30 seconds, for example, then you could say, okay, maxH equals 30, 30 seconds is then still allowing for some level of cacheability, but it's up to you. But don't forget to specify that it's at least not permanently cacheable because that will lead to horrible end results. Manually rendering a link. Remember that URL example from earlier, if you're still using, so it Drupal 8 currently in its current state, we are still working on that aspect, trying to figure out the best way forward. But Drupal 8 still allows the same kind of URL rendering where you just call the URL function. And it is completely unaware of the dependencies that are actually incoming, it's just talking to the overall request context and configuration state of Drupal, which makes it so that we cannot possibly bubble that cacheability metadata that is actually associated with that link. We don't know that it's giving you back, for example, slash nl for net and for Dutch slash node slash one because the currently negotiated language is Dutch. There is no way to know. So instead of doing that, please use entwijk, or entwijk you can use a link or URL functions, that works just fine. But when you're rendering a link, you should actually be thinking about using type link. Why? Because when rendering a link, you're actually rendering markup. And the l function in Drupal 7 and in 8 is about actually sidestepping the renderer, Drupal renderer in general, because it is actually markup, but we have never been treating it that way. So let's just start treating it as markup, use pound type link, and then you will be fine. And a few more advanced scenarios. Maybe you're varying by cookie. Maybe you're showing some information that actually is coming directly from a cookie. This is maybe a little bit far-fetched, but let's assume, and this is actually something that quite a few websites do, if you've logged in at some points in e-commerce websites, and the user's session has expired because he hasn't visited for a week, for example, you wanna provide a nicer experience. So you wanna say hi, Wim, or hi, Fabian, but you aren't actually logged in. So you're getting that information from a cookie to create a nicer user experience, but that actually does mean that you are varying by that cookie information, and you wanna make sure that I don't see hi, Fabian, I wanna see hi, Wim. And it's important again to then specify the right cache context. So you can even specify cache contexts on things that aren't Drupal inherent because of things we saw earlier, like user.permissions, that's really Drupal concepts, but cookies, colon, username is basically saying I wanna vary by the cookie with the ID, the username. So all of that is also possible. And then finally an example that Fabian has actually encountered in his performance consulting work, device cookies, basically to ensure that the website is optimized for a certain device. Maybe that's not always the nicest solution, but it is something that you see in the real world. In Drupal 8, what we do is, what we also have, which I didn't mention yet, is a concept of required cache context. So some cache contexts we don't want you to have to worry about because every single render array is going to at least depend on the theme system because it uses templates, therefore it is always depending on the theme system. So we always specify the theme cache context for you so you don't have to worry about that. But another one that is almost always used is the team function, the D function, right? Translating text, translating strings. So we are taking care of the interface language cache context for you as well. But then we just can choose for a certain website. Maybe your website is varying on almost every single page by a certain cookie or by a certain permission or by something. You can specify your own cache context by the way. You can add a country cache context, for example, to make sure that the markup is varied automatically by country. So all we're doing here is specifying another one that is going to be used everywhere so that you don't have to do, have to go through the effort of repeating the same thing all across your site if you have your site-specific knowledge that your site is going to be varied by some advanced thing all over. So that's really all we had. So we hope you liked it. And if you have any questions. I have one little note please. I want to thank TechOne Consulting for sponsoring the work on the render cache module for seven weeks and the Drupal Association actually for providing me with a grant to work on some pre-work for all the stuff you today saw. So if I could ask you a favor, if you liked what you saw today and you want to see more of great performance work in Drupal 8, please donate to Drupal 8 Accelerate. That would be great because it makes things like this possible, makes things like this and views possible so that cacheability is everywhere great. That's one big deal we are working on right now. And last thing I want to thank Akia's office of the CTO who have sponsored some of that Big Pipe stuff. Thanks. And finally, if you want to read more about this, we do have decent documentation already about these things where you can actually read more about it in silence. And if there are things unclear, ping me on IRC or ping me on Twitter and we will work on improving the documentation further. And last but not least, Big Pipe has fabian demonstrated it. There is an issue in the CorkU and it's right there listed below. And if there are questions, feel free to ask now.