{"id":3120,"date":"2024-04-18T15:15:45","date_gmt":"2024-04-18T22:15:45","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sql\/?p=3120"},"modified":"2024-04-18T15:21:11","modified_gmt":"2024-04-18T22:21:11","slug":"data-api-builder-caching-feature","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sql\/data-api-builder-caching-feature\/","title":{"rendered":"Data API builder Version 0.11 Brings In-Memory Caching"},"content":{"rendered":"<p>Literally, I just said that! I have three daughters, and it&#8217;s amazing how they ask me the same questions over and over. I don&#8217;t mind answering them, but I sure wish they would either remember my answer or, at least, write it down. There&#8217;s a measurable cognitive load with the context switching and staying consistent in my answers. And that&#8217;s a good\u2014though a little messy\u2014segue into data caching.\u00a0<strong>Data API builder can now relieve your database&#8217;s burden with the new caching feature available to REST endpoints.\u00a0<\/strong><\/p>\n<p><div class=\"alert alert-info\"><p class=\"alert-divider\"><i class=\"fabric-icon fabric-icon--Info\"><\/i><strong>Version 0.11 is now available<\/strong><\/p>Data API builder goes into General Availability soon, in the meantime, these are pre-version 1.0 releases, like <a href=\"https:\/\/github.com\/Azure\/data-api-builder\/releases\">version 0.11<\/a>, with bug fixes, fit and finish improvements, and brand-new features like caching\u2014the focus of this article.<\/div><\/p>\n<p><!--more-->Your database is good at joining, filtering, sorting, and projecting data. Two, ten, even a hundred times a second isn&#8217;t a big deal if you have a sufficiently allocated database. But eventually, you reach a point where just asking the same question over and over doesn&#8217;t yield new results and pushes your database to its knees for no good reason. <a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2.png\"><img decoding=\"async\" class=\"alignright wp-image-3123 size-medium\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-300x300.png\" alt=\"Data API builder's caching feature relieves your database's burden.\" width=\"300\" height=\"300\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-300x300.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-150x150.png 150w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-768x768.png 768w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-24x24.png 24w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-48x48.png 48w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2-96x96.png 96w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/scale2.png 1024w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Data caching is an important strategy that lets you more freely determine how to invest in each part of your solution topology. Let&#8217;s weigh the advantages while comparing the cost of each component.<\/p>\n<p>Do you pay for a larger database, or do you pay for a caching service? This is a reasonable question because the TCO (Total Cost of Ownership) of each service is not equal\u2014even if they start that way. Databases, reliable and capable, eventually become a significant cost in any solution.<\/p>\n<h3>Caching in the API tier<\/h3>\n<p>Introducing a data API layer centralizes non-database capabilities in one place, offering significant benefits. For example, Data API builder manages data projection, security policies, graph resolution, application logs, and now in-memory caching. Since JSON payloads are generally small, caching them in container memory is straightforward. Your API often represents the most cost-effective part of your solution, and leveraging underutilized RAM can greatly benefit your budget.<\/p>\n<h3>We use Fusion Cache<\/h3>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/Fusion_Cache.png\"><img decoding=\"async\" class=\"alignright wp-image-3127 size-medium\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/Fusion_Cache-300x205.png\" alt=\"Fusion Cache Overview\" width=\"300\" height=\"205\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/Fusion_Cache-300x205.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/Fusion_Cache-768x526.png 768w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/Fusion_Cache.png 799w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>What&#8217;s great about Data API builder is that we aren&#8217;t building something exotic. We&#8217;re building a regular data API just like you would build. Because of this, your code base doesn&#8217;t need as much source code. As we often say about Data API builder, &#8220;<em>more engine, less code<\/em>.&#8221;<\/p>\n<p>But even better, because this is all standard, we use common technologies, frameworks, and techniques. To that end, we have selected <a href=\"https:\/\/github.com\/ZiggyCreatures\/FusionCache\">Fusion Cache<\/a> as our caching library. Why? Because it&#8217;s .NET, it&#8217;s brand new, it&#8217;s pluggable, and it allows us to plan for the future\u2014introducing distributed, second-level caches like Redis or <a href=\"https:\/\/www.microsoft.com\/en-us\/research\/blog\/introducing-garnet-an-open-source-next-generation-faster-cache-store-for-accelerating-applications-and-services\/\">Microsoft Garnet<\/a>.<\/p>\n<p>Fusion Cache is award-winning and includes advanced resiliency features like cache stampede prevention, a fail-safe mechanism, fine-grained soft\/hard timeouts with background factory completion, and customizable extensive logging. It uses a memory cache as the primary backing store and, optionally, a distributed, second-level cache as a secondary backing store for better resilience and higher performance, such as in a multi-node scenario or to mitigate the typical effects of a cold start.<\/p>\n<h3>Simple to use caching feature<\/h3>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo.png\"><img decoding=\"async\" class=\"alignright wp-image-2563 size-medium\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo-300x300.png\" alt=\"Data API builder logo\" width=\"300\" height=\"300\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo-300x300.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo-150x150.png 150w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo-24x24.png 24w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo-48x48.png 48w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo-96x96.png 96w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2023\/10\/dab-logo.png 336w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>Data API builder remains committed to simplicity. Developers have the flexibility to configure caching on a global scale or for each entity as needed. The available settings are Enabled and Time-To-Live (TTL). You can set Enabled to either true or false (default). TTL specifies how long cached data remains valid before expiring.<\/p>\n<p>Activating caching and setting a TTL for an entity prompts the system to store the data returned from the API call in an in-memory cache. The system then utilizes this cached data for future requests for the same data, significantly boosting your application&#8217;s performance by minimizing the need for additional network calls or database queries. Check out <a href=\"https:\/\/aka.ms\/dab\/docs\">our docs<\/a>.<\/p>\n<h4>Global configuration<\/h4>\n<pre class=\"prettyprint language-json\"><code class=\"language-json\">{\r\n ...\r\n \"runtime\": {\r\n    \"cache\": {\r\n      \"enabled\": true,\r\n      \"ttl-seconds\": 5\r\n    }\r\n  }\r\n}<\/code><\/pre>\n<p class=\"prettyprint language-json\">Allowing developers global control to enable or disable caching lets them deactivate caching (default) for debugging or activate it during crucial, peak events. Setting the TTL globally enables developers to omit this value from individual entity configurations if they prefer.<\/p>\n<h4>Entity configuration<\/h4>\n<pre class=\"prettyprint language-json\"><code class=\"language-json\"> \"entities\": {\r\n    \"Actor\": {\r\n      ...\r\n      \"cache\": {\r\n        \"enabled\": true,\r\n        \"ttl-seconds\": 1\r\n      }\r\n    },<\/code><\/pre>\n<p class=\"prettyprint language-json\">Granular control over each entity allows developers to pinpoint the best opportunities for cost savings and performance gains, while maintaining the control they need to ensure appropriate representation of volatile data.<\/p>\n<h3>Cache caveats<\/h3>\n<p><strong>Caching supports REST endpoints but not GraphQL endpoints.<\/strong> With REST, the system returns entities one at a time, and filters appear in the URL, simplifying the identification of repeated calls and the creation of caching keys. We are still developing a secure and reliable method to uniquely identify GraphQL queries, an initial step necessary to enable GraphQL caching. As a result, we have not enabled caching for GraphQL endpoints yet.<\/p>\n<p><strong>The system automatically disables caching when it enables session context in the configuration file.<\/strong> This feature, specific to SQL Server, allows developers to pass claims information to the database where objects can use them for custom logic\u2014often for row-level security. This custom logic can generate internal predicates invisible to the Data API builder, making the caching key unreliable and possibly returning results inadvertently. Consequently, the system disables caching when it enables the session context.<\/p>\n<pre class=\"prettyprint language-json\"><code class=\"language-json\">{\r\n  ...\r\n  \"data-source\": {\r\n    \"database-type\": \"mssql\",\r\n    \"connection-string\": ...,\r\n    \"options\": {\r\n      \"set-session-context\": false\r\n    }\r\n  },\r\n}<\/code><\/pre>\n<p><strong>The system fully supports caching for tables and views, but support for stored procedures is forthcoming.<\/strong> Despite these caveats, caching is available to most Data API builder customers and in most currently deployed scenarios.<\/p>\n<h3>Caching benefits: relieves your database<\/h3>\n<p>Understanding that caching is more than just a way to budget resources is crucial. Yes, caching allows you to allocate spending toward lower-cost services in your solution. But it also offers an incredible way to scale. Developers often consider caching in terms of minutes, but let&#8217;s discuss caching for just a single second\u2014that is, with a time-to-live value of one.<\/p>\n<h4>Time to live: one second<\/h4>\n<p>When several calls simultaneously hit your endpoint (presenting the same caching key), we refer to this burst of requests as a stampede. Practically speaking, Data API builder executes the first call against the database and makes the others wait. This approach means 100 simultaneous calls result in a single database query. To put it more dramatically, 1,000,000 simultaneous calls to your endpoint would result in just a single database query. Then, once the first call returns, the system returns the results for the rest.<\/p>\n<p>After that, the system returns every call inside the time-to-live window instantly from memory, without involving the database. This improvement not only reduces response times from seconds to milliseconds but also frees your database to perform other operations or respond to other queries. You have scaled your endpoint to handle 10, even 100 times as many requests with a TTL value so low, most scenarios would not consider the results stale.<\/p>\n<h5>Consider these results:<\/h5>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/cache-results.png\"><img decoding=\"async\" class=\"alignnone wp-image-3152 size-full\" src=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/cache-results.png\" alt=\"Data API builder's caching feature relieves your database's burden.\" width=\"1143\" height=\"482\" srcset=\"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/cache-results.png 1143w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/cache-results-300x127.png 300w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/cache-results-1024x432.png 1024w, https:\/\/devblogs.microsoft.com\/azure-sql\/wp-content\/uploads\/sites\/56\/2024\/04\/cache-results-768x324.png 768w\" sizes=\"(max-width: 1143px) 100vw, 1143px\" \/><\/a><\/p>\n<p>The left and right tests are identical in concurrency and duration. The test on the left sets a time-to-live of zero seconds, effectively turning caching off. The test on the right sets a time-to-live of just one second. The database query takes 5 seconds to execute.\u00a0Look at the multiplier between the two scenarios even with such a tiny time-to-live. Caching works wonders and makes your database look like a champ. Data API builder can now relieve your database&#8217;s burden with the new caching feature available to REST endpoints.<\/p>\n<p><strong>We hope you love Data API builder.<\/strong> Our open-source <a href=\"https:\/\/aka.ms\/dab\">repository<\/a> on GitHub is a great place to view the code, report issues, and\u2014importantly\u2014sign up to be part of the Data API builder community. You can find the signup at the top of the repository&#8217;s readme file. We invite you to join our open-source team.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Literally, I just said that! I have three daughters, and it&#8217;s amazing how they ask me the same questions over and over. I don&#8217;t mind answering them, but I sure wish they would either remember my answer or, at least, write it down. There&#8217;s a measurable cognitive load with the context switching and staying consistent [&hellip;]<\/p>\n","protected":false},"author":96788,"featured_media":81,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,597,576],"tags":[],"class_list":["post-3120","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sql","category-data-api-builder-2","category-rest"],"acf":[],"blog_post_summary":"<p>Literally, I just said that! I have three daughters, and it&#8217;s amazing how they ask me the same questions over and over. I don&#8217;t mind answering them, but I sure wish they would either remember my answer or, at least, write it down. There&#8217;s a measurable cognitive load with the context switching and staying consistent [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/3120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/users\/96788"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/comments?post=3120"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/posts\/3120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media\/81"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/media?parent=3120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/categories?post=3120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sql\/wp-json\/wp\/v2\/tags?post=3120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}