Files
nexus/sreweekly/articles/452/05-making-aws-news-stupid-fast-with-smart-caching.html
2026-09-12 17:23:01 +08:00

1204 lines
160 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name='robots' content='max-image-preview:large' />
<!-- Async WordPress.com Remote Login -->
<script id="wpcom_remote_login_js">
var wpcom_remote_login_extra_auth = '';
function wpcom_remote_login_remove_dom_node_id( element_id ) {
var dom_node = document.getElementById( element_id );
if ( dom_node ) { dom_node.parentNode.removeChild( dom_node ); }
}
function wpcom_remote_login_remove_dom_node_classes( class_name ) {
var dom_nodes = document.querySelectorAll( '.' + class_name );
for ( var i = 0; i < dom_nodes.length; i++ ) {
dom_nodes[ i ].parentNode.removeChild( dom_nodes[ i ] );
}
}
function wpcom_remote_login_final_cleanup() {
wpcom_remote_login_remove_dom_node_classes( "wpcom_remote_login_msg" );
wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" );
wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_validate" );
wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_js" );
wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_iframe" );
wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_styles" );
}
// Watch for messages back from the remote login
window.addEventListener( "message", function( e ) {
if ( e.origin === "https://r-login.wordpress.com" ) {
var data = {};
try {
data = JSON.parse( e.data );
} catch( e ) {
wpcom_remote_login_final_cleanup();
return;
}
if ( data.msg === 'LOGIN' ) {
// Clean up the login check iframe
wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" );
var id_regex = new RegExp( /^[0-9]+$/ );
var token_regex = new RegExp( /^.*|.*|.*$/ );
if (
token_regex.test( data.token )
&& id_regex.test( data.wpcomid )
) {
// We have everything we need to ask for a login
var script = document.createElement( "script" );
script.setAttribute( "id", "wpcom_remote_login_validate" );
script.src = '/remote-login.php?wpcom_remote_login=validate'
+ '&wpcomid=' + data.wpcomid
+ '&token=' + encodeURIComponent( data.token )
+ '&host=' + window.location.protocol
+ '//' + window.location.hostname
+ '&postid=984'
+ '&is_singular=1';
document.body.appendChild( script );
}
return;
}
// Safari ITP, not logged in, so redirect
if ( data.msg === 'LOGIN-REDIRECT' ) {
window.location = 'https://wordpress.com/log-in?redirect_to=' + window.location.href;
return;
}
// Safari ITP, storage access failed, remove the request
if ( data.msg === 'LOGIN-REMOVE' ) {
var css_zap = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } @media screen and ( max-width: 782px ) { html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } }';
var style_zap = document.createElement( 'style' );
style_zap.type = 'text/css';
style_zap.appendChild( document.createTextNode( css_zap ) );
document.body.appendChild( style_zap );
var e = document.getElementById( 'wpcom_request_access_iframe' );
e.parentNode.removeChild( e );
document.cookie = 'wordpress_com_login_access=denied; path=/; max-age=31536000';
return;
}
// Safari ITP
if ( data.msg === 'REQUEST_ACCESS' ) {
console.log( 'request access: safari' );
// Check ITP iframe enable/disable knob
if ( wpcom_remote_login_extra_auth !== 'safari_itp_iframe' ) {
return;
}
// If we are in a "private window" there is no ITP.
var private_window = false;
try {
var opendb = window.openDatabase( null, null, null, null );
} catch( e ) {
private_window = true;
}
if ( private_window ) {
console.log( 'private window' );
return;
}
var iframe = document.createElement( 'iframe' );
iframe.id = 'wpcom_request_access_iframe';
iframe.setAttribute( 'scrolling', 'no' );
iframe.setAttribute( 'sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-top-navigation-by-user-activation' );
iframe.src = 'https://r-login.wordpress.com/remote-login.php?wpcom_remote_login=request_access&origin=' + encodeURIComponent( data.origin ) + '&wpcomid=' + encodeURIComponent( data.wpcomid );
var css = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 46px !important; } * html body { margin-top: 46px !important; } @media screen and ( max-width: 660px ) { html { margin-top: 71px !important; } * html body { margin-top: 71px !important; } #wpcom_request_access_iframe { display: block; height: 71px !important; } } #wpcom_request_access_iframe { border: 0px; height: 46px; position: fixed; top: 0; left: 0; width: 100%; min-width: 100%; z-index: 99999; background: #23282d; } ';
var style = document.createElement( 'style' );
style.type = 'text/css';
style.id = 'wpcom_request_access_styles';
style.appendChild( document.createTextNode( css ) );
document.body.appendChild( style );
document.body.appendChild( iframe );
}
if ( data.msg === 'DONE' ) {
wpcom_remote_login_final_cleanup();
}
}
}, false );
// Inject the remote login iframe after the page has had a chance to load
// more critical resources
window.addEventListener( "DOMContentLoaded", function( e ) {
var iframe = document.createElement( "iframe" );
iframe.style.display = "none";
iframe.setAttribute( "scrolling", "no" );
iframe.setAttribute( "id", "wpcom_remote_login_key" );
iframe.src = "https://r-login.wordpress.com/remote-login.php"
+ "?wpcom_remote_login=key"
+ "&origin=aHR0cHM6Ly9sdWN2YW5kb25rZXJzZ29lZC5jb20%3D"
+ "&wpcomid=221649942"
+ "&time=" + Math.floor( Date.now() / 1000 );
document.body.appendChild( iframe );
}, false );
</script>
<title>Making AWS News stupid fast with smart caching &#8211; Luc van Donkersgoed&#039;s Notes</title>
<link rel='dns-prefetch' href='//s0.wp.com' />
<link rel='dns-prefetch' href='//s2.wp.com' />
<link rel='dns-prefetch' href='//wordpress.com' />
<link rel='dns-prefetch' href='//s1.wp.com' />
<link rel="alternate" type="application/rss+xml" title="Luc van Donkersgoed&#039;s Notes &raquo; Feed" href="https://lucvandonkersgoed.com/feed/" />
<link rel="alternate" type="application/rss+xml" title="Luc van Donkersgoed&#039;s Notes &raquo; Comments Feed" href="https://lucvandonkersgoed.com/comments/feed/" />
<link rel="alternate" type="application/rss+xml" title="Luc van Donkersgoed&#039;s Notes &raquo; Making AWS News stupid fast with smart&nbsp;caching Comments Feed" href="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/feed/" />
<script type="text/javascript">
/* <![CDATA[ */
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function () {
oldonload();
func();
}
}
}
/* ]]> */
</script>
<style id="wp-img-auto-sizes-contain-inline-css">
img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px}
/*# sourceURL=wp-img-auto-sizes-contain-inline-css */
</style>
<link crossorigin='anonymous' rel='stylesheet' id='all-css-2-1' href='/_static/??-eJxtjEsKgDAMBS9kjbqwuBDPUtog9o9J8fpaEQSRBw8GhoEjC50iY2QIRWRf1i0SWOSstHsYQkr1TPFIsKNXjEbkRPyhVhM18J/0m8M3fFPVlzD3UnbTtWG0J2CTNNk=&cssminify=yes' type='text/css' media='all' />
<style id="wp-block-site-title-inline-css">
.wp-block-site-title{box-sizing:border-box}.wp-block-site-title :where(a){color:inherit;font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;text-decoration:inherit}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/site-title/style.min.css */
</style>
<style id="wp-block-page-list-inline-css">
.wp-block-navigation .wp-block-page-list{align-items:var(--navigation-layout-align,initial);background-color:inherit;display:flex;flex-direction:var(--navigation-layout-direction,initial);flex-wrap:var(--navigation-layout-wrap,wrap);justify-content:var(--navigation-layout-justify,initial)}.wp-block-navigation .wp-block-navigation-item{background-color:inherit}.wp-block-page-list{box-sizing:border-box}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/page-list/style.min.css */
</style>
<link crossorigin='anonymous' rel='stylesheet' id='all-css-6-1' href='/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/navigation/style.min.css?m=1788785546i&cssminify=yes' type='text/css' media='all' />
<style id="wp-block-group-inline-css">
.wp-block-group{box-sizing:border-box}:where(.wp-block-group.wp-block-group-is-layout-constrained){position:relative}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/group/style.min.css */
</style>
<style id="wp-block-post-featured-image-inline-css">
.wp-block-post-featured-image{margin-left:0;margin-right:0}.wp-block-post-featured-image a{display:block;height:100%}.wp-block-post-featured-image :where(img){box-sizing:border-box;height:auto;max-width:100%;vertical-align:bottom;width:100%}.wp-block-post-featured-image.alignfull img,.wp-block-post-featured-image.alignwide img{width:100%}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim{background-color:#000;inset:0;position:absolute}.wp-block-post-featured-image{position:relative}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-gradient{background-color:transparent}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-0{opacity:0}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-10{opacity:.1}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-20{opacity:.2}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-30{opacity:.3}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-40{opacity:.4}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-50{opacity:.5}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-60{opacity:.6}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-70{opacity:.7}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-80{opacity:.8}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-90{opacity:.9}.wp-block-post-featured-image .wp-block-post-featured-image__overlay.has-background-dim-100{opacity:1}.wp-block-post-featured-image:where(.alignleft,.alignright){width:100%}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/post-featured-image/style.min.css */
</style>
<style id="wp-block-post-title-inline-css">
.wp-block-post-title{box-sizing:border-box;word-break:break-word}.wp-block-post-title :where(a){display:inline-block;font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;line-height:inherit;text-decoration:inherit}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/post-title/style.min.css */
</style>
<style id="wp-block-paragraph-inline-css">
.is-small-text{font-size:.875em}.is-regular-text{font-size:1em}.is-large-text{font-size:2.25em}.is-larger-text{font-size:3em}.has-drop-cap:not(:focus):first-letter{float:left;font-size:8.4em;font-style:normal;font-weight:100;line-height:.68;margin:.05em .1em 0 0;text-transform:uppercase}body.rtl .has-drop-cap:not(:focus):first-letter{float:none;margin-left:.1em}p.has-drop-cap.has-background{overflow:hidden}:root :where(p.has-background){padding:1.25em 2.375em}:where(p.has-text-color:not(.has-link-color)) a{color:inherit}p.has-text-align-left[style*="writing-mode:vertical-lr"],p.has-text-align-right[style*="writing-mode:vertical-rl"]{rotate:180deg}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/paragraph/style.min.css */
</style>
<style id="wp-block-quote-inline-css">
.wp-block-quote{box-sizing:border-box;overflow-wrap:break-word}.wp-block-quote.is-large:where(:not(.is-style-plain)),.wp-block-quote.is-style-large:where(:not(.is-style-plain)){margin-bottom:1em;padding:0 1em}.wp-block-quote.is-large:where(:not(.is-style-plain)) p,.wp-block-quote.is-style-large:where(:not(.is-style-plain)) p{font-size:1.5em;font-style:italic;line-height:1.6}.wp-block-quote.is-large:where(:not(.is-style-plain)) cite,.wp-block-quote.is-large:where(:not(.is-style-plain)) footer,.wp-block-quote.is-style-large:where(:not(.is-style-plain)) cite,.wp-block-quote.is-style-large:where(:not(.is-style-plain)) footer{font-size:1.125em;text-align:right}.wp-block-quote>cite{display:block}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/quote/style.min.css */
</style>
<style id="wp-block-heading-inline-css">
h1:where(.wp-block-heading).has-background,h2:where(.wp-block-heading).has-background,h3:where(.wp-block-heading).has-background,h4:where(.wp-block-heading).has-background,h5:where(.wp-block-heading).has-background,h6:where(.wp-block-heading).has-background{padding:1.25em 2.375em}h1.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h1.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h2.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h2.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h3.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h3.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h4.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h4.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h5.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h5.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]),h6.has-text-align-left[style*=writing-mode]:where([style*=vertical-lr]),h6.has-text-align-right[style*=writing-mode]:where([style*=vertical-rl]){rotate:180deg}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/heading/style.min.css */
</style>
<style id="wp-block-list-inline-css">
ol,ul{box-sizing:border-box}:root :where(.wp-block-list.has-background){padding:1.25em 2.375em}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/list/style.min.css */
</style>
<style id="wp-block-image-inline-css">
.wp-block-image>a,.wp-block-image>figure>a{display:inline-block}.wp-block-image img{box-sizing:border-box;height:auto;max-width:100%;vertical-align:bottom}@media not (prefers-reduced-motion){.wp-block-image img.hide{visibility:hidden}.wp-block-image img.show{animation:show-content-image .4s}}.wp-block-image[style*=border-radius] img,.wp-block-image[style*=border-radius]>a{border-radius:inherit}.wp-block-image.has-custom-border img{box-sizing:border-box}.wp-block-image.aligncenter{text-align:center}.wp-block-image.alignfull>a,.wp-block-image.alignwide>a{width:100%}.wp-block-image.alignfull img,.wp-block-image.alignwide img{height:auto;width:100%}.wp-block-image .aligncenter,.wp-block-image .alignleft,.wp-block-image .alignright,.wp-block-image.aligncenter,.wp-block-image.alignleft,.wp-block-image.alignright{display:table}.wp-block-image .aligncenter>figcaption,.wp-block-image .alignleft>figcaption,.wp-block-image .alignright>figcaption,.wp-block-image.aligncenter>figcaption,.wp-block-image.alignleft>figcaption,.wp-block-image.alignright>figcaption{caption-side:bottom;display:table-caption}.wp-block-image .alignleft{float:left;margin:.5em 1em .5em 0}.wp-block-image .alignright{float:right;margin:.5em 0 .5em 1em}.wp-block-image .aligncenter{margin-left:auto;margin-right:auto}.wp-block-image :where(figcaption){margin-bottom:1em;margin-top:.5em}.wp-block-image.is-style-circle-mask img{border-radius:9999px}@supports ((-webkit-mask-image:none) or (mask-image:none)) or (-webkit-mask-image:none){.wp-block-image.is-style-circle-mask img{border-radius:0;-webkit-mask-image:url('data:image/svg+xml;utf8,<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50"/></svg>');mask-image:url('data:image/svg+xml;utf8,<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="50"/></svg>');mask-mode:alpha;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}}:root :where(.wp-block-image.is-style-rounded img,.wp-block-image .is-style-rounded img){border-radius:9999px}.wp-block-image figure{margin:0}.wp-lightbox-container{display:flex;flex-direction:column;position:relative}.wp-lightbox-container img{cursor:zoom-in}.wp-lightbox-container img:hover+button{opacity:1}.wp-lightbox-container button{align-items:center;backdrop-filter:blur(16px) saturate(180%);background-color:rgba(90,90,90,.25);border:none;border-radius:4px;cursor:zoom-in;display:flex;height:20px;justify-content:center;opacity:0;padding:0;position:absolute;right:16px;text-align:center;top:16px;width:20px;z-index:100}@media not (prefers-reduced-motion){.wp-lightbox-container button{transition:opacity .2s ease}}.wp-lightbox-container button:focus-visible{outline:3px auto rgba(90,90,90,.25);outline:3px auto -webkit-focus-ring-color;outline-offset:3px}.wp-lightbox-container button:hover{cursor:pointer;opacity:1}.wp-lightbox-container button:focus{opacity:1}.wp-lightbox-container button:focus,.wp-lightbox-container button:hover,.wp-lightbox-container button:not(:hover):not(:active):not(.has-background){background-color:rgba(90,90,90,.25);border:none}.wp-lightbox-overlay{box-sizing:border-box;cursor:zoom-out;height:100vh;left:0;overflow:hidden;position:fixed;top:0;visibility:hidden;width:100%;z-index:100000}.wp-lightbox-overlay .wp-lightbox-close-button{align-items:center;cursor:pointer;display:flex;font-family:inherit;gap:8px;justify-content:center;line-height:1;min-height:40px;min-width:40px;padding:0 4px;position:absolute;right:calc(env(safe-area-inset-right) + 16px);top:calc(env(safe-area-inset-top) + 16px);z-index:5000000}.wp-lightbox-overlay .wp-lightbox-close-button:focus,.wp-lightbox-overlay .wp-lightbox-close-button:hover,.wp-lightbox-overlay .wp-lightbox-close-button:not(:hover):not(:active):not(.has-background){background:none;border:none}.wp-lightbox-overlay .wp-lightbox-close-button:has(.wp-lightbox-close-text:not([hidden])) .wp-lightbox-close-icon svg{height:1em;width:1em}.wp-lightbox-overlay .wp-lightbox-close-icon svg{display:block}.wp-lightbox-overlay .wp-lightbox-navigation-button-next,.wp-lightbox-overlay .wp-lightbox-navigation-button-prev{align-items:center;bottom:16px;cursor:pointer;display:flex;font-family:inherit;gap:4px;justify-content:center;line-height:1;min-height:40px;min-width:40px;padding:0 8px;position:absolute;z-index:2000002}.wp-lightbox-overlay .wp-lightbox-navigation-button-next[hidden],.wp-lightbox-overlay .wp-lightbox-navigation-button-prev[hidden]{display:none}@media (min-width:960px){.wp-lightbox-overlay .wp-lightbox-navigation-button-next,.wp-lightbox-overlay .wp-lightbox-navigation-button-prev{bottom:50%;transform:translateY(-50%)}}.wp-lightbox-overlay .wp-lightbox-navigation-button-next:focus,.wp-lightbox-overlay .wp-lightbox-navigation-button-next:hover,.wp-lightbox-overlay .wp-lightbox-navigation-button-next:not(:hover):not(:active):not(.has-background),.wp-lightbox-overlay .wp-lightbox-navigation-button-prev:focus,.wp-lightbox-overlay .wp-lightbox-navigation-button-prev:hover,.wp-lightbox-overlay .wp-lightbox-navigation-button-prev:not(:hover):not(:active):not(.has-background){background:none;border:none;padding:0 8px}.wp-lightbox-overlay .wp-lightbox-navigation-button-next:has(.wp-lightbox-navigation-text:not([hidden])) .wp-lightbox-navigation-icon svg,.wp-lightbox-overlay .wp-lightbox-navigation-button-prev:has(.wp-lightbox-navigation-text:not([hidden])) .wp-lightbox-navigation-icon svg{display:block;height:1.5em;width:1.5em}.wp-lightbox-overlay .wp-lightbox-navigation-button-prev{left:calc(env(safe-area-inset-left) + 16px)}.wp-lightbox-overlay .wp-lightbox-navigation-button-next{right:calc(env(safe-area-inset-right) + 16px)}.wp-lightbox-overlay .wp-lightbox-navigation-icon svg{vertical-align:middle}.wp-lightbox-overlay .lightbox-image-container{height:var(--wp--lightbox-container-height);left:50%;overflow:hidden;position:absolute;top:50%;transform:translate(-50%,-50%);transform-origin:top left;width:var(--wp--lightbox-container-width);z-index:2000001}.wp-lightbox-overlay .wp-block-image{align-items:center;box-sizing:border-box;display:flex;height:100%;justify-content:center;margin:0;position:relative;transform-origin:0 0;width:100%;z-index:3000000}.wp-lightbox-overlay .wp-block-image img{height:var(--wp--lightbox-image-height);min-height:var(--wp--lightbox-image-height);min-width:var(--wp--lightbox-image-width);width:var(--wp--lightbox-image-width)}.wp-lightbox-overlay .wp-block-image figcaption{display:none}.wp-lightbox-overlay button{background:none;border:none}.wp-lightbox-overlay .scrim{background-color:#fff;height:100%;opacity:.9;position:absolute;width:100%;z-index:2000000}.wp-lightbox-overlay.active{visibility:visible}@media not (prefers-reduced-motion){.wp-lightbox-overlay.active{animation:turn-on-visibility .25s both}.wp-lightbox-overlay.active img{animation:turn-on-visibility .35s both}.wp-lightbox-overlay.show-closing-animation:not(.active){animation:turn-off-visibility .35s both}.wp-lightbox-overlay.show-closing-animation:not(.active) img{animation:turn-off-visibility .25s both}.wp-lightbox-overlay.zoom.active{animation:none;opacity:1;visibility:visible}.wp-lightbox-overlay.zoom.active .lightbox-image-container{animation:lightbox-zoom-in .4s}.wp-lightbox-overlay.zoom.active .lightbox-image-container img{animation:none}.wp-lightbox-overlay.zoom.active .scrim{animation:turn-on-visibility .4s forwards}.wp-lightbox-overlay.zoom.show-closing-animation:not(.active){animation:none}.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container{animation:lightbox-zoom-out .4s}.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container img{animation:none}.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .scrim{animation:turn-off-visibility .4s forwards}}@keyframes show-content-image{0%{visibility:hidden}99%{visibility:hidden}to{visibility:visible}}@keyframes turn-on-visibility{0%{opacity:0}to{opacity:1}}@keyframes turn-off-visibility{0%{opacity:1;visibility:visible}99%{opacity:0;visibility:visible}to{opacity:0;visibility:hidden}}@keyframes lightbox-zoom-in{0%{transform:translate(calc((-100vw + var(--wp--lightbox-scrollbar-width))/2 + var(--wp--lightbox-initial-left-position)),calc(-50vh + var(--wp--lightbox-initial-top-position))) scale(var(--wp--lightbox-scale))}to{transform:translate(-50%,-50%) scale(1)}}@keyframes lightbox-zoom-out{0%{transform:translate(-50%,-50%) scale(1);visibility:visible}99%{visibility:visible}to{transform:translate(calc((-100vw + var(--wp--lightbox-scrollbar-width))/2 + var(--wp--lightbox-initial-left-position)),calc(-50vh + var(--wp--lightbox-initial-top-position))) scale(var(--wp--lightbox-scale));visibility:hidden}}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/image/style.min.css */
</style>
<style id="videopress-video-view-style-inline-css">
.wp-block-jetpack-videopress{position:relative}:is(.wp-block-jetpack-videopress.jetpack-videopress-player.alignleft,.wp-block-jetpack-videopress.jetpack-videopress-player.alignright)~.wp-block-jetpack-videopress.jetpack-videopress-player{clear:both}.wp-block-jetpack-videopress figcaption{color:#555;font-size:13px;margin-bottom:1em;margin-top:.5em;text-align:center}.is-dark-theme .wp-block-jetpack-videopress figcaption{color:#ffffffa6}.wp-block-jetpack-videopress .jetpack-videopress-player__wrapper{line-height:0;position:relative}.wp-block-jetpack-videopress .jetpack-videopress-player__overlay{cursor:pointer;height:100%;left:0;opacity:1;position:absolute;top:0;transition:opacity .3s ease-in-out;width:100%}.wp-block-jetpack-videopress .jetpack-videopress-player__overlay:hover{opacity:0}.wp-block-jetpack-videopress.wp-block-jetpack-videopress--has-max-width{margin:auto}.is-layout-flex .wp-block-jetpack-videopress.wp-block-jetpack-videopress--has-max-width{margin:0}
/*# sourceURL=/wp-content/mu-plugins/jetpack-plugin/moon/jetpack_vendor/automattic/jetpack-videopress/build/block-editor/blocks/video/view.css */
</style>
<link crossorigin='anonymous' rel='stylesheet' id='all-css-30-1' href='/_static/??-eJyNjMEKhDAMBX9IfaiIXsRPWdxskGqbFNPi7y+CevY4wzA4YkkqiSUh5DL6vDgxrJziTNvFCKqCjxPC1yttBjtc5L0iswLvD0F/2bOB5l2zsX+iW5zDKYx1P3RN07b1sP4BKPs7aw==&cssminify=yes' type='text/css' media='all' />
<style id="wp-block-post-content-inline-css">
.wp-block-post-content{display:flow-root}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/post-content/style.min.css */
</style>
<style id="wp-block-spacer-inline-css">
.wp-block-spacer{clear:both}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/spacer/style.min.css */
</style>
<style id="wp-block-separator-inline-css">
@charset "UTF-8";.wp-block-separator{border:none;border-top:2px solid}:root :where(.wp-block-separator.is-style-dots){height:auto;line-height:1;text-align:center}:root :where(.wp-block-separator.is-style-dots):before{color:currentColor;content:"···";font-family:serif;font-size:1.5em;letter-spacing:2em;padding-left:2em}.wp-block-separator.is-style-dots{background:none!important;border:none!important}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/separator/style.min.css */
</style>
<style id="wp-block-post-date-inline-css">
.wp-block-post-date{box-sizing:border-box}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/post-date/style.min.css */
</style>
<style id="wp-block-post-terms-inline-css">
.wp-block-post-terms{box-sizing:border-box}.wp-block-post-terms .wp-block-post-terms__separator{white-space:pre-wrap}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/post-terms/style.min.css */
</style>
<style id="wp-block-columns-inline-css">
.wp-block-columns{box-sizing:border-box;display:flex;flex-wrap:wrap!important}@media (min-width:782px){.wp-block-columns{flex-wrap:nowrap!important}}.wp-block-columns{align-items:normal!important}.wp-block-columns.are-vertically-aligned-top{align-items:flex-start}.wp-block-columns.are-vertically-aligned-center{align-items:center}.wp-block-columns.are-vertically-aligned-bottom{align-items:flex-end}@media (max-width:781px){.wp-block-columns:not(.is-not-stacked-on-mobile)>.wp-block-column{flex-basis:100%!important}}@media (min-width:782px){.wp-block-columns:not(.is-not-stacked-on-mobile)>.wp-block-column{flex-basis:0;flex-grow:1}.wp-block-columns:not(.is-not-stacked-on-mobile)>.wp-block-column[style*=flex-basis]{flex-grow:0}}.wp-block-columns.is-not-stacked-on-mobile{flex-wrap:nowrap!important}.wp-block-columns.is-not-stacked-on-mobile>.wp-block-column{flex-basis:0;flex-grow:1}.wp-block-columns.is-not-stacked-on-mobile>.wp-block-column[style*=flex-basis]{flex-grow:0}:where(.wp-block-columns){margin-bottom:1.75em}:where(.wp-block-columns.has-background){padding:1.25em 2.375em}.wp-block-column{flex-grow:1;min-width:0;overflow-wrap:break-word;word-break:break-word}.wp-block-column.is-vertically-aligned-top{align-self:flex-start}.wp-block-column.is-vertically-aligned-center{align-self:center}.wp-block-column.is-vertically-aligned-bottom{align-self:flex-end}.wp-block-column.is-vertically-aligned-stretch{align-self:stretch}.wp-block-column.is-vertically-aligned-bottom,.wp-block-column.is-vertically-aligned-center,.wp-block-column.is-vertically-aligned-top{width:100%}
/*# sourceURL=/wp-content/plugins/gutenberg-core/v23.9.1/build/styles/block-library/columns/style.min.css */
</style>
<style id="wp-emoji-styles-inline-css">
img.wp-smiley, img.emoji {
display: inline !important;
border: none !important;
box-shadow: none !important;
height: 1em !important;
width: 1em !important;
margin: 0 0.07em !important;
vertical-align: -0.1em !important;
background: none !important;
padding: 0 !important;
}
/*# sourceURL=wp-emoji-styles-inline-css */
</style>
<style id="wp-block-library-inline-css">
:root{--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color);--wp-editor-canvas-background:#ddd;--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,160.5;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-element-button{cursor:pointer}:root .has-very-light-gray-background-color{background-color:#eee}:root .has-very-dark-gray-background-color{background-color:#313131}:root .has-very-light-gray-color{color:#eee}:root .has-very-dark-gray-color{color:#313131}:root .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background{background:linear-gradient(135deg,#00d084,#0693e3)}:root .has-purple-crush-gradient-background{background:linear-gradient(135deg,#34e2e4,#4721fb 50%,#ab1dfe)}:root .has-hazy-dawn-gradient-background{background:linear-gradient(135deg,#faaca8,#dad0ec)}:root .has-subdued-olive-gradient-background{background:linear-gradient(135deg,#fafae1,#67a671)}:root .has-atomic-cream-gradient-background{background:linear-gradient(135deg,#fdd79a,#004a59)}:root .has-nightshade-gradient-background{background:linear-gradient(135deg,#330968,#31cdcf)}:root .has-midnight-gradient-background{background:linear-gradient(135deg,#020381,#2874fc)}:root{--wp--preset--font-size--normal:16px;--wp--preset--font-size--huge:42px}.has-regular-font-size{font-size:1em}.has-larger-font-size{font-size:2.625em}.has-normal-font-size{font-size:var(--wp--preset--font-size--normal)}.has-huge-font-size{font-size:var(--wp--preset--font-size--huge)}:root .has-text-align-center{text-align:center}:root .has-text-align-left{text-align:left}:root .has-text-align-right{text-align:right}.has-fit-text{white-space:nowrap!important}#end-resizable-editor-section{display:none}.aligncenter{clear:both}.items-justified-left{justify-content:flex-start}.items-justified-center{justify-content:center}.items-justified-right{justify-content:flex-end}.items-justified-space-between{justify-content:space-between}.screen-reader-text{word-wrap:normal!important;border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-break:normal!important}.screen-reader-text:focus{background-color:#ddd;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}html :where(.has-border-color){border-style:solid}html :where([style^=border-color],[style*=";border-color"],[style*="; border-color"]){border-style:solid}html :where([style^=border-top-color],[style*=";border-top-color"],[style*="; border-top-color"]){border-top-style:solid}html :where([style^=border-right-color],[style*=";border-right-color"],[style*="; border-right-color"]){border-right-style:solid}html :where([style^=border-bottom-color],[style*=";border-bottom-color"],[style*="; border-bottom-color"]){border-bottom-style:solid}html :where([style^=border-left-color],[style*=";border-left-color"],[style*="; border-left-color"]){border-left-style:solid}html :where([style^=border-width],[style*=";border-width"],[style*="; border-width"]){border-style:solid}html :where([style^=border-top-width],[style*=";border-top-width"],[style*="; border-top-width"]){border-top-style:solid}html :where([style^=border-right-width],[style*=";border-right-width"],[style*="; border-right-width"]){border-right-style:solid}html :where([style^=border-bottom-width],[style*=";border-bottom-width"],[style*="; border-bottom-width"]){border-bottom-style:solid}html :where([style^=border-left-width],[style*=";border-left-width"],[style*="; border-left-width"]){border-left-style:solid}html :where(img[class*=wp-image-]){height:auto;max-width:100%}:where(figure){margin:0 0 1em}html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:var(--wp-admin--admin-bar--height,0px)}@media screen and (max-width:600px){html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:0px}}
.has-text-align-justify {
text-align:justify;
}
.has-text-align-justify{text-align:justify;}
/*# sourceURL=wp-block-library-inline-css */
</style>
<style id="wp-block-template-skip-link-inline-css">
/*! This file is auto-generated */
.skip-link.screen-reader-text{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute!important;width:1px;word-wrap:normal!important;word-break:normal!important}.skip-link.screen-reader-text:focus{background-color:#eee;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}
/*# sourceURL=/wp-includes/css/wp-block-template-skip-link.min.css */
</style>
<link crossorigin='anonymous' rel='stylesheet' id='all-css-50-1' href='/_static/??/wp-content/mu-plugins/core-compat/wp-mediaelement.css,/wp-content/mu-plugins/wpcom-bbpress-premium-themes.css?m=1432920480j&cssminify=yes' type='text/css' media='all' />
<style id="global-styles-inline-css">
:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--base: #ffffff;--wp--preset--color--contrast: #000000;--wp--preset--color--primary: #9DFF20;--wp--preset--color--secondary: #345C00;--wp--preset--color--tertiary: #F6F6F6;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.227), 1rem);--wp--preset--font-size--medium: clamp(1rem, 1rem + ((1vw - 0.2rem) * 0.227), 1.125rem);--wp--preset--font-size--large: clamp(1.75rem, 1.75rem + ((1vw - 0.2rem) * 0.227), 1.875rem);--wp--preset--font-size--x-large: 2.25rem;--wp--preset--font-family--albert-sans: 'Albert Sans';--wp--preset--font-family--alegreya: Alegreya;--wp--preset--font-family--arvo: Arvo;--wp--preset--font-family--bodoni-moda: 'Bodoni Moda';--wp--preset--font-family--bricolage-grotesque: 'Bricolage Grotesque', sans-serif;--wp--preset--font-family--cabin: Cabin;--wp--preset--font-family--chivo: Chivo;--wp--preset--font-family--commissioner: Commissioner;--wp--preset--font-family--cormorant: Cormorant;--wp--preset--font-family--courier-prime: 'Courier Prime';--wp--preset--font-family--crimson-pro: 'Crimson Pro';--wp--preset--font-family--dm-mono: 'DM Mono';--wp--preset--font-family--dm-sans: "DM Sans", sans-serif;--wp--preset--font-family--dm-serif-display: 'DM Serif Display', serif;--wp--preset--font-family--domine: Domine;--wp--preset--font-family--eb-garamond: 'EB Garamond';--wp--preset--font-family--epilogue: Epilogue;--wp--preset--font-family--fahkwang: Fahkwang, sans-serif;--wp--preset--font-family--figtree: Figtree;--wp--preset--font-family--fira-sans: 'Fira Sans';--wp--preset--font-family--fjalla-one: 'Fjalla One', sans-serif;--wp--preset--font-family--fraunces: Fraunces;--wp--preset--font-family--gabarito: Gabarito, system-ui;--wp--preset--font-family--ibm-plex-mono: 'IBM Plex Mono', monospace;--wp--preset--font-family--ibm-plex-sans: 'IBM Plex Sans';--wp--preset--font-family--ibarra-real-nova: 'Ibarra Real Nova', serif;--wp--preset--font-family--instrument-serif: 'Instrument Serif', serif;--wp--preset--font-family--inter: "Inter", sans-serif;--wp--preset--font-family--josefin-sans: 'Josefin Sans';--wp--preset--font-family--jost: Jost;--wp--preset--font-family--libre-baskerville: 'Libre Baskerville';--wp--preset--font-family--libre-franklin: 'Libre Franklin';--wp--preset--font-family--literata: Literata;--wp--preset--font-family--lora: Lora;--wp--preset--font-family--merriweather: Merriweather;--wp--preset--font-family--montserrat: Montserrat;--wp--preset--font-family--newsreader: Newsreader;--wp--preset--font-family--noto-sans-mono: 'Noto Sans Mono', sans-serif;--wp--preset--font-family--nunito: Nunito;--wp--preset--font-family--open-sans: 'Open Sans';--wp--preset--font-family--overpass: Overpass;--wp--preset--font-family--pt-serif: 'PT Serif', serif;--wp--preset--font-family--petrona: Petrona;--wp--preset--font-family--piazzolla: Piazzolla;--wp--preset--font-family--playfair-display: 'Playfair Display';--wp--preset--font-family--plus-jakarta-sans: 'Plus Jakarta Sans';--wp--preset--font-family--poppins: Poppins;--wp--preset--font-family--raleway: Raleway;--wp--preset--font-family--roboto: Roboto;--wp--preset--font-family--roboto-slab: 'Roboto Slab';--wp--preset--font-family--rubik: Rubik;--wp--preset--font-family--rufina: Rufina, serif;--wp--preset--font-family--sora: Sora;--wp--preset--font-family--source-sans-3: 'Source Sans 3', sans-serif;--wp--preset--font-family--source-serif-4: 'Source Serif 4', serif;--wp--preset--font-family--space-mono: 'Space Mono';--wp--preset--font-family--syne: Syne, sans-serif;--wp--preset--font-family--texturina: Texturina;--wp--preset--font-family--urbanist: Urbanist, sans-serif;--wp--preset--font-family--work-sans: 'Work Sans';--wp--preset--font-family--system-font: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;--wp--preset--font-family--source-serif-pro: "Source Serif Pro", serif;--wp--preset--font-family--source-sans-pro: 'Source Sans Pro';--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: clamp(1.5rem, 5vw, 2rem);--wp--preset--spacing--40: clamp(1.8rem, 1.8rem + ((1vw - 0.48rem) * 2.885), 3rem);--wp--preset--spacing--50: clamp(2.5rem, 8vw, 4.5rem);--wp--preset--spacing--60: clamp(3.75rem, 10vw, 7rem);--wp--preset--spacing--70: clamp(5rem, 5.25rem + ((1vw - 0.48rem) * 9.096), 8rem);--wp--preset--spacing--80: clamp(7rem, 14vw, 11rem);--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}.wp-block-button{--wp--preset--dimension--25: 25%;--wp--preset--dimension--50: 50%;--wp--preset--dimension--75: 75%;--wp--preset--dimension--100: 100%;}.wp-block-code{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--base: #ffffff;--wp--preset--color--contrast: #000000;--wp--preset--color--primary: #9DFF20;--wp--preset--color--secondary: #345C00;--wp--preset--color--tertiary: #F6F6F6;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: clamp(0.875rem, 0.875rem + ((1vw - 0.2rem) * 0.227), 1rem);--wp--preset--font-size--medium: clamp(1rem, 1rem + ((1vw - 0.2rem) * 0.227), 1.125rem);--wp--preset--font-size--large: clamp(1.75rem, 1.75rem + ((1vw - 0.2rem) * 0.227), 1.875rem);--wp--preset--font-size--x-large: 2.25rem;--wp--preset--font-family--dm-sans: "DM Sans", sans-serif;--wp--preset--font-family--ibm-plex-mono: 'IBM Plex Mono', monospace;--wp--preset--font-family--inter: "Inter", sans-serif;--wp--preset--font-family--system-font: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;--wp--preset--font-family--source-serif-pro: "Source Serif Pro", serif;--wp--preset--font-family--albert-sans: 'Albert Sans';--wp--preset--font-family--alegreya: Alegreya;--wp--preset--font-family--arvo: Arvo;--wp--preset--font-family--bodoni-moda: 'Bodoni Moda';--wp--preset--font-family--cabin: Cabin;--wp--preset--font-family--chivo: Chivo;--wp--preset--font-family--commissioner: Commissioner;--wp--preset--font-family--cormorant: Cormorant;--wp--preset--font-family--courier-prime: 'Courier Prime';--wp--preset--font-family--crimson-pro: 'Crimson Pro';--wp--preset--font-family--dm-mono: 'DM Mono';--wp--preset--font-family--domine: Domine;--wp--preset--font-family--eb-garamond: 'EB Garamond';--wp--preset--font-family--epilogue: Epilogue;--wp--preset--font-family--figtree: Figtree;--wp--preset--font-family--fira-sans: 'Fira Sans';--wp--preset--font-family--fraunces: Fraunces;--wp--preset--font-family--ibm-plex-sans: 'IBM Plex Sans';--wp--preset--font-family--josefin-sans: 'Josefin Sans';--wp--preset--font-family--jost: Jost;--wp--preset--font-family--libre-baskerville: 'Libre Baskerville';--wp--preset--font-family--libre-franklin: 'Libre Franklin';--wp--preset--font-family--literata: Literata;--wp--preset--font-family--lora: Lora;--wp--preset--font-family--merriweather: Merriweather;--wp--preset--font-family--montserrat: Montserrat;--wp--preset--font-family--newsreader: Newsreader;--wp--preset--font-family--nunito: Nunito;--wp--preset--font-family--open-sans: 'Open Sans';--wp--preset--font-family--overpass: Overpass;--wp--preset--font-family--petrona: Petrona;--wp--preset--font-family--piazzolla: Piazzolla;--wp--preset--font-family--playfair-display: 'Playfair Display';--wp--preset--font-family--plus-jakarta-sans: 'Plus Jakarta Sans';--wp--preset--font-family--poppins: Poppins;--wp--preset--font-family--raleway: Raleway;--wp--preset--font-family--roboto-slab: 'Roboto Slab';--wp--preset--font-family--roboto: Roboto;--wp--preset--font-family--rubik: Rubik;--wp--preset--font-family--sora: Sora;--wp--preset--font-family--source-sans-pro: 'Source Sans Pro';--wp--preset--font-family--space-mono: 'Space Mono';--wp--preset--font-family--texturina: Texturina;--wp--preset--font-family--work-sans: 'Work Sans';--wp--preset--spacing--30: clamp(1.5rem, 5vw, 2rem);--wp--preset--spacing--40: clamp(1.8rem, 1.8rem + ((1vw - 0.48rem) * 2.885), 3rem);--wp--preset--spacing--50: clamp(2.5rem, 8vw, 4.5rem);--wp--preset--spacing--60: clamp(3.75rem, 10vw, 7rem);--wp--preset--spacing--70: clamp(5rem, 5.25rem + ((1vw - 0.48rem) * 9.096), 8rem);--wp--preset--spacing--80: clamp(7rem, 14vw, 11rem);--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:root { --wp--style--global--content-size: 700px;--wp--style--global--wide-size: 1200px; }:where(body) { margin: 0; }.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }.has-global-padding { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.has-global-padding > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) { padding-right: 0; padding-left: 0; }.has-global-padding :where(:not(.alignfull.is-layout-flow) > .has-global-padding:not(.wp-block-block, .alignfull)) > .alignfull { margin-left: 0; margin-right: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.wp-site-blocks) > * { margin-block-start: 1.5rem; margin-block-end: 0; }:where(.wp-site-blocks) > :first-child { margin-block-start: 0; }:where(.wp-site-blocks) > :last-child { margin-block-end: 0; }:root { --wp--style--block-gap: 1.5rem; }:root :where(.is-layout-flow) > :first-child{margin-block-start: 0;}:root :where(.is-layout-flow) > :last-child{margin-block-end: 0;}:root :where(.is-layout-flow) > *{margin-block-start: 1.5rem;margin-block-end: 0;}:root :where(.is-layout-constrained) > :first-child{margin-block-start: 0;}:root :where(.is-layout-constrained) > :last-child{margin-block-end: 0;}:root :where(.is-layout-constrained) > *{margin-block-start: 1.5rem;margin-block-end: 0;}:root :where(.is-layout-flex){gap: 1.5rem;}:root :where(.is-layout-grid){gap: 1.5rem;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{background-color: var(--wp--preset--color--base);color: var(--wp--preset--color--contrast);font-family: var(--wp--preset--font-family--system-font);font-size: var(--wp--preset--font-size--medium);line-height: 1.6;--wp--style--root--padding-top: var(--wp--preset--spacing--40);--wp--style--root--padding-right: var(--wp--preset--spacing--30);--wp--style--root--padding-bottom: var(--wp--preset--spacing--40);--wp--style--root--padding-left: var(--wp--preset--spacing--30);}a:where(:not(.wp-element-button)){color: var(--wp--preset--color--contrast);text-decoration: underline;}:root :where(a:where(:not(.wp-element-button)):hover){text-decoration: none;}:root :where(a:where(:not(.wp-element-button)):focus){text-decoration: underline dashed;}:root :where(a:where(:not(.wp-element-button)):active){color: var(--wp--preset--color--secondary);text-decoration: none;}h1, h2, h3, h4, h5, h6{font-weight: 400;line-height: 1.4;}h1{font-size: clamp(2.032rem, 2.032rem + ((1vw - 0.2rem) * 2.896), 3.625rem);line-height: 1.2;}h2{font-size: clamp(1.502rem, 1.502rem + ((1vw - 0.2rem) * 1.815), 2.5rem);line-height: 1.2;}h3{font-size: clamp(1.378rem, 1.378rem + ((1vw - 0.2rem) * 1.585), 2.25rem);}h4{font-size: var(--wp--preset--font-size--large);}h5{font-size: var(--wp--preset--font-size--medium);font-weight: 700;text-transform: uppercase;}h6{font-size: var(--wp--preset--font-size--medium);text-transform: uppercase;}:root :where(.wp-element-button, .wp-block-button__link){background-color: var(--wp--preset--color--primary);border-radius: 0;border-width: 0;color: var(--wp--preset--color--contrast);font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;letter-spacing: inherit;line-height: inherit;padding-top: calc(0.667em + 2px);padding-right: calc(1.333em + 2px);padding-bottom: calc(0.667em + 2px);padding-left: calc(1.333em + 2px);text-decoration: none;text-transform: inherit;}:root :where(.wp-element-button:visited, .wp-block-button__link:visited){color: var(--wp--preset--color--contrast);}:root :where(.wp-element-button:hover, .wp-block-button__link:hover){background-color: var(--wp--preset--color--contrast);color: var(--wp--preset--color--base);}:root :where(.wp-element-button:focus, .wp-block-button__link:focus){background-color: var(--wp--preset--color--contrast);color: var(--wp--preset--color--base);}:root :where(.wp-element-button:active, .wp-block-button__link:active){background-color: var(--wp--preset--color--secondary);color: var(--wp--preset--color--base);}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-base-color{color: var(--wp--preset--color--base) !important;}.has-contrast-color{color: var(--wp--preset--color--contrast) !important;}.has-primary-color{color: var(--wp--preset--color--primary) !important;}.has-secondary-color{color: var(--wp--preset--color--secondary) !important;}.has-tertiary-color{color: var(--wp--preset--color--tertiary) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-base-background-color{background-color: var(--wp--preset--color--base) !important;}.has-contrast-background-color{background-color: var(--wp--preset--color--contrast) !important;}.has-primary-background-color{background-color: var(--wp--preset--color--primary) !important;}.has-secondary-background-color{background-color: var(--wp--preset--color--secondary) !important;}.has-tertiary-background-color{background-color: var(--wp--preset--color--tertiary) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-base-border-color{border-color: var(--wp--preset--color--base) !important;}.has-contrast-border-color{border-color: var(--wp--preset--color--contrast) !important;}.has-primary-border-color{border-color: var(--wp--preset--color--primary) !important;}.has-secondary-border-color{border-color: var(--wp--preset--color--secondary) !important;}.has-tertiary-border-color{border-color: var(--wp--preset--color--tertiary) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-albert-sans-font-family{font-family: var(--wp--preset--font-family--albert-sans) !important;}.has-alegreya-font-family{font-family: var(--wp--preset--font-family--alegreya) !important;}.has-arvo-font-family{font-family: var(--wp--preset--font-family--arvo) !important;}.has-bodoni-moda-font-family{font-family: var(--wp--preset--font-family--bodoni-moda) !important;}.has-bricolage-grotesque-font-family{font-family: var(--wp--preset--font-family--bricolage-grotesque) !important;}.has-cabin-font-family{font-family: var(--wp--preset--font-family--cabin) !important;}.has-chivo-font-family{font-family: var(--wp--preset--font-family--chivo) !important;}.has-commissioner-font-family{font-family: var(--wp--preset--font-family--commissioner) !important;}.has-cormorant-font-family{font-family: var(--wp--preset--font-family--cormorant) !important;}.has-courier-prime-font-family{font-family: var(--wp--preset--font-family--courier-prime) !important;}.has-crimson-pro-font-family{font-family: var(--wp--preset--font-family--crimson-pro) !important;}.has-dm-mono-font-family{font-family: var(--wp--preset--font-family--dm-mono) !important;}.has-dm-sans-font-family{font-family: var(--wp--preset--font-family--dm-sans) !important;}.has-dm-serif-display-font-family{font-family: var(--wp--preset--font-family--dm-serif-display) !important;}.has-domine-font-family{font-family: var(--wp--preset--font-family--domine) !important;}.has-eb-garamond-font-family{font-family: var(--wp--preset--font-family--eb-garamond) !important;}.has-epilogue-font-family{font-family: var(--wp--preset--font-family--epilogue) !important;}.has-fahkwang-font-family{font-family: var(--wp--preset--font-family--fahkwang) !important;}.has-figtree-font-family{font-family: var(--wp--preset--font-family--figtree) !important;}.has-fira-sans-font-family{font-family: var(--wp--preset--font-family--fira-sans) !important;}.has-fjalla-one-font-family{font-family: var(--wp--preset--font-family--fjalla-one) !important;}.has-fraunces-font-family{font-family: var(--wp--preset--font-family--fraunces) !important;}.has-gabarito-font-family{font-family: var(--wp--preset--font-family--gabarito) !important;}.has-ibm-plex-mono-font-family{font-family: var(--wp--preset--font-family--ibm-plex-mono) !important;}.has-ibm-plex-sans-font-family{font-family: var(--wp--preset--font-family--ibm-plex-sans) !important;}.has-ibarra-real-nova-font-family{font-family: var(--wp--preset--font-family--ibarra-real-nova) !important;}.has-instrument-serif-font-family{font-family: var(--wp--preset--font-family--instrument-serif) !important;}.has-inter-font-family{font-family: var(--wp--preset--font-family--inter) !important;}.has-josefin-sans-font-family{font-family: var(--wp--preset--font-family--josefin-sans) !important;}.has-jost-font-family{font-family: var(--wp--preset--font-family--jost) !important;}.has-libre-baskerville-font-family{font-family: var(--wp--preset--font-family--libre-baskerville) !important;}.has-libre-franklin-font-family{font-family: var(--wp--preset--font-family--libre-franklin) !important;}.has-literata-font-family{font-family: var(--wp--preset--font-family--literata) !important;}.has-lora-font-family{font-family: var(--wp--preset--font-family--lora) !important;}.has-merriweather-font-family{font-family: var(--wp--preset--font-family--merriweather) !important;}.has-montserrat-font-family{font-family: var(--wp--preset--font-family--montserrat) !important;}.has-newsreader-font-family{font-family: var(--wp--preset--font-family--newsreader) !important;}.has-noto-sans-mono-font-family{font-family: var(--wp--preset--font-family--noto-sans-mono) !important;}.has-nunito-font-family{font-family: var(--wp--preset--font-family--nunito) !important;}.has-open-sans-font-family{font-family: var(--wp--preset--font-family--open-sans) !important;}.has-overpass-font-family{font-family: var(--wp--preset--font-family--overpass) !important;}.has-pt-serif-font-family{font-family: var(--wp--preset--font-family--pt-serif) !important;}.has-petrona-font-family{font-family: var(--wp--preset--font-family--petrona) !important;}.has-piazzolla-font-family{font-family: var(--wp--preset--font-family--piazzolla) !important;}.has-playfair-display-font-family{font-family: var(--wp--preset--font-family--playfair-display) !important;}.has-plus-jakarta-sans-font-family{font-family: var(--wp--preset--font-family--plus-jakarta-sans) !important;}.has-poppins-font-family{font-family: var(--wp--preset--font-family--poppins) !important;}.has-raleway-font-family{font-family: var(--wp--preset--font-family--raleway) !important;}.has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}.has-roboto-slab-font-family{font-family: var(--wp--preset--font-family--roboto-slab) !important;}.has-rubik-font-family{font-family: var(--wp--preset--font-family--rubik) !important;}.has-rufina-font-family{font-family: var(--wp--preset--font-family--rufina) !important;}.has-sora-font-family{font-family: var(--wp--preset--font-family--sora) !important;}.has-source-sans-3-font-family{font-family: var(--wp--preset--font-family--source-sans-3) !important;}.has-source-serif-4-font-family{font-family: var(--wp--preset--font-family--source-serif-4) !important;}.has-space-mono-font-family{font-family: var(--wp--preset--font-family--space-mono) !important;}.has-syne-font-family{font-family: var(--wp--preset--font-family--syne) !important;}.has-texturina-font-family{font-family: var(--wp--preset--font-family--texturina) !important;}.has-urbanist-font-family{font-family: var(--wp--preset--font-family--urbanist) !important;}.has-work-sans-font-family{font-family: var(--wp--preset--font-family--work-sans) !important;}.has-system-font-font-family{font-family: var(--wp--preset--font-family--system-font) !important;}.has-source-serif-pro-font-family{font-family: var(--wp--preset--font-family--source-serif-pro) !important;}.has-source-sans-pro-font-family{font-family: var(--wp--preset--font-family--source-sans-pro) !important;}:where(.wp-block-code).has-black-color{color: var(--wp--preset--color--black) !important;}:where(.wp-block-code).has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}:where(.wp-block-code).has-white-color{color: var(--wp--preset--color--white) !important;}:where(.wp-block-code).has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}:where(.wp-block-code).has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}:where(.wp-block-code).has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}:where(.wp-block-code).has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}:where(.wp-block-code).has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}:where(.wp-block-code).has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}:where(.wp-block-code).has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}:where(.wp-block-code).has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}:where(.wp-block-code).has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}:where(.wp-block-code).has-base-color{color: var(--wp--preset--color--base) !important;}:where(.wp-block-code).has-contrast-color{color: var(--wp--preset--color--contrast) !important;}:where(.wp-block-code).has-primary-color{color: var(--wp--preset--color--primary) !important;}:where(.wp-block-code).has-secondary-color{color: var(--wp--preset--color--secondary) !important;}:where(.wp-block-code).has-tertiary-color{color: var(--wp--preset--color--tertiary) !important;}:where(.wp-block-code).has-black-background-color{background-color: var(--wp--preset--color--black) !important;}:where(.wp-block-code).has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}:where(.wp-block-code).has-white-background-color{background-color: var(--wp--preset--color--white) !important;}:where(.wp-block-code).has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}:where(.wp-block-code).has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}:where(.wp-block-code).has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}:where(.wp-block-code).has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}:where(.wp-block-code).has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}:where(.wp-block-code).has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}:where(.wp-block-code).has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}:where(.wp-block-code).has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}:where(.wp-block-code).has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}:where(.wp-block-code).has-base-background-color{background-color: var(--wp--preset--color--base) !important;}:where(.wp-block-code).has-contrast-background-color{background-color: var(--wp--preset--color--contrast) !important;}:where(.wp-block-code).has-primary-background-color{background-color: var(--wp--preset--color--primary) !important;}:where(.wp-block-code).has-secondary-background-color{background-color: var(--wp--preset--color--secondary) !important;}:where(.wp-block-code).has-tertiary-background-color{background-color: var(--wp--preset--color--tertiary) !important;}:where(.wp-block-code).has-black-border-color{border-color: var(--wp--preset--color--black) !important;}:where(.wp-block-code).has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}:where(.wp-block-code).has-white-border-color{border-color: var(--wp--preset--color--white) !important;}:where(.wp-block-code).has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}:where(.wp-block-code).has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}:where(.wp-block-code).has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}:where(.wp-block-code).has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}:where(.wp-block-code).has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}:where(.wp-block-code).has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}:where(.wp-block-code).has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}:where(.wp-block-code).has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}:where(.wp-block-code).has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}:where(.wp-block-code).has-base-border-color{border-color: var(--wp--preset--color--base) !important;}:where(.wp-block-code).has-contrast-border-color{border-color: var(--wp--preset--color--contrast) !important;}:where(.wp-block-code).has-primary-border-color{border-color: var(--wp--preset--color--primary) !important;}:where(.wp-block-code).has-secondary-border-color{border-color: var(--wp--preset--color--secondary) !important;}:where(.wp-block-code).has-tertiary-border-color{border-color: var(--wp--preset--color--tertiary) !important;}:where(.wp-block-code).has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}:where(.wp-block-code).has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}:where(.wp-block-code).has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}:where(.wp-block-code).has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}:where(.wp-block-code).has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}:where(.wp-block-code).has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}:where(.wp-block-code).has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}:where(.wp-block-code).has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}:where(.wp-block-code).has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}:where(.wp-block-code).has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}:where(.wp-block-code).has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}:where(.wp-block-code).has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}:where(.wp-block-code).has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}:where(.wp-block-code).has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}:where(.wp-block-code).has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}:where(.wp-block-code).has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}:where(.wp-block-code).has-dm-sans-font-family{font-family: var(--wp--preset--font-family--dm-sans) !important;}:where(.wp-block-code).has-ibm-plex-mono-font-family{font-family: var(--wp--preset--font-family--ibm-plex-mono) !important;}:where(.wp-block-code).has-inter-font-family{font-family: var(--wp--preset--font-family--inter) !important;}:where(.wp-block-code).has-system-font-font-family{font-family: var(--wp--preset--font-family--system-font) !important;}:where(.wp-block-code).has-source-serif-pro-font-family{font-family: var(--wp--preset--font-family--source-serif-pro) !important;}:where(.wp-block-code).has-albert-sans-font-family{font-family: var(--wp--preset--font-family--albert-sans) !important;}:where(.wp-block-code).has-alegreya-font-family{font-family: var(--wp--preset--font-family--alegreya) !important;}:where(.wp-block-code).has-arvo-font-family{font-family: var(--wp--preset--font-family--arvo) !important;}:where(.wp-block-code).has-bodoni-moda-font-family{font-family: var(--wp--preset--font-family--bodoni-moda) !important;}:where(.wp-block-code).has-cabin-font-family{font-family: var(--wp--preset--font-family--cabin) !important;}:where(.wp-block-code).has-chivo-font-family{font-family: var(--wp--preset--font-family--chivo) !important;}:where(.wp-block-code).has-commissioner-font-family{font-family: var(--wp--preset--font-family--commissioner) !important;}:where(.wp-block-code).has-cormorant-font-family{font-family: var(--wp--preset--font-family--cormorant) !important;}:where(.wp-block-code).has-courier-prime-font-family{font-family: var(--wp--preset--font-family--courier-prime) !important;}:where(.wp-block-code).has-crimson-pro-font-family{font-family: var(--wp--preset--font-family--crimson-pro) !important;}:where(.wp-block-code).has-dm-mono-font-family{font-family: var(--wp--preset--font-family--dm-mono) !important;}:where(.wp-block-code).has-domine-font-family{font-family: var(--wp--preset--font-family--domine) !important;}:where(.wp-block-code).has-eb-garamond-font-family{font-family: var(--wp--preset--font-family--eb-garamond) !important;}:where(.wp-block-code).has-epilogue-font-family{font-family: var(--wp--preset--font-family--epilogue) !important;}:where(.wp-block-code).has-figtree-font-family{font-family: var(--wp--preset--font-family--figtree) !important;}:where(.wp-block-code).has-fira-sans-font-family{font-family: var(--wp--preset--font-family--fira-sans) !important;}:where(.wp-block-code).has-fraunces-font-family{font-family: var(--wp--preset--font-family--fraunces) !important;}:where(.wp-block-code).has-ibm-plex-sans-font-family{font-family: var(--wp--preset--font-family--ibm-plex-sans) !important;}:where(.wp-block-code).has-josefin-sans-font-family{font-family: var(--wp--preset--font-family--josefin-sans) !important;}:where(.wp-block-code).has-jost-font-family{font-family: var(--wp--preset--font-family--jost) !important;}:where(.wp-block-code).has-libre-baskerville-font-family{font-family: var(--wp--preset--font-family--libre-baskerville) !important;}:where(.wp-block-code).has-libre-franklin-font-family{font-family: var(--wp--preset--font-family--libre-franklin) !important;}:where(.wp-block-code).has-literata-font-family{font-family: var(--wp--preset--font-family--literata) !important;}:where(.wp-block-code).has-lora-font-family{font-family: var(--wp--preset--font-family--lora) !important;}:where(.wp-block-code).has-merriweather-font-family{font-family: var(--wp--preset--font-family--merriweather) !important;}:where(.wp-block-code).has-montserrat-font-family{font-family: var(--wp--preset--font-family--montserrat) !important;}:where(.wp-block-code).has-newsreader-font-family{font-family: var(--wp--preset--font-family--newsreader) !important;}:where(.wp-block-code).has-nunito-font-family{font-family: var(--wp--preset--font-family--nunito) !important;}:where(.wp-block-code).has-open-sans-font-family{font-family: var(--wp--preset--font-family--open-sans) !important;}:where(.wp-block-code).has-overpass-font-family{font-family: var(--wp--preset--font-family--overpass) !important;}:where(.wp-block-code).has-petrona-font-family{font-family: var(--wp--preset--font-family--petrona) !important;}:where(.wp-block-code).has-piazzolla-font-family{font-family: var(--wp--preset--font-family--piazzolla) !important;}:where(.wp-block-code).has-playfair-display-font-family{font-family: var(--wp--preset--font-family--playfair-display) !important;}:where(.wp-block-code).has-plus-jakarta-sans-font-family{font-family: var(--wp--preset--font-family--plus-jakarta-sans) !important;}:where(.wp-block-code).has-poppins-font-family{font-family: var(--wp--preset--font-family--poppins) !important;}:where(.wp-block-code).has-raleway-font-family{font-family: var(--wp--preset--font-family--raleway) !important;}:where(.wp-block-code).has-roboto-slab-font-family{font-family: var(--wp--preset--font-family--roboto-slab) !important;}:where(.wp-block-code).has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}:where(.wp-block-code).has-rubik-font-family{font-family: var(--wp--preset--font-family--rubik) !important;}:where(.wp-block-code).has-sora-font-family{font-family: var(--wp--preset--font-family--sora) !important;}:where(.wp-block-code).has-source-sans-pro-font-family{font-family: var(--wp--preset--font-family--source-sans-pro) !important;}:where(.wp-block-code).has-space-mono-font-family{font-family: var(--wp--preset--font-family--space-mono) !important;}:where(.wp-block-code).has-texturina-font-family{font-family: var(--wp--preset--font-family--texturina) !important;}:where(.wp-block-code).has-work-sans-font-family{font-family: var(--wp--preset--font-family--work-sans) !important;}
:root :where(.wp-block-navigation){font-size: var(--wp--preset--font-size--small);}
:root :where(.wp-block-navigation a:where(:not(.wp-element-button))){text-decoration: none;}
:root :where(.wp-block-navigation a:where(:not(.wp-element-button)):hover){text-decoration: underline;}
:root :where(.wp-block-navigation a:where(:not(.wp-element-button)):focus){text-decoration: underline dashed;}
:root :where(.wp-block-navigation a:where(:not(.wp-element-button)):active){text-decoration: none;}
:root :where(.wp-block-post-content){font-size: var(--wp--preset--font-size--medium);}
:root :where(.wp-block-post-content a:where(:not(.wp-element-button))){color: var(--wp--preset--color--secondary);}
:root :where(.wp-block-post-date){font-size: var(--wp--preset--font-size--small);font-weight: 400;}
:root :where(.wp-block-post-date a:where(:not(.wp-element-button))){text-decoration: none;}
:root :where(.wp-block-post-date a:where(:not(.wp-element-button)):hover){text-decoration: underline;}
:root :where(.wp-block-post-terms){font-size: var(--wp--preset--font-size--small);}
:root :where(.wp-block-post-title){font-weight: 400;margin-top: 1.25rem;margin-bottom: 1.25rem;}
:root :where(.wp-block-post-title a:where(:not(.wp-element-button))){text-decoration: none;}
:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):hover){text-decoration: underline;}
:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):focus){text-decoration: underline dashed;}
:root :where(.wp-block-post-title a:where(:not(.wp-element-button)):active){color: var(--wp--preset--color--secondary);text-decoration: none;}
:root :where(.wp-block-quote){border-left-color: inherit;border-left-width: 1px;border-left-style: solid;padding-right: var(--wp--preset--spacing--30);padding-left: var(--wp--preset--spacing--30);}
:root :where(.wp-block-quote cite){font-size: var(--wp--preset--font-size--small);font-style: normal;}
:root :where(.wp-block-site-title){font-size: var(--wp--preset--font-size--medium);font-weight: normal;line-height: 1.4;}
:root :where(.wp-block-site-title a:where(:not(.wp-element-button))){text-decoration: none;}
:root :where(.wp-block-site-title a:where(:not(.wp-element-button)):hover){text-decoration: underline;}
:root :where(.wp-block-site-title a:where(:not(.wp-element-button)):focus){text-decoration: underline dashed;}
:root :where(.wp-block-site-title a:where(:not(.wp-element-button)):active){color: var(--wp--preset--color--secondary);text-decoration: none;}
:root :where(.wp-block-separator){}:root :where(.wp-block-separator:not(.is-style-wide):not(.is-style-dots):not(.alignwide):not(.alignfull)){width: 100px}
:root :where(p){padding-right: 0;padding-left: 0;}
/*# sourceURL=global-styles-inline-css */
</style>
<style id="core-block-supports-inline-css">
.wp-container-core-navigation-is-layout-de66bf79{justify-content:flex-end;}.wp-container-core-group-is-layout-c369a02f{justify-content:flex-start;}.wp-container-core-group-is-layout-951168c3{justify-content:space-between;}.wp-container-core-group-is-layout-386ab566{gap:0.5ch;}.wp-container-core-column-is-layout-98f6e6d0 > *{margin-block-start:0;margin-block-end:0;}.wp-container-core-column-is-layout-98f6e6d0 > * + *{margin-block-start:0px;margin-block-end:0;}.wp-container-core-group-is-layout-5c71f5ee{gap:0.5ch;flex-direction:column;align-items:flex-start;}.wp-container-core-columns-is-layout-4edd3c80{flex-wrap:nowrap;gap:var(--wp--preset--spacing--30);}
/*# sourceURL=core-block-supports-inline-css */
</style>
<link crossorigin='anonymous' rel='stylesheet' id='all-css-54-1' href='/_static/??-eJx9jFEKg0AMRC9kDMJK24/Ss9hlu8RmE3FXen1jBcUi/Zs3wxv8DOBVSpCCaYKBp0iS0WtKVgHTOxjln6a2pkJC0UJm5y2sw/nnGJ6s0WL8Hu74T4pBgdV3hVQOAC/uaFzUR7o3rr05d700rp8Bg7ZNhA==&cssminify=yes' type='text/css' media='all' />
<style id="jetpack-global-styles-frontend-style-inline-css">
:root { --font-headings: unset; --font-base: unset; --font-headings-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; --font-base-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;}
/*# sourceURL=jetpack-global-styles-frontend-style-inline-css */
</style>
<link crossorigin='anonymous' rel='stylesheet' id='all-css-56-1' href='/_static/??-eJyNjcEKAjEMRH/ImhVlqwfxU6TbhrZrmhTTIv69u+JFvHgZ5sHwBh7VeOGG3KB0U6nHzAoztur87cNQRNYInVBBk7tjcCE83zVz3HrVDfxvumb2MPVMAVR8dmRIougX/DhbwrK8pwNEksnROriU884e9+PJDnaYXxwFS20=&cssminify=yes' type='text/css' media='all' />
<script crossorigin='anonymous' type='text/javascript' src='/wp-content/plugins/video/assets/js/videojs/videopress-iframe-api.js?m=1773851158i'></script>
<script id="wp-dom-ready-js" src="/wp-content/plugins/gutenberg-core/v23.9.1/build/scripts/dom-ready/index.min.js?m=1788785546i&#038;ver=3fe927cab37bf38d6a23"></script>
<script crossorigin='anonymous' type='text/javascript' src='/wp-includes/js/dist/vendor/wp-polyfill.min.js?m=1786440387i'></script>
<script data-wp-strategy="defer" defer id="videopress-video-view-script-js" src="/wp-content/mu-plugins/jetpack-plugin/moon/jetpack_vendor/automattic/jetpack-videopress/build/block-editor/blocks/video/view.js?m=1785407911i&#038;ver=8a434125808531899b68"></script>
<script id="wpcom-actionbar-placeholder-js-extra">
var actionbardata = {"siteID":"221649942","postID":"984","siteURL":"https://lucvandonkersgoed.com","xhrURL":"https://lucvandonkersgoed.com/wp-admin/admin-ajax.php","nonce":"e8f3aebd24","isLoggedIn":"","statusMessage":"","subsEmailDefault":"instantly","proxyScriptUrl":"https://s0.wp.com/wp-content/js/wpcom-proxy-request.js?m=1513050504i&amp;ver=20211021","shortlink":"https://wp.me/pf01h4-fS","i18n":{"followedText":"New posts from this site will now appear in your \u003Ca href=\"https://wordpress.com/reader\"\u003EReader\u003C/a\u003E","foldBar":"Collapse this bar","unfoldBar":"Expand this bar","shortLinkCopied":"Shortlink copied to clipboard."}};
//# sourceURL=wpcom-actionbar-placeholder-js-extra
</script>
<script id="jetpack-mu-wpcom-settings-js-before">
var JETPACK_MU_WPCOM_SETTINGS = {"assetsUrl":"https://s1.wp.com/wp-content/mu-plugins/jetpack-mu-wpcom-plugin/moon/jetpack_vendor/automattic/jetpack-mu-wpcom/src/build/"};
//# sourceURL=jetpack-mu-wpcom-settings-js-before
</script>
<script crossorigin='anonymous' type='text/javascript' src='/wp-content/js/rlt-proxy.js?m=1720530689i'></script>
<script id="rlt-proxy-js-after">
rltInitialize( {"token":null,"iframeOrigins":["https:\/\/widgets.wp.com"]} );
//# sourceURL=rlt-proxy-js-after
</script>
<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://donkersgoed.wordpress.com/xmlrpc.php?rsd" />
<meta name="generator" content="WordPress.com" />
<link rel="canonical" href="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/" />
<link rel='shortlink' href='https://wp.me/pf01h4-fS' />
<link rel="alternate" type="application/json+oembed" href="https://public-api.wordpress.com/oembed/?format=json&amp;url=https%3A%2F%2Flucvandonkersgoed.com%2F2024%2F11%2F16%2Fmaking-aws-news-stupid-fast-with-smart-caching%2F&amp;for=wpcom-auto-discovery" /><link rel="alternate" type="application/xml+oembed" href="https://public-api.wordpress.com/oembed/?format=xml&amp;url=https%3A%2F%2Flucvandonkersgoed.com%2F2024%2F11%2F16%2Fmaking-aws-news-stupid-fast-with-smart-caching%2F&amp;for=wpcom-auto-discovery" />
<!-- Jetpack Open Graph Tags -->
<meta property="og:type" content="article" />
<meta property="og:title" content="Making AWS News stupid fast with smart caching" />
<meta property="og:url" content="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/" />
<meta property="og:description" content="As I’m typing this, Re:Invent 2024 is only weeks away. In anticipation of AWS News&#8217; busiest period of the year, I redesigned the API access patterns to support very efficient caching. This re…" />
<meta property="article:published_time" content="2024-11-16T21:24:12+00:00" />
<meta property="article:modified_time" content="2024-11-17T10:05:25+00:00" />
<meta property="og:site_name" content="Luc van Donkersgoed&#039;s Notes" />
<meta property="og:image" content="https://i0.wp.com/lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?fit=1200%2C800&#038;ssl=1" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="800" />
<meta property="og:image:alt" content="" />
<meta property="og:locale" content="en_US" />
<meta property="article:publisher" content="https://www.facebook.com/WordPresscom" />
<meta name="twitter:text:title" content="Making AWS News stupid fast with smart&nbsp;caching" />
<meta name="twitter:image" content="https://i0.wp.com/lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?fit=1200%2C800&#038;ssl=1&#038;w=640" />
<meta name="twitter:card" content="summary_large_image" />
<!-- End Jetpack Open Graph Tags -->
<link rel="search" type="application/opensearchdescription+xml" href="https://lucvandonkersgoed.com/osd.xml" title="Luc van Donkersgoed&#039;s Notes" />
<link rel="search" type="application/opensearchdescription+xml" href="https://s1.wp.com/opensearch.xml" title="WordPress.com" />
<script id="wp-importmap" type="importmap">
{"imports":{"@wordpress/interactivity":"/wp-content/plugins/gutenberg-core/v23.9.1/build/modules/interactivity/index.min.js?m=1788785546i&ver=b0929e0bd08daccaa778"}}
</script>
<link rel="modulepreload" href="/wp-content/plugins/gutenberg-core/v23.9.1/build/modules/interactivity/index.min.js?m=1788785546i&#038;ver=b0929e0bd08daccaa778" id="@wordpress/interactivity-js-modulepreload" fetchpriority="low">
<meta name="description" content="As I’m typing this, Re:Invent 2024 is only weeks away. In anticipation of AWS News&#039; busiest period of the year, I redesigned the API access patterns to support very efficient caching. This resulted in significantly reduced backend load and a much faster frontend." />
<link rel="icon" href="https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=32" sizes="32x32" />
<link rel="icon" href="https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=192" sizes="192x192" />
<link rel="apple-touch-icon" href="https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=180" />
<meta name="msapplication-TileImage" content="https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=270" />
<link rel="stylesheet" id="custom-css-css" type="text/css" href="https://s0.wp.com/?custom-css=1&#038;csblog=f01h4&#038;cscache=6&#038;csrev=39" />
<!-- Jetpack Google Analytics -->
<script async src='https://www.googletagmanager.com/gtag/js?id=G-WT187TXHPL'></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push( arguments ); }
gtag( 'js', new Date() );
gtag( 'config', "G-WT187TXHPL" );
</script>
<!-- End Jetpack Google Analytics -->
</head>
<body class="wp-singular post-template-default single single-post postid-984 single-format-standard wp-embed-responsive wp-theme-pubtwentytwentythree is-block-theme customizer-styles-applied jetpack-reblog-enabled">
<a class="skip-link screen-reader-text" id="wp-skip-link" href="#wp--skip-link--target">Skip to content</a><div class="wp-site-blocks"><header class="wp-block-template-part">
<div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained">
<div class="wp-block-group alignwide is-content-justification-space-between is-layout-flex wp-container-core-group-is-layout-951168c3 wp-block-group-is-layout-flex" style="padding-bottom:var(--wp--preset--spacing--40)">
<p class="wp-block-site-title"><a href="https://lucvandonkersgoed.com" target="_self" rel="home">Luc van Donkersgoed&#039;s Notes</a></p>
<div class="wp-block-group is-content-justification-left is-layout-flex wp-container-core-group-is-layout-c369a02f wp-block-group-is-layout-flex">
<nav class="is-responsive items-justified-right wp-block-navigation is-content-justification-right is-layout-flex wp-container-core-navigation-is-layout-de66bf79 wp-block-navigation-is-layout-flex"
data-wp-interactive="core/navigation" data-wp-context='{"overlayOpenedBy":{"click":false,"hover":false,"focus":false},"type":"overlay","roleAttribute":"","ariaLabel":"Menu"}'><button aria-haspopup="dialog" aria-label="Open menu" class="wp-block-navigation__responsive-container-open"
data-wp-on--click="actions.openMenuOnClick"
data-wp-on--keydown="actions.handleMenuKeydown"
><svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M4 7.5h16v1.5H4z"></path><path d="M4 15h16v1.5H4z"></path></svg></button>
<div class="wp-block-navigation__responsive-container" id="modal-1"
data-wp-class--has-modal-open="state.isMenuOpen"
data-wp-class--is-menu-open="state.isMenuOpen"
data-wp-watch="callbacks.initMenu"
data-wp-on--keydown="actions.handleMenuKeydown"
data-wp-on--focusout="actions.handleMenuFocusout"
tabindex="-1"
>
<div class="wp-block-navigation__responsive-close" tabindex="-1">
<div class="wp-block-navigation__responsive-dialog"
data-wp-bind--aria-modal="state.ariaModal"
data-wp-bind--aria-label="state.ariaLabel"
data-wp-bind--role="state.roleAttribute"
>
<button aria-label="Close menu" class="wp-block-navigation__responsive-container-close"
data-wp-on--click="actions.closeMenuOnClick"
><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="m13.06 12 6.47-6.47-1.06-1.06L12 10.94 5.53 4.47 4.47 5.53 10.94 12l-6.47 6.47 1.06 1.06L12 13.06l6.47 6.47 1.06-1.06L13.06 12Z"></path></svg></button>
<div class="wp-block-navigation__responsive-container-content"
data-wp-watch="callbacks.focusFirstElement"
id="modal-1-content">
<ul class="wp-block-navigation__container is-responsive items-justified-right wp-block-navigation"><ul class="wp-block-page-list"><li class="wp-block-pages-list__item wp-block-navigation-item open-on-hover-click"><a class="wp-block-pages-list__item__link wp-block-navigation-item__content" href="https://lucvandonkersgoed.com/about/">About</a></li><li class="wp-block-pages-list__item wp-block-navigation-item open-on-hover-click"><a class="wp-block-pages-list__item__link wp-block-navigation-item__content" href="https://lucvandonkersgoed.com/content-and-appearances/">Content and appearances</a></li></ul></ul>
</div>
</div>
</div>
</div></nav>
</div>
</div>
</div>
</header>
<main id="wp--skip-link--target" class="wp-block-group is-layout-flow wp-block-group-is-layout-flow" style="margin-top:var(--wp--preset--spacing--50)">
<div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained"><figure style="margin-bottom:var(--wp--preset--spacing--50);margin-top:calc(-1 * var(--wp--preset--spacing--50))" class="alignwide wp-block-post-featured-image"><img width="1024" height="683" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=1024" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" decoding="async" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=2048 2048w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=1440 1440w" sizes="(max-width: 1024px) 100vw, 1024px" data-attachment-id="1006" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/pexels-jeshoots-253647/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg" data-orig-size="4200,2800" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="pexels-jeshoots-253647" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/pexels-jeshoots-253647.jpg?w=1024" /><span class="wp-block-post-featured-image__overlay has-background-dim has-background-dim-10 has-contrast-background-color" style="" aria-hidden="true"></span></figure>
<h1 style="margin-bottom:var(--wp--preset--spacing--40)" class="wp-block-post-title">Making AWS News stupid fast with smart&nbsp;caching</h1></div>
<div class="entry-content wp-block-post-content has-global-padding is-layout-constrained wp-block-post-content-is-layout-constrained">
<p class="wp-block-paragraph">As I&#8217;m typing this, Re:Invent 2024 is only weeks away. In anticipation of <a href="https://aws-news.com">https://aws-news.com</a>&#8216;s busiest period of the year, I redesigned the API access patterns to support very effective caching. This resulted in significantly reduced backend load and a much faster frontend.</p>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">This article focuses on CDN caching &#8211; storing HTTP responses on points-of-presence (POPs) near the user. When you read &#8216;caching&#8217; in this article, we&#8217;re talking about caching in CloudFront, unless stated otherwise.</p>
</blockquote>
<h2 class="wp-block-heading">Background</h2>
<p class="wp-block-paragraph">My strong suit is backend development in Python on AWS. Conversely, I&#8217;m quite lacking in frontend and Typescript skills (although they&#8217;re getting better). So when I started building <a href="https://aws-news.com">AWS News</a> I naturally composed most of the business logic in the backend. This included enrichment features, such as mark as read, bookmark, and rating of articles. As a result, retrieving articles from the backend always yielded a <em>personalized</em> response. In this article we&#8217;ll learn why this approach does not promote efficient caching, and what the better alternatives are.</p>
<h3 class="wp-block-heading">The three components of an article</h3>
<p class="wp-block-paragraph">An article on AWS News has three types of data:</p>
<ul class="wp-block-list">
<li>Data related to the article itself, such as the title, URL, and publication date</li>
<li>Data related to the article&#8217;s presence on <a href="https://aws-news.com">https://aws-news.com</a>, such as its popularity and read counts</li>
<li>Data related to the user reading the article, such as its mark-as-read state, bookmark state, or user tags applied to the article</li>
</ul>
<p class="wp-block-paragraph">In the first iteration of the AWS News API, a <code>GET /articles</code> response looked like this:</p>
<figure class="wp-block-image size-large"><img data-attachment-id="994" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-26/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png" data-orig-size="1180,838" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png?w=1024" width="1024" height="727" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png?w=1024" alt="" class="wp-image-994" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-2.png 1180w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
<p class="wp-block-paragraph">Notice how we&#8217;re combining the three types of data? Since this response contained personalized data, it was impossible to cache efficiently. <em>Maybe</em> the response could be cached for repeat visits by a single user, but as soon as the user data or popularity of the article changed, the cache would need to be invalidated. In practice, I did not cache these responses at all. Efficiency and cost aside, this meant the user generally had to wait for 300-700ms for the different data sources to be retrieved, combined, and sent over the wire. For every request. Not a great user experience.</p>
<h2 class="wp-block-heading">Classifying data by cacheability</h2>
<p class="wp-block-paragraph">To improve the efficiency of AWS News I looked at the data returned by the API and classified it by cacheability. This led to the following categories, ordered from least dynamic to most dynamic:</p>
<ul class="wp-block-list">
<li>Data which only changes when new articles are added or updated in the database: <strong>long-term caching</strong></li>
<li>Data which changes periodically, for example every 10 minutes or every hour: <strong>short-term caching</strong></li>
<li>Data which might change with every request or is different for every user: <strong>no caching</strong></li>
</ul>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Pro tip: do not mix data with different lifecycles in a single HTTP response. It will limit the cacheability of the response to the lifecycle of the most dynamic value.</p>
</blockquote>
<p class="wp-block-paragraph">With these lifecycle categories identified, the problem with the initial design became clear: because the response contained values with different lifecycles, including always-changing data, the entire response could not be cached.</p>
<h3 class="wp-block-heading">Introducing new endpoints</h3>
<p class="wp-block-paragraph">To solve this problem, I had to change existing API endpoints and introduce new ones: the endpoint for articles had to be stripped of dynamic data, and the endpoints for popular articles and user data had to be hosted under their own paths. The new urls became:</p>
<ul class="wp-block-list">
<li><code>GET /articles</code></li>
<li><code>GET /articles/popular</code></li>
<li><code>GET /articles/user_data?article_ids=....</code></li>
</ul>
<p class="wp-block-paragraph">With the user data and popularity removed the <code>GET /articles</code> call clearly falls in the long-term caching category. A response on this endpoint now looks like this:</p>
<figure class="wp-block-image size-large"><img data-attachment-id="996" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-27/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png" data-orig-size="1110,474" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png?w=1024" width="1024" height="437" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png?w=1024" alt="" class="wp-image-996" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-3.png 1110w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
<p class="wp-block-paragraph">This data will not change as long as the article data in the database is not updated. In the example above we&#8217;re only looking at a single article, but search results, lists, pages, and summaries all fall in the same category. After all, a <code>GET /articles?search=Lambda</code> will always yield the same results, as long as the contents of the article database do not change.</p>
<p class="wp-block-paragraph">Popularity data falls in the second category &#8211; it changes periodically. For example, a <code>GET /articles/popular</code> response looks like this:</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1000" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-29/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png" data-orig-size="886,438" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png?w=886" loading="lazy" width="886" height="438" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png?w=886" alt="" class="wp-image-1000" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png 886w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-5.png?w=768 768w" sizes="auto, (max-width: 886px) 100vw, 886px" /></figure>
<p class="wp-block-paragraph">The popularity data is based on user interaction with the site, and is recalculated every 10 minutes. Within this window of 10 minutes the response will never change, making it a good candidate for short-term caching.</p>
<p class="wp-block-paragraph">The third endpoint is new, and was specifically added to support better caching of the first endpoint (<code>GET /articles</code>). The new <code>GET /articles/user_data?article_ids=...</code> endpoint allows the frontend to asynchronously fetch the user data for the articles displayed. By splitting these calls every user can fetch the cached articles extremely quickly, after which logged-in users will have their articles enriched with their personal data. The response of the user data call looks like this, and will never be cached:</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1008" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/screenshot-2024-11-16-at-11-51-52/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/screenshot-2024-11-16-at-11.51.52.png" data-orig-size="766,294" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Screenshot 2024-11-16 at 11.51.52" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/screenshot-2024-11-16-at-11.51.52.png?w=766" loading="lazy" width="766" height="294" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/screenshot-2024-11-16-at-11.51.52.png?w=766" alt="" class="wp-image-1008" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/screenshot-2024-11-16-at-11.51.52.png 766w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/screenshot-2024-11-16-at-11.51.52.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/screenshot-2024-11-16-at-11.51.52.png?w=300 300w" sizes="auto, (max-width: 766px) 100vw, 766px" /></figure>
<p class="wp-block-paragraph">By separating the data with three different lifecycles into three different endpoints, the system can start caching each of them with their own ideal time-to-live (TTL).</p>
<h3 class="wp-block-heading">Increased frontend responsibility </h3>
<p class="wp-block-paragraph">The flip side of this approach is that the frontend gains new responsibilities. Back when all data was returned in a single request, the frontend could just display the results as they came in. With the separated calls, the frontend first needs to fetch the articles and the popularity data (this can be done in parallel). When the articles have been retrieved, the article lists can be displayed. If the popularity request finishes after the articles request, the article cells will need to be updated with a &#8216;hot&#8217; icon where applicable.</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1011" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-31/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png" data-orig-size="1234,658" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png?w=1024" loading="lazy" width="1024" height="546" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png?w=1024" alt="" class="wp-image-1011" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-7.png 1234w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
<p class="wp-block-paragraph">After the articles have been loaded, the frontend needs to do an additional request for the user data. When this data has been retrieved, the read, bookmark, rating and tags icons need to be updated.</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1013" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-32/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png" data-orig-size="1238,706" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png?w=1024" loading="lazy" width="1024" height="583" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png?w=1024" alt="" class="wp-image-1013" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-8.png 1238w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
<p class="wp-block-paragraph">I found building this in React / Next.js quite challenging. I had to use hooks, stores, contexts, effects, and a lot of other dark magic to make it work. Especially preventing reloads and unnecessary rerenders cost me many hours. But! It works and I&#8217;m happy with the results.</p>
<h3 class="wp-block-heading">Results</h3>
<p class="wp-block-paragraph">Speaking of results, let&#8217;s take a look at the speed at which the AWS News frontend now retrieves data. Here&#8217;s a view on the network requests as I&#8217;m clicking around on the site, filtering blogs and news articles, and searching for various terms.</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1017" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-34/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png" data-orig-size="1456,836" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=1024" loading="lazy" width="1024" height="587" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=1024" alt="" class="wp-image-1017" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png?w=1440 1440w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-10.png 1456w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
<p class="wp-block-paragraph">As you can see, most requests are INSANELY fast. Out of 18 requests, 16 hit the CDN cache. Out of these 16 requests, 14 completed under 30ms. You can also see one <code>GET articles</code> request not hitting the CDN. This was a search for DynamoDB, which had not been performed since the last cache invalidation. At 371ms, the request still completed quickly enough, and any other user searching for the same term would now get the response from the cache. You can also see the <code>user_data</code> request, which takes a little longer &#8211; but that&#8217;s okay, because the user could already scroll through the articles as soon as the <code>GET /articles</code> call finished.</p>
<p class="wp-block-paragraph">But these are just numbers. What does 30ms actually look like? Here&#8217;s a video.</p>
<figure class="wp-block-jetpack-videopress jetpack-videopress-player" style="" >
<div class="jetpack-videopress-player__wrapper"> <iframe title='VideoPress Video Player' aria-label='VideoPress Video Player' width='500' height='375' src='https://video.wordpress.com/embed/RcHoyJib?cover=1&amp;autoPlay=0&amp;controls=1&amp;loop=0&amp;muted=0&amp;persistVolume=1&amp;playsinline=0&amp;preloadContent=metadata&amp;useAverageColor=1&amp;hd=0' frameborder='0' allowfullscreen data-resize-to-parent="true" allow='clipboard-write; presentation' ></iframe><script src='https://v0.wordpress.com/js/next/videopress-iframe.js?m=1770107250'></script></div>
</figure>
<p class="wp-block-paragraph">It&#8217;s fast. And that&#8217;s not the only win, because this approach also greatly reduces the number of backend invocations. This means fewer Lambda calls, fewer S3 retrievals, fewer database calls, and generally lower cost.</p>
<h2 class="wp-block-heading">Cache Invalidation</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">There are only two hard things in Computer Science: cache invalidation and naming things.</p>
<p class="wp-block-paragraph">&#8212; <a href="https://martinfowler.com/bliki/TwoHardThings.html">Phil Karlton</a></p>
</blockquote>
<p class="wp-block-paragraph">We&#8217;ve seen that our new caching strategy has delivered great response times. And this makes sense: if the data doesn&#8217;t change, we don&#8217;t calculate it and we host it close to our users. But what if the data does change? The way I see it, there are two approaches you can take:</p>
<ol class="wp-block-list">
<li>Create a comprehensive cache invalidation mechanism and spend days making sure the right objects are invalidated at the right time.</li>
<li>Nuke the cache when something changes.</li>
</ol>
<p class="wp-block-paragraph">I chose the latter. At the scale of AWS News, cache misses and the resulting recalculations of responses aren&#8217;t terribly expensive. So whenever an article is updated or newly added to the database, I just create a <code>/*</code> invalidation, removing all cached objects from the CDN. This guarantees that every page, every search query, and every list includes the updated values. It also means some data which hasn&#8217;t changed will be invalidated and will need to be retrieved again, but I found this an acceptable trade-off.</p>
<p class="wp-block-paragraph">An additional argument for nuking the cache is that the articles database doesn&#8217;t actually change too often. Generally, AWS releases news and blogs five days a week, between 10AM and 4PM Seattle time. During these periods the cache will be invalidated a few times, but <em>outside</em> these periods the cache is stable for many hours, sometimes even days.</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1024" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/image-35/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png" data-orig-size="2682,760" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=1024" loading="lazy" width="1024" height="290" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=1024" alt="" class="wp-image-1024" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=2048 2048w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/image-11.png?w=1440 1440w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">A chart showing when new articles are published</figcaption></figure>
<h3 class="wp-block-heading">Invalidation debouncing</h3>
<p class="wp-block-paragraph">Nuking the cache every time an article is created or updated had an unexpected side effect. Sometimes AWS will release a number of articles at the same time, leading to multiple invalidations at the same moment. Additionally, some parts of the backend system might create multiple invalidations for the same article. This can lead to rate-limit exceptions in CloudFront, as well as some cost. To solve these problems, I created a invalidation debouncer using SQS and Lambda. Instead of directly invalidating the CDN, my backend system now write an CreateInvalidation command to SQS. The SQS queue has a batch window of 10 seconds, which means it collects events for 10 seconds before sending them as a batch to Lambda. The Lambda function filters out any duplicates and only invalidates the CDN once per invalidation pattern. If any of these invalidations fail (maybe they are still being throttled), the message is returned to SQS and retried 30 seconds later. This guarantees that requested invalidations are always executed, which is essential for surfacing new articles in the frontend (almost) as soon as they are published.</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1032" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/debouncer/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png" data-orig-size="2175,788" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Debouncer" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=1024" loading="lazy" width="1024" height="370" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=1024" alt="" class="wp-image-1032" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=1024 1024w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=2048 2048w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=768 768w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/debouncer.png?w=1440 1440w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
<p class="wp-block-paragraph">The diagram above shows the debouncer design. This solution makes it very easy to trigger invalidations from any corner of the system, while buffering, deduplication, and retry logic is completely handled by the debouncer system.</p>
<h2 class="wp-block-heading">UX mitigations</h2>
<p class="wp-block-paragraph">One effect of splitting the single <code>GET /articles</code> request into three separate calls is that the UI can no longer be rendered in one pass. Instead, the layout is updated as each of the responses come in. Initially this led to a very twitchy design, with UI elements suddenly changing as the data changed. An example can be seen below.</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1041" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/old-ezgif-com-video-to-gif-converter-1/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif" data-orig-size="800,431" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="old-ezgif.com-video-to-gif-converter (1)" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif?w=800" loading="lazy" width="800" height="431" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif?w=800" alt="" class="wp-image-1041" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif 800w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/old-ezgif.com-video-to-gif-converter-1.gif?w=768 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>
<p class="wp-block-paragraph">To solve this, I added some ease-in animations to the the UI. The data is exactly the same, but by smoothly transitioning into the new state the change is a lot less jarring. I expected this to be one of the more challenging parts, but CSS animations are really quite simple to implement!</p>
<figure class="wp-block-image size-large"><img data-attachment-id="1042" data-permalink="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/new-ezgif-com-video-to-gif-converter/" data-orig-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif" data-orig-size="800,431" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="new-ezgif.com-video-to-gif-converter" data-image-description="" data-image-caption="" data-large-file="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif?w=800" loading="lazy" width="800" height="431" src="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif?w=800" alt="" class="wp-image-1042" srcset="https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif 800w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif?w=150 150w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif?w=300 300w, https://lucvandonkersgoed.com/wp-content/uploads/2024/11/new-ezgif.com-video-to-gif-converter.gif?w=768 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></figure>
<h2 class="wp-block-heading">Conclusion</h2>
<p class="wp-block-paragraph">At its core, this article is about trade-offs. Initially I chose to minimize frontend logic to optimize time to market, but as trade-off I got an uncacheable design. Then I optimized my API for caching, leading to much, much faster response times and initial renders, but at the cost of additional complexity in the frontend. It also added new cache invalidation requirements to the system, which required additional moving parts like the invalidation debouncer. Finally, the asynchronously loading UI is much faster, but required additional UX work to make it visually acceptable.</p>
<p class="wp-block-paragraph">Regardless of the additional complexity, I advice everyone to consider the lifecycles of the individual fields in their HTTP responses. If you discover mixed lifecycles in the same response, you may have identified a design flaw in your API. Separating them into different calls will introduce some additional complexity, but in the long run it will make your applications much more scalable and maintainable.</p>
<p class="wp-block-paragraph">As you were reading this post, you may have seen other potential improvements. For example, user data can also be cached. Database queries can be cached. We can use smarter invalidation strategies. All of this is true, and if I have the time and need to implement them I&#8217;ll be sure to write a blog post about it.</p>
<div id="jp-post-flair" class="sharedaddy sd-like-enabled"><div class="sharedaddy sd-sharing-enabled"><div class="robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing"><h3 class="sd-title">Share this:</h3><div class="sd-content"><ul><li class="share-twitter"><a rel="nofollow noopener noreferrer"
data-shared="sharing-twitter-984"
class="share-twitter sd-button share-icon"
href="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/?share=twitter"
target="_blank"
aria-labelledby="sharing-twitter-984"
>
<span id="sharing-twitter-984" hidden>Share on X (Opens in new window)</span>
<span>X</span>
</a></li><li class="share-facebook"><a rel="nofollow noopener noreferrer"
data-shared="sharing-facebook-984"
class="share-facebook sd-button share-icon"
href="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/?share=facebook"
target="_blank"
aria-labelledby="sharing-facebook-984"
>
<span id="sharing-facebook-984" hidden>Share on Facebook (Opens in new window)</span>
<span>Facebook</span>
</a></li><li class="share-end"></li></ul></div></div></div><div class='sharedaddy sd-block sd-like jetpack-likes-widget-wrapper jetpack-likes-widget-unloaded' id='like-post-wrapper-221649942-984-6aa4f1df71e6f' data-src='//widgets.wp.com/likes/index.html?ver=20260912#blog_id=221649942&amp;post_id=984&amp;origin=donkersgoed.wordpress.com&amp;obj_id=221649942-984-6aa4f1df71e6f&amp;domain=lucvandonkersgoed.com' data-name='like-post-frame-221649942-984-6aa4f1df71e6f' data-title='Like or Reblog'><div class='likes-widget-placeholder post-likes-widget-placeholder' style='height: 55px;'><span class='button'><span>Like</span></span> <span class='loading'>Loading&#8230;</span></div><span class='sd-text-color'></span><a class='sd-link-color'></a></div></div></div>
<div class="wp-block-template-part">
<div style="height:0" aria-hidden="true" class="wp-block-spacer"></div>
<div class="wp-block-group has-global-padding is-layout-constrained wp-block-group-is-layout-constrained" style="margin-top:var(--wp--preset--spacing--70)">
<hr class="wp-block-separator alignwide has-css-opacity is-style-wide" />
<div class="wp-block-columns alignwide has-small-font-size is-layout-flex wp-container-core-columns-is-layout-4edd3c80 wp-block-columns-is-layout-flex" style="margin-top:var(--wp--preset--spacing--30)">
<div class="wp-block-column is-layout-flow wp-container-core-column-is-layout-98f6e6d0 wp-block-column-is-layout-flow">
<div class="wp-block-group is-layout-flex wp-container-core-group-is-layout-386ab566 wp-block-group-is-layout-flex">
<p class="wp-block-paragraph">
Posted </p>
<div class="wp-block-post-date"><time datetime="2024-11-16T22:24:12+01:00">November 16, 2024</time></div>
<p class="wp-block-paragraph">
in </p>
<div class="taxonomy-category wp-block-post-terms"><a href="https://lucvandonkersgoed.com/category/architecture/" rel="tag">Architecture</a><span class="wp-block-post-terms__separator">, </span><a href="https://lucvandonkersgoed.com/category/design-patterns/" rel="tag">Design Patterns</a><span class="wp-block-post-terms__separator">, </span><a href="https://lucvandonkersgoed.com/category/technical/" rel="tag">Technical</a></div></div>
<div class="wp-block-group is-layout-flex wp-container-core-group-is-layout-386ab566 wp-block-group-is-layout-flex"></div>
</div>
<div class="wp-block-column is-layout-flow wp-container-core-column-is-layout-98f6e6d0 wp-block-column-is-layout-flow">
<div class="wp-block-group is-vertical is-layout-flex wp-container-core-group-is-layout-5c71f5ee wp-block-group-is-layout-flex"><div class="taxonomy-post_tag wp-block-post-terms"><a href="https://lucvandonkersgoed.com/tag/aws/" rel="tag">AWS</a><span class="wp-block-post-terms__separator">, </span><a href="https://lucvandonkersgoed.com/tag/aws-news/" rel="tag">AWS News</a><span class="wp-block-post-terms__separator">, </span><a href="https://lucvandonkersgoed.com/tag/cloudfront/" rel="tag">CloudFront</a><span class="wp-block-post-terms__separator">, </span><a href="https://lucvandonkersgoed.com/tag/frontend/" rel="tag">Frontend</a><span class="wp-block-post-terms__separator">, </span><a href="https://lucvandonkersgoed.com/tag/latency/" rel="tag">Latency</a></div></div>
</div>
</div>
</div>
</div></main>
<footer class="wp-block-template-part"></footer></div>
<!-- wpcom_wp_footer -->
<script type="speculationrules">
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/files/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/pub/twentytwentythree/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
</script>
<script data-wp-router-options="{&quot;loadOnClientNavigation&quot;:true}" fetchpriority="low" id="@wordpress/block-library/navigation/view-js-module" src="/wp-content/plugins/gutenberg-core/v23.9.1/build/modules/block-library/navigation/view.min.js?m=1788785546i&#038;ver=1bf28ded04f9f188bdcb" type="module"></script>
<script id="grofiles-cards-js" src="//0.gravatar.com/js/hovercards/hovercards.min.js?ver=202637d1133547e8a1f2801609f51cef12522abe7f6647d869e9fbc974fe356a37e613"></script>
<script id="wpgroho-js-extra">
var WPGroHo = {"my_hash":""};
//# sourceURL=wpgroho-js-extra
</script>
<script crossorigin='anonymous' type='text/javascript' src='/wp-content/mu-plugins/gravatar-hovercards/wpgroho.js?m=1610363240i'></script>
<script>
// Initialize and attach hovercards to all gravatars
( function() {
function init() {
if ( typeof Gravatar === 'undefined' ) {
return;
}
if ( typeof Gravatar.init !== 'function' ) {
return;
}
Gravatar.profile_cb = function ( hash, id ) {
WPGroHo.syncProfileData( hash, id );
};
Gravatar.my_hash = WPGroHo.my_hash;
Gravatar.init(
'body',
'#wp-admin-bar-my-account',
{
i18n: {
'Edit your profile →': 'Edit your profile →',
'View profile →': 'View profile →',
'Contact': 'Contact',
'Send money': 'Send money',
'Sorry, we are unable to load this Gravatar profile.': 'Sorry, we are unable to load this Gravatar profile.',
'Gravatar not found.': 'Gravatar not found.',
'Too Many Requests.': 'Too Many Requests.',
'Internal Server Error.': 'Internal Server Error.',
'Is this you?': 'Is this you?',
'Claim your free profile.': 'Claim your free profile.',
'Email': 'Email',
'Home Phone': 'Home Phone',
'Work Phone': 'Work Phone',
'Cell Phone': 'Cell Phone',
'Contact Form': 'Contact Form',
'Calendar': 'Calendar',
},
}
);
}
if ( document.readyState !== 'loading' ) {
init();
} else {
document.addEventListener( 'DOMContentLoaded', init );
}
} )();
</script>
<div style="display:none">
</div>
<div id="jp-carousel-loading-overlay" style="display: none;">
<div id="jp-carousel-loading-wrapper">
<span id="jp-carousel-library-loading"><svg class="jetpack-spinner" width="40" height="40" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><circle cx="50" cy="50" r="46" fill="none" stroke="#ddd" stroke-width="8"/><path d="M 50 4 A 46 46 0 0 1 96 50" fill="none" stroke="currentColor" stroke-width="8" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" dur="1.4s" from="0 50 50" to="360 50 50" repeatCount="indefinite"/></path></svg></span>
</div>
</div>
<div class="jp-carousel-overlay" style="display: none;">
<div class="jp-carousel-container">
<!-- The Carousel Swiper -->
<div
class="jp-carousel-wrap swiper jp-carousel-swiper-container jp-carousel-transitions"
itemscope
itemtype="https://schema.org/ImageGallery">
<div class="jp-carousel swiper-wrapper"></div>
<div class="jp-swiper-button-prev swiper-button-prev">
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="maskPrev" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="9" height="12">
<path d="M16.2072 16.59L11.6496 12L16.2072 7.41L14.8041 6L8.8335 12L14.8041 18L16.2072 16.59Z" fill="white"/>
</mask>
<g mask="url(#maskPrev)">
<rect x="0.579102" width="23.8823" height="24" fill="#FFFFFF"/>
</g>
</svg>
</div>
<div class="jp-swiper-button-next swiper-button-next">
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="maskNext" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="8" height="12">
<path d="M8.59814 16.59L13.1557 12L8.59814 7.41L10.0012 6L15.9718 12L10.0012 18L8.59814 16.59Z" fill="white"/>
</mask>
<g mask="url(#maskNext)">
<rect x="0.34375" width="23.8822" height="24" fill="#FFFFFF"/>
</g>
</svg>
</div>
</div>
<!-- The main close buton -->
<div class="jp-carousel-close-hint">
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="maskClose" mask-type="alpha" maskUnits="userSpaceOnUse" x="5" y="5" width="15" height="14">
<path d="M19.3166 6.41L17.9135 5L12.3509 10.59L6.78834 5L5.38525 6.41L10.9478 12L5.38525 17.59L6.78834 19L12.3509 13.41L17.9135 19L19.3166 17.59L13.754 12L19.3166 6.41Z" fill="white"/>
</mask>
<g mask="url(#maskClose)">
<rect x="0.409668" width="23.8823" height="24" fill="#FFFFFF"/>
</g>
</svg>
</div>
<!-- Image info, comments and meta -->
<div class="jp-carousel-info">
<div class="jp-carousel-info-footer">
<div class="jp-carousel-pagination-container">
<div class="jp-swiper-pagination swiper-pagination"></div>
<div class="jp-carousel-pagination"></div>
</div>
<div class="jp-carousel-photo-title-container">
<div class="jp-carousel-photo-caption"></div>
</div>
<div class="jp-carousel-photo-icons-container">
<a href="#" class="jp-carousel-icon-btn jp-carousel-icon-info" aria-label="Toggle photo metadata visibility">
<span class="jp-carousel-icon">
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="maskInfo" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7537 2C7.26076 2 2.80273 6.48 2.80273 12C2.80273 17.52 7.26076 22 12.7537 22C18.2466 22 22.7046 17.52 22.7046 12C22.7046 6.48 18.2466 2 12.7537 2ZM11.7586 7V9H13.7488V7H11.7586ZM11.7586 11V17H13.7488V11H11.7586ZM4.79292 12C4.79292 16.41 8.36531 20 12.7537 20C17.142 20 20.7144 16.41 20.7144 12C20.7144 7.59 17.142 4 12.7537 4C8.36531 4 4.79292 7.59 4.79292 12Z" fill="white"/>
</mask>
<g mask="url(#maskInfo)">
<rect x="0.8125" width="23.8823" height="24" fill="#FFFFFF"/>
</g>
</svg>
</span>
</a>
<a href="#" class="jp-carousel-icon-btn jp-carousel-icon-comments" aria-label="Toggle photo comments visibility">
<span class="jp-carousel-icon">
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="maskComments" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.3271 2H20.2486C21.3432 2 22.2388 2.9 22.2388 4V16C22.2388 17.1 21.3432 18 20.2486 18H6.31729L2.33691 22V4C2.33691 2.9 3.2325 2 4.3271 2ZM6.31729 16H20.2486V4H4.3271V18L6.31729 16Z" fill="white"/>
</mask>
<g mask="url(#maskComments)">
<rect x="0.34668" width="23.8823" height="24" fill="#FFFFFF"/>
</g>
</svg>
<span class="jp-carousel-has-comments-indicator" aria-label="This image has comments."></span>
</span>
</a>
</div>
</div>
<div class="jp-carousel-info-extra">
<div class="jp-carousel-info-content-wrapper">
<div class="jp-carousel-photo-title-container">
<div class="jp-carousel-photo-title"></div>
</div>
<div class="jp-carousel-comments-wrapper">
<div id="jp-carousel-comments-loading">
<span>Loading Comments...</span>
</div>
<div class="jp-carousel-comments"></div>
<div id="jp-carousel-comment-form-container">
<span id="jp-carousel-comment-form-spinner"><svg class="jetpack-spinner" width="20" height="20" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><circle cx="50" cy="50" r="46" fill="none" stroke="#ddd" stroke-width="8"/><path d="M 50 4 A 46 46 0 0 1 96 50" fill="none" stroke="currentColor" stroke-width="8" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" dur="1.4s" from="0 50 50" to="360 50 50" repeatCount="indefinite"/></path></svg></span>
<div id="jp-carousel-comment-post-results"></div>
<form id="jp-carousel-comment-form">
<label for="jp-carousel-comment-form-comment-field" class="screen-reader-text">Write a Comment...</label>
<textarea
name="comment"
class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea"
id="jp-carousel-comment-form-comment-field"
placeholder="Write a Comment..."
></textarea>
<div id="jp-carousel-comment-form-submit-and-info-wrapper">
<div id="jp-carousel-comment-form-commenting-as">
<fieldset>
<label for="jp-carousel-comment-form-email-field">Email (Required)</label>
<input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" />
</fieldset>
<fieldset>
<label for="jp-carousel-comment-form-author-field">Name (Required)</label>
<input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" />
</fieldset>
<fieldset>
<label for="jp-carousel-comment-form-url-field">Website</label>
<input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" />
</fieldset>
</div>
<input
type="submit"
name="submit"
class="jp-carousel-comment-form-button"
id="jp-carousel-comment-form-button-submit"
value="Post Comment" />
</div>
</form>
</div>
</div>
<div class="jp-carousel-image-meta">
<div class="jp-carousel-title-and-caption">
<div class="jp-carousel-photo-info">
<div class="jp-carousel-caption" itemprop="caption description"></div>
</div>
<div class="jp-carousel-photo-description"></div>
</div>
<a class="jp-carousel-image-download" href="#" aria-label="Download image" target="_blank" style="display: none;">
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="3" width="19" height="18">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.84615 5V19H19.7775V12H21.7677V19C21.7677 20.1 20.8721 21 19.7775 21H5.84615C4.74159 21 3.85596 20.1 3.85596 19V5C3.85596 3.9 4.74159 3 5.84615 3H12.8118V5H5.84615ZM14.802 5V3H21.7677V10H19.7775V6.41L9.99569 16.24L8.59261 14.83L18.3744 5H14.802Z" fill="white"/>
</mask>
<g mask="url(#mask0)">
<rect x="0.870605" width="23.8823" height="24" fill="#FFFFFF"/>
</g>
</svg>
<span class="jp-carousel-download-text"></span>
</a>
<div class="jp-carousel-image-map" style="display: none;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
window.WPCOM_sharing_counts = {"https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/":984};
</script>
<div id="actionbar" dir="ltr" style="display: none;"
class="actnbr-pub-twentytwentythree actnbr-has-follow actnbr-has-actions">
<ul>
<li class="actnbr-btn actnbr-hidden">
<a class="actnbr-action actnbr-actn-reblog" href="">
<svg class="gridicon gridicons-reblog" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M22.086 9.914L20 7.828V18c0 1.105-.895 2-2 2h-7v-2h7V7.828l-2.086 2.086L14.5 8.5 19 4l4.5 4.5-1.414 1.414zM6 16.172V6h7V4H6c-1.105 0-2 .895-2 2v10.172l-2.086-2.086L.5 15.5 5 20l4.5-4.5-1.414-1.414L6 16.172z"/></g></svg><span>Reblog</span>
</a>
</li>
<li class="actnbr-btn actnbr-hidden">
<a class="actnbr-action actnbr-actn-follow " href="">
<svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path clip-rule="evenodd" d="m4 4.5h12v6.5h1.5v-6.5-1.5h-1.5-12-1.5v1.5 10.5c0 1.1046.89543 2 2 2h7v-1.5h-7c-.27614 0-.5-.2239-.5-.5zm10.5 2h-9v1.5h9zm-5 3h-4v1.5h4zm3.5 1.5h-1v1h1zm-1-1.5h-1.5v1.5 1 1.5h1.5 1 1.5v-1.5-1-1.5h-1.5zm-2.5 2.5h-4v1.5h4zm6.5 1.25h1.5v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25z" fill-rule="evenodd"></path></svg>
<span>Subscribe</span>
</a>
<a class="actnbr-action actnbr-actn-following no-display" href="">
<svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.5H4V15C4 15.2761 4.22386 15.5 4.5 15.5H11.5V17H4.5C3.39543 17 2.5 16.1046 2.5 15V3H17.5V12.5H16V4.5ZM5.5 6.5H14.5V8H5.5V6.5ZM5.5 9.5H9.5V11H5.5V9.5ZM12 11H13V12H12V11ZM10.5 9.5H14.5V13.5H10.5V9.5ZM5.5 12H9.5V13.5H5.5V12Z" fill="#008A20"></path><path d="M19.5303 15.0303L15.5 19.0605L12.9697 16.5303L14.0303 15.4697L15.5 16.9395L18.4697 13.9697L19.5303 15.0303Z" fill="#008A20"></path></svg>
<span>Subscribed</span>
</a>
<div class="actnbr-popover tip tip-top-left actnbr-notice" id="follow-bubble">
<div class="tip-arrow"></div>
<div class="tip-inner actnbr-follow-bubble">
<ul>
<li class="actnbr-sitename">
<a href="https://lucvandonkersgoed.com">
<img loading='lazy' alt='' src='https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=50' srcset='https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=50 1x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=75 1.5x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=100 2x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=150 3x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=200 4x' class='avatar avatar-50' height='50' width='50' /> Luc van Donkersgoed&#039;s Notes </a>
</li>
<div class="actnbr-message no-display"></div>
<form method="post" action="https://subscribe.wordpress.com" accept-charset="utf-8" style="display: none;">
<div class="actnbr-follow-count">Join 30 other subscribers</div>
<div>
<input type="email" name="email" placeholder="Enter your email address" class="actnbr-email-field" aria-label="Enter your email address" />
</div>
<input type="hidden" name="action" value="subscribe" />
<input type="hidden" name="blog_id" value="221649942" />
<input type="hidden" name="source" value="https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/" />
<input type="hidden" name="sub-type" value="actionbar-follow" />
<input type="hidden" id="_wpnonce" name="_wpnonce" value="a28e5ec845" /> <div class="actnbr-button-wrap">
<button type="submit" value="Sign me up">
Sign me up </button>
</div>
</form>
<li class="actnbr-login-nudge">
<div>
Already have a WordPress.com account? <a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Flucvandonkersgoed.com%252F2024%252F11%252F16%252Fmaking-aws-news-stupid-fast-with-smart-caching%252F">Log in now.</a> </div>
</li>
</ul>
</div>
</div>
</li>
<li class="actnbr-ellipsis actnbr-hidden">
<svg class="gridicon gridicons-ellipsis" height="24" width="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M7 12c0 1.104-.896 2-2 2s-2-.896-2-2 .896-2 2-2 2 .896 2 2zm12-2c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2zm-7 0c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2z"/></g></svg> <div class="actnbr-popover tip tip-top-left actnbr-more">
<div class="tip-arrow"></div>
<div class="tip-inner">
<ul>
<li class="actnbr-sitename">
<a href="https://lucvandonkersgoed.com">
<img loading='lazy' alt='' src='https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=50' srcset='https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=50 1x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=75 1.5x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=100 2x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=150 3x, https://lucvandonkersgoed.com/wp-content/uploads/2023/07/image.jpg?w=200 4x' class='avatar avatar-50' height='50' width='50' /> Luc van Donkersgoed&#039;s Notes </a>
</li>
<li class="actnbr-folded-follow">
<a class="actnbr-action actnbr-actn-follow " href="">
<svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path clip-rule="evenodd" d="m4 4.5h12v6.5h1.5v-6.5-1.5h-1.5-12-1.5v1.5 10.5c0 1.1046.89543 2 2 2h7v-1.5h-7c-.27614 0-.5-.2239-.5-.5zm10.5 2h-9v1.5h9zm-5 3h-4v1.5h4zm3.5 1.5h-1v1h1zm-1-1.5h-1.5v1.5 1 1.5h1.5 1 1.5v-1.5-1-1.5h-1.5zm-2.5 2.5h-4v1.5h4zm6.5 1.25h1.5v2.25h2.25v1.5h-2.25v2.25h-1.5v-2.25h-2.25v-1.5h2.25z" fill-rule="evenodd"></path></svg>
<span>Subscribe</span>
</a>
<a class="actnbr-action actnbr-actn-following no-display" href="">
<svg class="gridicon" height="20" width="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path fill-rule="evenodd" clip-rule="evenodd" d="M16 4.5H4V15C4 15.2761 4.22386 15.5 4.5 15.5H11.5V17H4.5C3.39543 17 2.5 16.1046 2.5 15V3H17.5V12.5H16V4.5ZM5.5 6.5H14.5V8H5.5V6.5ZM5.5 9.5H9.5V11H5.5V9.5ZM12 11H13V12H12V11ZM10.5 9.5H14.5V13.5H10.5V9.5ZM5.5 12H9.5V13.5H5.5V12Z" fill="#008A20"></path><path d="M19.5303 15.0303L15.5 19.0605L12.9697 16.5303L14.0303 15.4697L15.5 16.9395L18.4697 13.9697L19.5303 15.0303Z" fill="#008A20"></path></svg>
<span>Subscribed</span>
</a>
</li>
<li class="actnbr-signup"><a href="https://wordpress.com/start/">Sign up</a></li>
<li class="actnbr-login"><a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Flucvandonkersgoed.com%252F2024%252F11%252F16%252Fmaking-aws-news-stupid-fast-with-smart-caching%252F">Log in</a></li>
<li class="actnbr-shortlink">
<a href="https://wp.me/pf01h4-fS">
<span class="actnbr-shortlink__text">Copy shortlink</span>
<span class="actnbr-shortlink__icon"><svg class="gridicon gridicons-checkmark" height="16" width="16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g><path d="M9 19.414l-6.707-6.707 1.414-1.414L9 16.586 20.293 5.293l1.414 1.414"/></g></svg></span>
</a>
</li>
<li class="flb-report">
<a href="https://wordpress.com/abuse/?report_url=https://lucvandonkersgoed.com/2024/11/16/making-aws-news-stupid-fast-with-smart-caching/" target="_blank" rel="noopener noreferrer">
Report this content </a>
</li>
<li class="actnbr-reader">
<a href="https://wordpress.com/reader/blogs/221649942/posts/984">
View post in Reader </a>
</li>
<li class="actnbr-subs">
<a href="https://subscribe.wordpress.com/">Manage subscriptions</a>
</li>
<li class="actnbr-fold"><a href="">Collapse this bar</a></li>
</ul>
</div>
</div>
</li>
</ul>
</div>
<script>
window.addEventListener( "DOMContentLoaded", function( event ) {
var link = document.createElement( "link" );
link.href = "/wp-content/mu-plugins/actionbar/actionbar.css?v=20250116";
link.type = "text/css";
link.rel = "stylesheet";
document.head.appendChild( link );
var script = document.createElement( "script" );
script.src = "/wp-content/mu-plugins/actionbar/actionbar.js?v=20250204";
document.body.appendChild( script );
} );
</script>
<script id="jetpack-carousel-js-extra">
var jetpackSwiperLibraryPath = {"url":"/wp-content/mu-plugins/jetpack-plugin/moon/_inc/blocks/swiper.js"};
var jetpackCarouselStrings = {"widths":[370,700,1000,1200,1400,2000],"is_logged_in":"","lang":"en","ajaxurl":"https://lucvandonkersgoed.com/wp-admin/admin-ajax.php","nonce":"fd1855488a","display_exif":"1","display_comments":"1","single_image_gallery":"1","single_image_gallery_media_file":"","background_color":"black","comment":"Comment","post_comment":"Post Comment","write_comment":"Write a Comment...","loading_comments":"Loading Comments...","image_label":"Open image in full-screen.","download_original":"View full size \u003Cspan class=\"photo-size\"\u003E{0}\u003Cspan class=\"photo-size-times\"\u003E\u00d7\u003C/span\u003E{1}\u003C/span\u003E","no_comment_text":"Please be sure to submit some text with your comment.","no_comment_email":"Please provide an email address to comment.","no_comment_author":"Please provide your name to comment.","comment_post_error":"Sorry, but there was an error posting your comment. Please try again later.","comment_approved":"Your comment was approved.","comment_unapproved":"Your comment is in moderation.","camera":"Camera","aperture":"Aperture","shutter_speed":"Shutter Speed","focal_length":"Focal Length","copyright":"Copyright","comment_registration":"0","require_name_email":"1","login_url":"https://donkersgoed.wordpress.com/wp-login.php?redirect_to=https%3A%2F%2Flucvandonkersgoed.com%2F2024%2F11%2F16%2Fmaking-aws-news-stupid-fast-with-smart-caching%2F","blog_id":"221649942","meta_data":["camera","aperture","shutter_speed","focal_length","copyright"],"stats_query_args":"blog=221649942&v=wpcom&tz=2&user_id=0&subd=donkersgoed","is_public":"1"};
//# sourceURL=jetpack-carousel-js-extra
</script>
<script id="comment-like-js-extra">
var comment_like_text = {"loading":"Loading...","swipeUrl":"https://s2.wp.com/wp-content/mu-plugins/comment-likes/js/lib/swipe.js?m=1382645497i&amp;ver=20131008"};
//# sourceURL=comment-like-js-extra
</script>
<script id="sharing-js-js-extra">
var sharing_js_options = {"lang":"en","counts":"1","is_stats_active":"1"};
//# sourceURL=sharing-js-js-extra
</script>
<script crossorigin='anonymous' type='text/javascript' src='/_static/??-eJydj8EOwiAQRH9IunqwrQfjpxiETQuFBYFN49/bKHpoTA/edl5mJjswR6ECFaQCnkV0PBjK4MyEGe6MjKMk7TA1Nu/gt9liiVJNVYMPgeBqSMGNjdOgZAqc0X19H9B4Qxu1Kni/IPH+xa7AVrD2izkukZX8f0ceZUIttX68TkNDHXDx50PXd6fjvm9b+wQo237F'></script>
<script id="sharing-js-js-after">
window.WPCOM_sharing_popups = window.WPCOM_sharing_popups || {};
window.WPCOM_sharing_popups[ "twitter" ] = "menubar=1,resizable=1,width=600,height=350";
window.WPCOM_sharing_popups = window.WPCOM_sharing_popups || {};
window.WPCOM_sharing_popups[ "facebook" ] = "menubar=1,resizable=1,width=600,height=400";
//# sourceURL=sharing-js-js-after
</script>
<script type="text/javascript">
(function () {
var wpcom_reblog = {
source: 'toolbar',
toggle_reblog_box_flair: function (obj_id, post_id) {
// Go to site selector. This will redirect to their blog if they only have one.
const postEndpoint = `https://wordpress.com/post`;
// Ideally we would use the permalink here, but fortunately this will be replaced with the
// post permalink in the editor.
const originalURL = `${ document.location.href }?page_id=${ post_id }`;
const url =
postEndpoint +
'?url=' +
encodeURIComponent( originalURL ) +
'&is_post_share=true' +
'&v=5';
const redirect = function () {
if (
! window.open( url, '_blank' )
) {
location.href = url;
}
};
if ( /Firefox/.test( navigator.userAgent ) ) {
setTimeout( redirect, 0 );
} else {
redirect();
}
},
};
window.wpcom_reblog = wpcom_reblog;
})();
</script>
<script id="wp-emoji-settings" type="application/json">
{"baseUrl":"https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/","ext":".png","svgUrl":"https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/","svgExt":".svg","source":{"concatemoji":"/wp-includes/js/wp-emoji-release.min.js?m=1783090810i&ver=7.1.1-alpha-63555"}}
</script>
<script type="module">
/*! This file is auto-generated */
var e="script#wp-emoji-settings",t=document.querySelector(e);if(!(t instanceof HTMLScriptElement))throw new Error("Element missing: "+e);const r=JSON.parse(t.text),s=(window._wpemojiSettings=r,"wpEmojiSettingsSupports"),o=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(s,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const r=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===r[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,r){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!r(e,"\ud83e\u1fac8")}return!1}function f(e,t,n,r){let a;const s=(a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),o=(s.textBaseline="top",s.font="600 32px Arial",{});return e.forEach(e=>{o[e]=t(s,e,n,r)}),o}function a(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}r.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(s));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(o),u.toString(),c.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"});const a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=e=>{i(n=e.data),a.terminate(),t(n)})}catch(e){}i(n=f(o,u,c,p))}t(n)}).then(e=>{for(const n in e)r.supports[n]=e[n],r.supports.everything=r.supports.everything&&r.supports[n],"flag"!==n&&(r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&r.supports[n]);var t;r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&!r.supports.flag,r.supports.everything||((t=r.source||{}).concatemoji?a(t.concatemoji):t.wpemoji&&t.twemoji&&(a(t.twemoji),a(t.wpemoji)))});
//# sourceURL=/wp-includes/js/wp-emoji-loader.min.js
</script>
<iframe src='https://widgets.wp.com/likes/master.html?ver=20260912#ver=20260912' scrolling='no' id='likes-master' name='likes-master' style='display:none;'></iframe>
<div id='likes-other-gravatars' role="dialog" aria-hidden="true" tabindex="-1"><div class="likes-text"><span>%d</span></div><ul class="wpl-avatars sd-like-gravatars"></ul></div>
<script src="//stats.wp.com/w.js?69" defer></script> <script type="text/javascript">
_tkq = window._tkq || [];
_stq = window._stq || [];
_tkq.push(['storeContext', {'blog_id':'221649942','blog_tz':'2','user_lang':'en','blog_lang':'en','user_id':'0'}]);
// Prevent sending pageview tracking from WP-Admin pages.
_stq.push(['view', {'blog':'221649942','v':'wpcom','tz':'2','user_id':'0','post':'984','subd':'donkersgoed'}]);
_stq.push(['extra', {'crypt':'UE5tW3cvZGQ/JUs1UEpSdi1dRV80cWliNnluVHVULnMxMThFWFVKPTYvWkdyelJMcixMfmNrKzddZ1BUQ3VyJnhENk8sWDV1Q1JqbyxDJUhqLGJCRFNaX0M/YWtIc0hZRyw3dktPV210QUlXKzd8a358S0toTVt3aFZYJStwcDFZSUMtUWV5aWhdX2lBL2pvLEV4a1ZJZ2xYRnAzb2JtNjhsMS8mR05JfkxNYituTmNxMk0vTnZiVndlMX5QSDkvNGI5ZGstWlBwaWlwV19zJWJtTloxS3xkWEtZUT1bcUp6bnZwUHM='}]);
_stq.push([ 'clickTrackerInit', '221649942', '984' ]);
</script>
<noscript><img src="https://pixel.wp.com/b.gif?v=noscript" style="height:1px;width:1px;overflow:hidden;position:absolute;bottom:1px;" alt="" /></noscript>
<meta id="bilmur" property="bilmur:data" content="" data-provider="wordpress.com" data-service="simple" data-site-tz="Europe/Amsterdam" data-custom-props="{&quot;enq_wp-polyfill&quot;:&quot;1&quot;,&quot;logged_in&quot;:&quot;0&quot;,&quot;wptheme&quot;:&quot;pub\/twentytwentythree&quot;,&quot;wptheme_is_block&quot;:&quot;1&quot;}" >
<script defer src="/wp-content/js/bilmur.min.js?i=17&amp;m=202637"></script> </body>
</html>