Anonymous user cache control We have written some custom blocks that render dynamic content; unfortunately, the caching defaults cache the first render of this block (and don't refresh for anonymous users). Cache control seems to only work for authenticated users. Are we missing something obvious? Is it possible to control anonymous caching on a block (or page) basis?
There are two different page caches.

The Internal Dynamic Page Cache works with all kind of elements like blocks and nodes and is uses the cache tags, cache contexts and cache max-age provided by these elements.

The Internal Page Cache is for complete pages for anonymous users and only uses cache tags.

You can control the page cache for anonymous users with one parameter.

Go to the perfomance configuration:

admin/config/development/performance


And configure the page cache maximum age with the time how long your information is valid. This is also important for proxies and the browser cache, because it would not help to invalidate the drupal cache, if the page is cached in other places. After that time the page expires and should be built again. According to the documentation:


  Configuring the internal page cache On the Performance page, you can
  configure how long browsers and proxies may cache pages; that setting
  is also respected by the Internal Page Cache module. There is no other
  configuration.


But this is not true. You should configure this time for proxies and browser cache, but the internal page cache does not respect the time you set there. The only reliable solution I found is to uninstall the module Internal Page Cache or set an expire time in an EventSubscriber (for example 3600 sec in the future):

/src/EventSubscriber/SetExpiresSubscriber.php

&lt;?php

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class SetExpiresSubscriber implements EventSubscriberInterface {

  public function onResponse(FilterResponseEvent $event) {
    $request = $event-&gt;getRequest();
    $response = $event-&gt;getResponse();
    if ($event-&gt;isMasterRequest()) {
      $request_time = $request-&gt;server-&gt;get('REQUEST_TIME');
      $expires_time = (new \Datetime)-&gt;setTimestamp($request_time + 3600);
      $response-&gt;setExpires($expires_time);
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['onResponse'];
    return $events;
  }

}


mymodule.services.yml

services:
  mymodule.setexpires:
    class: Drupal\mymodule\EventSubscriber\SetExpiresSubscriber
    tags:
      - { name: event_subscriber }