Hook or event before a page gets cached
If you need to decide whenever a page should be cached from Drupal, you need to create a service that implements the \Drupal\Core\PageCache\ResponsePolicyInterface interface and it's tagged page_cache_response_policy, as described in Flexible page cache policy.

That page shows code that can be used as example. You can also use code that Drupal core actually implements, as example, like the code for the node.page_cache_response_policy.deny_node_preview service.

The code implementing the service is quite simple. It becomes more complex basing on the logic you need to apply to decide when a page should be cached.

class DenyNodePreview implements ResponsePolicyInterface {

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a deny node preview page cache policy.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The current route match.
   */
  public function __construct(RouteMatchInterface $route_match) {
    $this-&gt;routeMatch = $route_match;
  }

  /**
   * {@inheritdoc}
   */
  public function check(Response $response, Request $request) {
    if ($this-&gt;routeMatch
      -&gt;getRouteName() === 'entity.node.preview') {
      return static::DENY;
    }
  }

}