My custom controller is returning data but it is never being cached.

My controller function:

use Symfony\Component\HttpFoundation\Response;

 $build = [
            '#theme' => 'search_form_suggest',
            '#nodes' => $nodes,
            '#term' => $term,
            '#type' => $type,
            '#cache' => [
                'keys' => [
                    'sg_search_term_suggestions_' . $term . "_". $type
                'tags' => [
                    'sg_search_term_suggestions_' . $term . "_". $type
                'contexts' => ['route']

$response = new Response($content);
return $response;
//retrun $build; //this does serve from CACHE

Looks like it never ends up hitting the cache mechanism. When I return $build then it does serve from cache.

1 Answer 1


Return a cacheable response. For example

use Drupal\Core\Cache\CacheableResponse;
use Drupal\user\Entity\User;

   * A route returning a CacheableResponse object.
   * @return \Drupal\Core\Cache\CacheableResponseInterface
   *   A CacheableResponseInterface object.
  public function cacheableResponse() {
    $user = User::load(1);
    $response = new CacheableResponse($user->label());
    return $response;

From Drupal\dynamic_page_cache_test\DynamicPageCacheTestController.

There are multiple ways to add cache data to the response object additional to the one used in the example.

You can use addCacheTags()/addCacheContexts():


The route cache context is by the way not necessary in a controller because it depends already on the route.

Or add cacheable metadata contained in a render array

use Drupal\Core\Cache\CacheableMetadata;


See also How to handle cache metadata in a cacheable response? and How to get cache metadata from nested render array when returning response?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.