{"id":142,"date":"2026-11-06T08:00:00","date_gmt":"2026-11-06T07:00:00","guid":{"rendered":"https:\/\/hoja.in\/blog\/?p=142"},"modified":"2026-10-16T14:00:13","modified_gmt":"2026-10-16T12:00:13","slug":"using-the-typo3-caching-framework-in-your-own-extension","status":"publish","type":"post","link":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/","title":{"rendered":"Using the TYPO3 caching framework in your own extension"},"content":{"rendered":"<p>Here is a situation I have seen more than once. An extension shows data from an external service, for example opening hours or events from a city API. The plugin is <code>USER_INT<\/code> because &#8220;the data must be fresh&#8221;, and every page view makes an HTTP call. The external service answers in one or two seconds on a good day. On a bad day the whole page waits.<\/p>\n<p>The fix is not to make the page cached and hope. The fix is to cache the expensive part, the API answer, with the TYPO3 caching framework. It has been in the core since 4.3, and it is still one of the most underused APIs in extensions I review.<\/p>\n<h2>Step 1: register the cache<\/h2>\n<p>A cache is a frontend (how values are stored: <code>VariableFrontend<\/code> for any serializable PHP value, <code>PhpFrontend<\/code> for PHP code) plus a backend (where they are stored). Register it in <code>ext_localconf.php<\/code>:<\/p>\n<pre><code class=\"language-php\">&lt;?php\n\ndefined('TYPO3') or die();\n\n$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_feed'] ??= [];\n$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_feed']['groups'] ??= ['pages'];<\/code><\/pre>\n<p>That&#8217;s really all. When frontend and backend are not set, the <code>CacheManager<\/code> uses <code>VariableFrontend<\/code> with <code>Typo3DatabaseBackend<\/code>. The <code>??=<\/code> is important: it lets the project override the configuration in <code>config\/system\/additional.php<\/code> without fighting your extension.<\/p>\n<p>The <code>groups<\/code> entry decides which &#8220;flush&#8221; actions clear your cache. Without it, the default group is <code>all<\/code>. I put this cache in <code>pages<\/code>, because its content is shown on pages and should be cleared together with the page cache. You will see in step 4 why this choice brings a nice bonus.<\/p>\n<p>With the database backend, TYPO3 needs two tables, <code>cache_myext_feed<\/code> and <code>cache_myext_feed_tags<\/code>. The Database Analyzer in the Install Tool or <code>ddev typo3 extension:setup<\/code> creates them for you.<\/p>\n<h2>Step 2: inject the cache<\/h2>\n<p>Don&#8217;t call <code>GeneralUtility::makeInstance(CacheManager::class)-&gt;getCache()<\/code> all over the place. Define the cache as a service and inject it, just like the core does for <code>cache.hash<\/code> or <code>cache.pages<\/code>:<\/p>\n<pre><code class=\"language-yaml\"># Configuration\/Services.yaml\nservices:\n  _defaults:\n    autowire: true\n    autoconfigure: true\n    public: false\n\n  VendorMyExt:\n    resource: '..\/Classes\/*'\n\n  cache.myext_feed:\n    class: TYPO3CMSCoreCacheFrontendFrontendInterface\n    factory: ['@TYPO3CMSCoreCacheCacheManager', 'getCache']\n    arguments: ['myext_feed']\n\n  VendorMyExtServiceFeedService:\n    arguments:\n      $cache: '@cache.myext_feed'<\/code><\/pre>\n<p>Instead of the last three lines you can also write <code>#[Autowire(service: 'cache.myext_feed')]<\/code> in front of the constructor parameter. Several core classes do exactly that with <code>cache.runtime<\/code>.<\/p>\n<h2>Step 3: read, fetch, tag, store<\/h2>\n<pre><code class=\"language-php\">&lt;?php\n\ndeclare(strict_types=1);\n\nnamespace VendorMyExtService;\n\nuse TYPO3CMSCoreCacheFrontendFrontendInterface;\nuse TYPO3CMSCoreHttpRequestFactory;\n\nfinal readonly class FeedService\n{\n    public function __construct(\n        private FrontendInterface $cache,\n        private RequestFactory $requestFactory,\n    ) {}\n\n    \/**\n     * @param array{uid: int, url: string, lifetime: int} $feed record from tx_myext_feed\n     *\/\n    public function getItems(array $feed): array\n    {\n        $identifier = 'feed_' . $feed['uid'] . '_' . sha1($feed['url']);\n        $items = $this-&gt;cache-&gt;get($identifier);\n        if (is_array($items)) {\n            return $items;\n        }\n\n        try {\n            $response = $this-&gt;requestFactory-&gt;request($feed['url'], 'GET', ['timeout' =&gt; 3]);\n            $items = json_decode((string)$response-&gt;getBody(), true, 32, JSON_THROW_ON_ERROR);\n        } catch (Throwable) {\n            \/\/ Remember the failure for one minute, do not hammer a broken API\n            $this-&gt;cache-&gt;set($identifier, [], ['tx_myext_feed_' . $feed['uid']], 60);\n            return [];\n        }\n\n        $this-&gt;cache-&gt;set(\n            $identifier,\n            $items,\n            ['tx_myext_feed', 'tx_myext_feed_' . $feed['uid']],\n            $feed['lifetime'] ?: 3600\n        );\n        return $items;\n    }\n}<\/code><\/pre>\n<p>A few things that I learned the hard way:<\/p>\n<ul>\n<li>Cache identifiers allow only letters, numbers and <code>_ - % &amp;<\/code>, at most 250 characters. A URL with slashes and colons is not a valid identifier, so hash it. <code>isValidEntryIdentifier()<\/code> tells you if you are unsure.<\/li>\n<li><code>get()<\/code> returns <code>false<\/code> for a miss. If you store a value that can be <code>false<\/code> itself, wrap it in an array, otherwise you cannot tell the difference.<\/li>\n<li>Cache the failure too, with a short lifetime. Otherwise a broken API makes every request wait for the timeout, which was the original problem.<\/li>\n<li>Always set a timeout on outgoing requests. <code>RequestFactory<\/code> passes it to Guzzle.<\/li>\n<\/ul>\n<p>Now the plugin itself can be a normal cached plugin again, or stay <code>USER_INT<\/code> but cheap. Both are fine, the slow part is gone.<\/p>\n<h2>Step 4: flush by tag at the right moment<\/h2>\n<p>Tags are the real power. Here the bonus from step 1 comes in. When an editor saves a record, DataHandler collects the tags <code>&lt;table&gt;<\/code> and <code>&lt;table&gt;_&lt;uid&gt;<\/code> (for example <code>tx_myext_feed_12<\/code>) and flushes them in all caches of the group <code>pages<\/code>. Because my cache is in that group and I used the same tag names, editing the feed record in the backend empties exactly the entries of that feed. No hook, no event listener, no code at all. This holds as long as nobody disabled it with <code>TCEMAIN.clearCache_disable<\/code> in page TSconfig.<\/p>\n<p>For other moments there are more tools:<\/p>\n<pre><code class=\"language-bash\"># TYPO3 v14: flush by tag from the command line, e.g. in a cron job after the API publishes new data\nddev typo3 cache:flushtags tx_myext_feed -g pages<\/code><\/pre>\n<pre><code class=\"language-typoscript\"># Page TSconfig: saving anything on this page also flushes all feed entries\nTCEMAIN.clearCacheCmd = cacheTag:tx_myext_feed<\/code><\/pre>\n<p>The <code>cache:flushtags<\/code> command is new in v14 (<a href=\"https:\/\/docs.typo3.org\/c\/typo3\/cms-core\/main\/en-us\/Changelog\/14.0\/Feature-104054-AddTagOptionToCacheFlushCommand.html\">Feature-104054<\/a>). In v13 you would write a tiny command yourself that calls <code>$this-&gt;cache-&gt;flushByTag('tx_myext_feed')<\/code>. And when you really need code on save, <code>$cache-&gt;flushByTag()<\/code> or <code>CacheManager::flushCachesInGroupByTags()<\/code> are the calls to use.<\/p>\n<h2>Step 5: choose the backend for production<\/h2>\n<p>The database backend is a good default. It works everywhere and survives deployments. For production I decide per cache:<\/p>\n<ul>\n<li>Few, big entries, read on many pages: database backend is fine. Keep <code>defaultLifetime<\/code> sensible, or the table grows forever. Garbage collection runs with the scheduler task &#8220;Caching framework garbage collection&#8221;.<\/li>\n<li>Many small entries and lots of traffic: <code>RedisBackend<\/code>. It supports tags, which <code>SimpleFileBackend<\/code> does not.<\/li>\n<li>Data needed only during one request: <code>TransientMemoryBackend<\/code>, or simply the core <code>cache.runtime<\/code>.<\/li>\n<\/ul>\n<p>Since the extension registered only defaults with <code>??=<\/code>, the project decides in <code>config\/system\/additional.php<\/code>:<\/p>\n<pre><code class=\"language-php\">$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_feed']['backend']\n    = TYPO3CMSCoreCacheBackendRedisBackend::class;\n$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['myext_feed']['options'] = [\n    'hostname' =&gt; 'redis',\n    'port' =&gt; 6379,\n    'database' =&gt; 3,\n    'defaultLifetime' =&gt; 3600,\n];<\/code><\/pre>\n<p>Give each cache its own Redis database number, so a flush of one never wipes another. One note for v14: if you wrote your own cache backend, the interfaces are now strictly typed and <code>AbstractBackend<\/code> lost the old constructor argument (<a href=\"https:\/\/docs.typo3.org\/c\/typo3\/cms-core\/main\/en-us\/Changelog\/14.0\/Breaking-107315-CacheBackendAndFrontendRelatedChanges.html\">Breaking-107315<\/a>). Using the core backends as shown above is not affected.<\/p>\n<p>If this post saved one of your pages from a slow API, I will be really happy. Cheers!<\/p>\n<h2>Further reading<\/h2>\n<ul>\n<li><a href=\"https:\/\/docs.typo3.org\/m\/typo3\/reference-coreapi\/main\/en-us\/ApiOverview\/CachingFramework\/Index.html\">TYPO3 Explained: Caching framework<\/a><\/li>\n<li><a href=\"https:\/\/docs.typo3.org\/m\/typo3\/reference-coreapi\/main\/en-us\/ApiOverview\/CachingFramework\/Developer\/Index.html\">TYPO3 Explained: Caching framework for developers<\/a><\/li>\n<li><a href=\"https:\/\/docs.typo3.org\/m\/typo3\/reference-coreapi\/main\/en-us\/ApiOverview\/Http\/Index.html\">TYPO3 Explained: HTTP requests to external sources<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A plugin that calls a slow external API on every request. How to register your own cache, inject it, tag entries, flush them at the right moment and pick a backend for production.<\/p>\n","protected":false},"author":1,"featured_media":143,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[30,39,5,33,24],"class_list":["post-142","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-typo3","tag-extension-development","tag-performance","tag-typo3","tag-typo3-v13","tag-typo3-v14"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>TYPO3 caching framework in your own extension<\/title>\n<meta name=\"description\" content=\"Use the TYPO3 caching framework in your extension: register a cache, inject it via Services.yaml, tag entries, flush on save, pick a production backend.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TYPO3 caching framework in your own extension\" \/>\n<meta property=\"og:description\" content=\"Use the TYPO3 caching framework in your extension: register a cache, inject it via Services.yaml, tag entries, flush on save, pick a production backend.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/\" \/>\n<meta property=\"og:site_name\" content=\"Hoja Mustaffa Abdul Latheef \u2013 Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-11-06T07:00:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/using-the-typo3-caching-framework-in-your-own-extension.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:site\" content=\"@hojaonline\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Hoja Mustaffa Abdul Latheef\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/\"},\"author\":{\"name\":\"Hoja Mustaffa Abdul Latheef\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"headline\":\"Using the TYPO3 caching framework in your own extension\",\"datePublished\":\"2026-11-06T07:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/\"},\"wordCount\":733,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/using-the-typo3-caching-framework-in-your-own-extension.jpg\",\"keywords\":[\"Extension development\",\"Performance\",\"TYPO3\",\"TYPO3 v13\",\"TYPO3 v14\"],\"articleSection\":[\"TYPO3\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/\",\"name\":\"TYPO3 caching framework in your own extension\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/using-the-typo3-caching-framework-in-your-own-extension.jpg\",\"datePublished\":\"2026-11-06T07:00:00+00:00\",\"description\":\"Use the TYPO3 caching framework in your extension: register a cache, inject it via Services.yaml, tag entries, flush on save, pick a production backend.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/using-the-typo3-caching-framework-in-your-own-extension.jpg\",\"contentUrl\":\"https:\\\/\\\/hoja.in\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/using-the-typo3-caching-framework-in-your-own-extension.jpg\",\"width\":1200,\"height\":630,\"caption\":\"Your own cache, done right\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/using-the-typo3-caching-framework-in-your-own-extension\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using the TYPO3 caching framework in your own extension\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/hoja.in\\\/blog\\\/\",\"name\":\"Hoja Mustaffa Abdul Latheef \u2013 Blog\",\"description\":\"Notes from daily work with TYPO3, PHP and AI-assisted engineering\",\"publisher\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hoja.in\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/e6fbd54c2061674d8ea3e7861d858c7b\",\"name\":\"Hoja Mustaffa Abdul Latheef\",\"logo\":{\"@id\":\"https:\\\/\\\/hoja.in\\\/blog\\\/#\\\/schema\\\/person\\\/image\\\/\"},\"description\":\"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.\",\"sameAs\":[\"https:\\\/\\\/hoja.in\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"TYPO3 caching framework in your own extension","description":"Use the TYPO3 caching framework in your extension: register a cache, inject it via Services.yaml, tag entries, flush on save, pick a production backend.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/","og_locale":"en_US","og_type":"article","og_title":"TYPO3 caching framework in your own extension","og_description":"Use the TYPO3 caching framework in your extension: register a cache, inject it via Services.yaml, tag entries, flush on save, pick a production backend.","og_url":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/","og_site_name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","article_published_time":"2026-11-06T07:00:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/using-the-typo3-caching-framework-in-your-own-extension.jpg","type":"image\/jpeg"}],"author":"Hoja Mustaffa Abdul Latheef","twitter_card":"summary_large_image","twitter_creator":"@hojaonline","twitter_site":"@hojaonline","twitter_misc":{"Written by":"Hoja Mustaffa Abdul Latheef","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#article","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/"},"author":{"name":"Hoja Mustaffa Abdul Latheef","@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"headline":"Using the TYPO3 caching framework in your own extension","datePublished":"2026-11-06T07:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/"},"wordCount":733,"commentCount":0,"publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"image":{"@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/using-the-typo3-caching-framework-in-your-own-extension.jpg","keywords":["Extension development","Performance","TYPO3","TYPO3 v13","TYPO3 v14"],"articleSection":["TYPO3"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/","url":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/","name":"TYPO3 caching framework in your own extension","isPartOf":{"@id":"https:\/\/hoja.in\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#primaryimage"},"image":{"@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#primaryimage"},"thumbnailUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/using-the-typo3-caching-framework-in-your-own-extension.jpg","datePublished":"2026-11-06T07:00:00+00:00","description":"Use the TYPO3 caching framework in your extension: register a cache, inject it via Services.yaml, tag entries, flush on save, pick a production backend.","breadcrumb":{"@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#primaryimage","url":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/using-the-typo3-caching-framework-in-your-own-extension.jpg","contentUrl":"https:\/\/hoja.in\/blog\/wp-content\/uploads\/2026\/10\/using-the-typo3-caching-framework-in-your-own-extension.jpg","width":1200,"height":630,"caption":"Your own cache, done right"},{"@type":"BreadcrumbList","@id":"https:\/\/hoja.in\/blog\/using-the-typo3-caching-framework-in-your-own-extension\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/hoja.in\/blog\/"},{"@type":"ListItem","position":2,"name":"Using the TYPO3 caching framework in your own extension"}]},{"@type":"WebSite","@id":"https:\/\/hoja.in\/blog\/#website","url":"https:\/\/hoja.in\/blog\/","name":"Hoja Mustaffa Abdul Latheef \u2013 Blog","description":"Notes from daily work with TYPO3, PHP and AI-assisted engineering","publisher":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hoja.in\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/e6fbd54c2061674d8ea3e7861d858c7b","name":"Hoja Mustaffa Abdul Latheef","logo":{"@id":"https:\/\/hoja.in\/blog\/#\/schema\/person\/image\/"},"description":"Senior TYPO3 Developer at jweiland.net, TYPO3 CMS Certified Developer. I write about TYPO3 upgrades, extension development, PHP and AI-assisted engineering with Claude Code.","sameAs":["https:\/\/hoja.in\/"]}]}},"_links":{"self":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/142","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/comments?post=142"}],"version-history":[{"count":1,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/142\/revisions"}],"predecessor-version":[{"id":149,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/posts\/142\/revisions\/149"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media\/143"}],"wp:attachment":[{"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/media?parent=142"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/categories?post=142"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hoja.in\/blog\/wp-json\/wp\/v2\/tags?post=142"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}