 core/modules/system/theme.api.php | 70 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php
index b88f740..db1dbbf 100644
--- a/core/modules/system/theme.api.php
+++ b/core/modules/system/theme.api.php
@@ -287,6 +287,74 @@
  * properties. Look through implementations of hook_element_info() to discover
  * elements defined this way.
  *
+ * @section sec_cacheability Cacheability
+ *
+ * Since the contents of a render array determine what is shown to the user, it
+ * also depends on render arrays "how cacheable" a page is. If your code is
+ * generating very dynamic render arrays (generally speaking, if it is using a
+ * lot of if-statements), then it also means that Drupal cannot simply cache the
+ * HTML that was rendered from your render array: it needs to call your code
+ * (and all those if-statements) when appropriate!
+ *
+ * In other words: Drupal needs to be aware of how dynamic your code is. If it's
+ * not aware, then it may send the same cached HTML to the wrong user!
+ *
+ * This is why it is of the utmost importance that you inform the Render API of
+ * the cacheability of a render array.
+ *
+ * Whenever you are generating a render array, use the following 4 steps:
+ * 1. I'm rendering something. That means I must think of cacheability!
+ * 2. Is this something that's expensive to render, and therefore is worth
+ *    caching? If the answer is "yes", then what identifies this particular
+ *    representation of the thing I'm rendering?
+ *    Those are the cache keys.
+ *    They're only necessary if I want to cache this render array.
+ * 3. Does the representation of the thing I'm rendering vary per role (needs
+ *    permission), per URL (needs something of the request), per language, per …
+ *    something? Those are the cache contexts.
+ *    They're always necessary, because they affect the cacheability of the
+ *    entire page. Therefore they "bubble": parents automatically receive them.
+ *    Note: cache contexts are completely analogous to HTTP's Vary header!
+ * 4. When does the representation of the thing I'm rendering become outdated?
+ *    I.e. which things does it depend upon, so that when those things change,
+ *    so should my representation?
+ *    Those are the cache tags.
+ *    They're always necessary, because they affect the cacheability of the
+ *    entire page. Therefore they "bubble": parents automatically receive them.
+ *
+ * Cache keys, contexts and tags together form the cache metadata trifecta.
+ *
+ * Let's apply this to a concrete example:
+ * - cache keys: when rendering a node (thing) in the teaser view mode
+ *   (configuration indicating a specific representation), my cache keys would
+ *   be e.g. ['node', 5, 'teaser']
+ * - cache contexts: a teaser node is rendered differently for users in
+ *   different timezones (because of the "authored on" date field), so my cache
+ *   contexts would be e.g. ['timezone'].
+ * - cache tags: the node teaser shows the node title, authoring date, author,
+ *   author's profile picture and body, the dependencies are the node itself,
+ *   the user entity associated with the author, the file entity associated with
+ *   the profile picture and the text format associated with the body field. If
+ *   any of them change, then the cached HTML for the node 5 teaser must be
+ *   regenerated. So my cache tags would be: ['node:5', 'user:3', 'file:4',
+ *   'config:filter.format.basic_html'].
+ *
+ * In summary: when a render array represents a thing, then:
+ * - cache keys identify a representation of a thing
+ *   - may only be set if this render array should be cached
+ *   - will trigger caching of this render array (subtree)
+ * - cache contexts identify the variations of the representation of the thing
+ *   -  must always be set (because they bubble & affect the entire page)
+ * - cache tags identify the dependencies of the representation
+ *   - must always be set (because they bubble & affect the entire page).
+ *
+ * Note that every Entity and Config has a ::getCacheTags() method, with which
+ * one can easily get the cache tags of the objects a render array depends upon.
+ *
+ * Finally: it is easy to see what cache contexts a certain page varies by and
+ * which cache tags it is invalidated by: one must only look at the
+ * X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags headers!
+ *
  * @section sec_attached Attaching libraries in render arrays
  *
  *
@@ -303,7 +371,7 @@
  * values. Example:
  * @code
  * $build['#attached']['library'][] = 'core/jquery';
- * $build['#attached']['drupalSettings']['foo] = 'bar';
+ * $build['#attached']['drupalSettings']['foo'] = 'bar';
  * $build['#attached']['feed'][] = ['aggregator/rss', $this->t('Feed title')];
  * @endcode
  *
