How to prevent programmatically created blocks from caching I've been working with Drupal 7 for a couple of years but am new to Drupal 8, and am just getting into building custom modules.

What I have built is a module that alters Drupal Commerce in order to make it work smoother for sponsoring children (so that it doesn't feel like you are buying children).

It does a couple of things:
1. If you add a second product to the cart, it deletes your old cart.
2. After clicking add to cart, it redirects you to an information page.
3. That page contains a module-generated block with a "continue" button that takes the customer to checkout.

The issue I am hitting is that the code which generates the checkout button block is getting cached, and is pulling an old, no longer existing order ID number.

Is there a way to prevent the block from getting cached, or a better way to programmatically set up a custom block?

Here is my code:

\src\Plugin\Block\ContinueCheckoutBlock.php

&lt;?php
/**
 * @file
 * Contains \Drupal\commerce_custom\Plugin\Block\ContinueCheckoutBlock.
 */
namespace Drupal\commerce_custom\Plugin\Block;
use Drupal\Core\Block\BlockBase;
use Symfony\Component\HttpFoundation;

/**
 * Provides a 'Continue Checkout' block.
 *
 * @Block(
 *   id = "continue_checkout",
 *   admin_label = @Translation("Continue Checkout"),
 *   category = @Translation("Continue Checkout Custom Block")
 * )
 */
class ContinueCheckoutBlock extends BlockBase {
  /**
   * {@inheritdoc}
   */

   public function build() {

      $user = \Drupal::currentUser()-&gt;id();
        $connection = \Drupal::database();
    $user_ip = \Drupal::request()-&gt;getClientIp();
        $query = $connection-&gt;query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft' and commerce_order.ip_address = :user_ip order by commerce_order.changed asc limit 1", [':user' =&gt; $user, ':user_ip' =&gt; $user_ip]);
        $result = $query-&gt;fetchAll();
        $order_id = $result[0]-&gt;order_id;
    drupal_set_message($order_id);

        return array(
            '#type' =&gt;'markup',
            '#markup' =&gt; '&lt;a href=checkout/' . $order_id . '/login class=button&gt;Continue&lt;/a&gt;',
            '#cache' =&gt; array('max_age'=&gt; 0),
        );
   }
}


commerce_custom.module

&lt;?php

use Drupal\Core\Form\FormStateInterface;
use Drupal\commerce_order\Entity\Order;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_custom_form_commerce_order_item_add_to_cart_form_alter(&amp;$form, FormStateInterface $form_state, $form_id) {
   $form['actions']['submit']['#value']='Sponsor';
   $form['#validate'][] = 'commerce_custom_form_validate';
   $form['actions']['submit']['#submit'][] = 'commerce_custom_cart_alter_redirect';
}

function commerce_custom_form_validate(array &amp;$form, FormStateInterface $form_state) {

    $user = \Drupal::currentUser()-&gt;id();
    $connection = \Drupal::database();
    $user_ip = \Drupal::request()-&gt;getClientIp();
    $query = $connection-&gt;query("select * from commerce_order_item join commerce_order on commerce_order_item.order_id = commerce_order.order_id where uid = :user and state = 'draft' and commerce_order.ip_address = :user_ip order by commerce_order.changed desc limit 1", [':user' =&gt; $user, ':user_ip' =&gt; $user_ip]);
    $result = $query-&gt;fetchAll();

    $cart_count = $result[0]-&gt;quantity;
    $order_id = $result[0]-&gt;order_id;

    if ($cart_count &gt; 0 &amp;&amp; $order_id) {
        $order = \Drupal::entityTypeManager()-&gt;getStorage('commerce_order')-&gt;load($order_id);
        $items = $order-&gt;getItems();
        $order-&gt;delete();
    }
}

function commerce_custom_cart_alter_redirect(&amp;$form, FormStateInterface $form_state) {
  $responce =  new RedirectResponse('/how-it-works');
  $responce-&gt;send();
}
The bug is in your code. max_age should actually be max-age.

See the documentation page for more information: https://www.drupal.org/docs/8/api/cache-api/cache-max-age

You could also set the max age in Jdrupal's answer.