Files
nexus/sreweekly/articles/454/08-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservic.html
2026-09-12 17:23:01 +08:00

179 lines
86 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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-US"> <head><title>Keeping User Journey SLOs Up-to-Date with E2E Testing in a Microservices Architecture | Mercari Engineering</title><!-- Google Tag Manager --><script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s),
dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-WFXJ8Q3');
</script><!-- End Google Tag Manager --><meta charset="UTF-8"><link rel="canonical" href="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/"><meta name="description" content="This post is for Day 3 of Mercari Advent Calendar 2024, brought to you by @yakenji from the Mercari Site Reliability Eng"><meta name="robots" content="index, follow"><meta property="og:title" content="Keeping User Journey SLOs Up-to-Date with E2E Testing in a Microservices Architecture | Mercari Engineering"><meta property="og:type" content="website"><meta property="og:image" content="https://storage.googleapis.com/prd-engineering-asset/2024/11/1f5fdacb-advent_calendar_2024_mercari.png"><meta property="og:url" content="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/"><meta property="og:description" content="This post is for Day 3 of Mercari Advent Calendar 2024, brought to you by @yakenji from the Mercari Site Reliability Eng"><meta property="og:locale" content="en_US"><meta property="og:locale:alternate" content="ja_JP"><link rel="icon" type="image/x-icon" href="/favicon.ico"><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="/favicons/favicon.ico"><link rel="icon" type="image/vnd.microsoft.icon" href="/favicons/favicon.ico"><link rel="alternate" type="application/rss+xml" href="/blog/feed.xml" title="メルカリエンジニアリングブログ"><link rel="alternate" type="application/rss+xml" href="/en/blog/feed.xml" title="Mercari Engineering blog"><link rel="alternate" href="https://engineering.mercari.com/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" hreflang="ja"><link rel="alternate" href="https://engineering.mercari.com/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" hreflang="ja-JP"><link rel="alternate" href="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" hreflang="en"><link rel="alternate" href="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" hreflang="en-US"><link rel="sitemap" href="https://engineering.mercari.com//sitemap-index.xml"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="twitter:card" property="twitter:card" content="summary_large_image"><meta name="twitter:site" content="MercariDev"><meta name="twitter:site" content="mercaridevjp"><meta name="description" content="This post is for Day 3 of Mercari Advent Calendar 2024, brought to you by @yakenji from the Mercari Site Reliability Eng"><meta property="og:description" content="This post is for Day 3 of Mercari Advent Calendar 2024, brought to you by @yakenji from the Mercari Site Reliability Eng"><meta property="og:url" content="https://engineering.mercari.com/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/"><meta property="og:image" content="https://storage.googleapis.com/prd-engineering-asset/2024/11/1f5fdacb-advent_calendar_2024_mercari.png"><meta property="og:title" content="Keeping User Journey SLOs Up-to-Date with E2E Testing in a Microservices Architecture"><meta data-hid="og:type" property="og:type" content="website"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta data-hid="thumbnail" name="thumbnail" content="https://engineering.mercari.com//img/ogp/ogp_a.jpg"><link data-n-head="ssr" rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-touch-icon-57x57.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-touch-icon-60x60.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-touch-icon-72x72.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-touch-icon-76x76.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-touch-icon-114x114.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon-120x120.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-touch-icon-144x144.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-touch-icon-152x152.png"><link data-n-head="ssr" rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon-180x180.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="36x36" href="/favicons/android-chrome-36x36.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="48x48" href="/favicons/android-chrome-48x48.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="72x72" href="/favicons/android-chrome-72x72.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="96x96" href="/favicons/android-chrome-96x96.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="128x128" href="/favicons/android-chrome-128x128.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="144x144" href="/favicons/android-chrome-144x144.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="152x152" href="/favicons/android-chrome-152x152.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="192x192" href="/favicons/android-chrome-192x192.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="256x256" href="/favicons/android-chrome-256x256.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="384x384" href="/favicons/android-chrome-384x384.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="512x512" href="/favicons/android-chrome-512x512.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="36x36" href="/favicons/icon-36x36.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="48x48" href="/favicons/icon-48x48.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="72x72" href="/favicons/icon-72x72.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="96x96" href="/favicons/icon-96x96.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="128x128" href="/favicons/icon-128x128.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="144x144" href="/favicons/icon-144x144.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="152x152" href="/favicons/icon-152x152.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="160x160" href="/favicons/icon-160x160.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="192x192" href="/favicons/icon-192x192.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="196x196" href="/favicons/icon-196x196.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="256x256" href="/favicons/icon-256x256.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="384x384" href="/favicons/icon-384x384.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="512x512" href="/favicons/icon-512x512.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="16x16" href="/favicons/icon-16x16.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="24x24" href="/favicons/icon-24x24.png"><link data-n-head="ssr" rel="icon" type="image/png" sizes="32x32" href="/favicons/icon-32x32.png"><meta name="astro-view-transitions-enabled" content="true"><meta name="astro-view-transitions-fallback" content="animate"><link rel="stylesheet" href="/_astro/_slug_.kTvJvROE.css">
<link rel="stylesheet" href="/_astro/_slug_.DRERk4z5.css">
<style>@charset "UTF-8";._layout-enter_p1it6_2,._fade-enter_p1it6_3{opacity:0}._layout-enter-active_p1it6_6,._fade-enter-active_p1it6_7{transition:opacity .5s}._layout-leave-active_p1it6_10,._fade-leave-active_p1it6_11{transition:opacity .1s}._layout-leave-to_p1it6_14,._fade-leave-to_p1it6_15{opacity:0}._card_p1it6_19{background:#ffffffe6;padding:30px 20px 20px 30px}@media screen and (max-width: 575px){._card_p1it6_19{padding:5.3333333333vw}}._card_p1it6_19:hover ._post__link_p1it6_28:after{width:100%}._card_p1it6_19:hover ._post_p1it6_28{opacity:.5}._card_p1it6_19:hover ._post__link_p1it6_28{transform:translate(5px)}._card_p1it6_19 *{transition:opacity .2s}._new_p1it6_41{position:relative}._new_p1it6_41:after{content:"NEW";color:#fff;font-size:1rem;position:absolute;background:#ff0211;width:40px;height:40px;top:-20px;left:-20px;display:flex;border-radius:100%;justify-content:center;line-height:4}@media screen and (max-width: 575px){._new_p1it6_41:after{left:auto;top:-5.3333333333vw;right:-5.3333333333vw;width:10.6666666667vw;height:10.6666666667vw;font-size:3.2vw;line-height:3.5}}._post_p1it6_28{padding-top:10px;display:flex;flex-wrap:no-wrap}@media screen and (max-width: 575px){._post_p1it6_28{padding-top:2.6666666667vw;display:block}}._post__thumbnail_p1it6_82{width:196px;max-height:110px;object-fit:cover}@media screen and (max-width: 575px){._post__thumbnail_p1it6_82{width:100%;max-height:44vw}}._post__text_p1it6_93{margin-left:25px;flex:1 1 0%;display:flex;flex-wrap:wrap}@media screen and (max-width: 575px){._post__text_p1it6_93{margin-left:0;padding-top:5.3333333333vw}}._post__title_p1it6_105{font-size:2rem;width:100%;font-family:Avenir-Black,Arial,游ゴシック体,YuGothic,游ゴシック,Yu Gothic,sans-serif;font-weight:700;font-style:normal}@media screen and (max-width: 575px){._post__title_p1it6_105{font-size:4.8vw}}._post__meta_p1it6_117{width:100%;display:flex;padding-top:20px;justify-content:space-between}@media screen and (max-width: 575px){._post__meta_p1it6_117{padding-top:5.3333333333vw}}._post__to-post_p1it6_128{display:inline-flex;align-items:flex-end}._post__link_p1it6_28{transition:transform .2s;padding-bottom:6px;position:relative}._post__link_p1it6_28:after{content:"";width:0%;height:1px;background:#3d3d3d;position:absolute;bottom:0;left:0;transition:width .2s ease-out}._meta-wrap_p1it6_148 .tag-list{font-size:1.2rem;color:#969696;display:flex;flex-wrap:wrap}@media screen and (max-width: 575px){._meta-wrap_p1it6_148 .tag-list{font-size:2.9333333333vw}}._meta-wrap_p1it6_148 .tag-list__item{margin-left:5px}@media screen and (max-width: 575px){._meta-wrap_p1it6_148 .tag-list__item{margin-left:1.3333333333vw}}._author_p1it6_168{font-size:1.2rem}@media screen and (max-width: 575px){._author_p1it6_168{font-size:2.9333333333vw}}._author__name_p1it6_176{color:#969696;margin-right:5px}._layout-enter_d76db_1,._fade-enter_d76db_2{opacity:0}._layout-enter-active_d76db_5,._fade-enter-active_d76db_6{transition:opacity .5s}._layout-leave-active_d76db_9,._fade-leave-active_d76db_10{transition:opacity .1s}._layout-leave-to_d76db_13,._fade-leave-to_d76db_14{opacity:0}._tag-list_d76db_18{font-size:1.5rem;color:#969696;display:flex;flex-wrap:wrap}@media screen and (max-width: 575px){._tag-list_d76db_18{font-size:3.2vw}}._tag-list__item_d76db_29:nth-of-type(n+2){margin-left:15px}@media screen and (max-width: 575px){._tag-list__item_d76db_29{margin-left:1.3333333333vw}}._tag-list__item_d76db_29 a,._tag-list__item_d76db_29 p{display:inline-flex;align-items:center}._tag-list__item_d76db_29 a:before,._tag-list__item_d76db_29 p:before{content:"";display:inline-block;background:url(/img/icon_category.svg) 0/100% no-repeat;width:12px;height:12px;margin-right:5px}
._layout-enter_1jn14_1,._fade-enter_1jn14_2{opacity:0}._layout-enter-active_1jn14_5,._fade-enter-active_1jn14_6{transition:opacity .5s}._layout-leave-active_1jn14_9,._fade-leave-active_1jn14_10{transition:opacity .1s}._layout-leave-to_1jn14_13,._fade-leave-to_1jn14_14{opacity:0}._post-meta_1jn14_18{width:100%;margin-bottom:30px}._post-title_1jn14_23{font-size:4rem;padding-top:15px;margin-bottom:5px;font-weight:700}._post-title_1jn14_23:before{content:"";display:block;height:0;width:0;margin-top:calc((1 - 1.6) * .5em)}._post-title_1jn14_23:after{content:"";display:block;height:0;width:0;margin-bottom:calc((1 - 1.6) * .5em)}@media screen and (max-width: 575px){._post-title_1jn14_23{padding-top:6.6666666667vw;font-size:7.4666666667vw;line-height:1.1}._post-title_1jn14_23:before{content:"";display:block;height:0;width:0;margin-top:calc((1 - 1.1) * .5em)}._post-title_1jn14_23:after{content:"";display:block;height:0;width:0;margin-bottom:calc((1 - 1.1) * .5em)}}._link_1jn14_65:hover{opacity:.6;transition:opacity .2s}._layout-enter_1c1i9_1,._fade-enter_1c1i9_2{opacity:0}._layout-enter-active_1c1i9_5,._fade-enter-active_1c1i9_6{transition:opacity .5s}._layout-leave-active_1c1i9_9,._fade-leave-active_1c1i9_10{transition:opacity .1s}._layout-leave-to_1c1i9_13,._fade-leave-to_1c1i9_14{opacity:0}._post-author_1c1i9_18{font-size:1.5rem;margin-left:5px;display:inline-flex}@media screen and (max-width: 575px){._post-author_1c1i9_18{font-size:2.9333333333vw}}._post-author_name_1c1i9_28{color:#969696}._post-author_1c1i9_18 span{margin-right:5px}._post-author_1c1i9_18 dt{font-weight:400}._post-author_1c1i9_18 a:hover{opacity:.6;transition:opacity .2s}
._layout-enter_3t7h3_1,._fade-enter_3t7h3_2{opacity:0}._layout-enter-active_3t7h3_5,._fade-enter-active_3t7h3_6{transition:opacity .5s}._layout-leave-active_3t7h3_9,._fade-leave-active_3t7h3_10{transition:opacity .1s}._layout-leave-to_3t7h3_13,._fade-leave-to_3t7h3_14{opacity:0}._link_3t7h3_18{display:inline-flex;align-items:center}._link_3t7h3_18 a{text-decoration:none}._link_3t7h3_18:hover *{opacity:.5}._link_3t7h3_18:hover ._link__arrow_3t7h3_28{transform:translate(5px)}._link_3t7h3_18 *{transition:opacity .2s}._link__tag_3t7h3_34{border-bottom:1px solid #3d3d3d;margin-right:15px;font-weight:700}._link__arrow_3t7h3_28{transition:transform .2s}@media screen and (max-width: 575px){._link__arrow_3t7h3_28{width:3.7333333333vw;height:2.4vw}}
</style>
<link rel="stylesheet" href="/_astro/_slug_.DflaUU4B.css">
<style>._layout-enter_15cy3_1,._fade-enter_15cy3_2{opacity:0}._layout-enter-active_15cy3_5,._fade-enter-active_15cy3_6{transition:opacity .5s}._layout-leave-active_15cy3_9,._fade-leave-active_15cy3_10{transition:opacity .1s}._layout-leave-to_15cy3_13,._fade-leave-to_15cy3_14{opacity:0}._catItem_15cy3_18{line-height:1.4;display:flex}._catItem_15cy3_18 span:not(:first-child){margin-left:2px}._catItem_15cy3_18 ._RnBRw_15cy3_25{width:15px;height:15px;margin-right:5px;margin-top:3px;color:#b4b4b4}
.layout-enter,.fade-enter{opacity:0}.layout-enter-active,.fade-enter-active{transition:opacity .5s}.layout-leave-active,.fade-leave-active{transition:opacity .1s}.layout-leave-to,.fade-leave-to{opacity:0}.toTop{width:63px;height:63px;border:1px solid #707684;border-radius:50%;display:flex;justify-content:center;align-items:center;background:#ffffffb3;position:fixed;bottom:40px;right:100px;cursor:pointer;z-index:99;opacity:1;transition:.2s}@media screen and (max-width: 767px){.toTop{right:14px;bottom:14px;transition:.3s}}.toTop:disabled{opacity:0;transition:.2s}@media screen and (max-width: 767px){.toTop:disabled{opacity:1;transform:translateY(calc(100% + 14px))}}.toTop .toTop_svg{width:16px;margin-bottom:2px}
</style><script type="module" src="/_astro/hoisted.kDiS2mRD.js"></script></head> <body> <!-- Google Tag Manager (noscript) --> <noscript> <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WFXJ8Q3" height="0" width="0" style="display:none;visibility:hidden">
</iframe> </noscript> <!-- End Google Tag Manager (noscript) --> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).load=e;window.dispatchEvent(new Event("astro:load"));})();;(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="dUIY4" component-url="/_astro/TheHeader.ByGQ2pxB.js" component-export="TheHeader" renderer-url="/_astro/client.DNGgaD7G.js" props="{&quot;currentPath&quot;:[0,&quot;/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/&quot;],&quot;categories&quot;:[0,{&quot;jp&quot;:[1,[[0,{&quot;uri&quot;:[0,&quot;/category/ai/&quot;],&quot;name&quot;:[0,&quot;AI&quot;],&quot;totalPosts&quot;:[0,116]}],[0,{&quot;uri&quot;:[0,&quot;/category/backend/&quot;],&quot;name&quot;:[0,&quot;Backend&quot;],&quot;totalPosts&quot;:[0,275]}],[0,{&quot;uri&quot;:[0,&quot;/category/client-side/&quot;],&quot;name&quot;:[0,&quot;Client side&quot;],&quot;totalPosts&quot;:[0,161]}],[0,{&quot;uri&quot;:[0,&quot;/category/development/&quot;],&quot;name&quot;:[0,&quot;Development&quot;],&quot;totalPosts&quot;:[0,234]}],[0,{&quot;uri&quot;:[0,&quot;/category/infrastructure/&quot;],&quot;name&quot;:[0,&quot;Infrastructure&quot;],&quot;totalPosts&quot;:[0,149]}],[0,{&quot;uri&quot;:[0,&quot;/category/organization/&quot;],&quot;name&quot;:[0,&quot;Organization&quot;],&quot;totalPosts&quot;:[0,195]}],[0,{&quot;uri&quot;:[0,&quot;/category/qa/&quot;],&quot;name&quot;:[0,&quot;QA&quot;],&quot;totalPosts&quot;:[0,89]}],[0,{&quot;uri&quot;:[0,&quot;/category/research-advanced-tech/&quot;],&quot;name&quot;:[0,&quot;Research &amp;amp; Advanced Tech&quot;],&quot;totalPosts&quot;:[0,31]}],[0,{&quot;uri&quot;:[0,&quot;/category/security/&quot;],&quot;name&quot;:[0,&quot;Security&quot;],&quot;totalPosts&quot;:[0,34]}]]],&quot;en&quot;:[1,[[0,{&quot;uri&quot;:[0,&quot;/category/ai/&quot;],&quot;name&quot;:[0,&quot;AI&quot;],&quot;totalPosts&quot;:[0,59]}],[0,{&quot;uri&quot;:[0,&quot;/category/backend/&quot;],&quot;name&quot;:[0,&quot;Backend&quot;],&quot;totalPosts&quot;:[0,88]}],[0,{&quot;uri&quot;:[0,&quot;/category/client-side/&quot;],&quot;name&quot;:[0,&quot;Client side&quot;],&quot;totalPosts&quot;:[0,85]}],[0,{&quot;uri&quot;:[0,&quot;/category/development/&quot;],&quot;name&quot;:[0,&quot;Development&quot;],&quot;totalPosts&quot;:[0,117]}],[0,{&quot;uri&quot;:[0,&quot;/category/infrastructure/&quot;],&quot;name&quot;:[0,&quot;Infrastructure&quot;],&quot;totalPosts&quot;:[0,84]}],[0,{&quot;uri&quot;:[0,&quot;/category/organization/&quot;],&quot;name&quot;:[0,&quot;Organization&quot;],&quot;totalPosts&quot;:[0,74]}],[0,{&quot;uri&quot;:[0,&quot;/category/qa/&quot;],&quot;name&quot;:[0,&quot;QA&quot;],&quot;totalPosts&quot;:[0,25]}],[0,{&quot;uri&quot;:[0,&quot;/category/research-advanced-tech/&quot;],&quot;name&quot;:[0,&quot;Research &amp;amp; Advanced Tech&quot;],&quot;totalPosts&quot;:[0,11]}],[0,{&quot;uri&quot;:[0,&quot;/category/security/&quot;],&quot;name&quot;:[0,&quot;Security&quot;],&quot;totalPosts&quot;:[0,40]}]]]}]}" ssr="" client="load" opts="{&quot;name&quot;:&quot;TheHeader&quot;,&quot;value&quot;:true}" await-children=""><header class="_header_133ho_18"><div class="_header__inner_133ho_30"><div class="_brand_133ho_51"><a href="/en/"><div><img src="/img/mercari.svg" alt="mercari" width="140" height="29" class="_brand__mercari_133ho_58"/><img src="/img/engineering.svg" alt="engineering" width="205" height="36" class="_brand__engineering_133ho_71"/></div></a><div class="_brand__description_133ho_77 false">Mercari Engineering Portal</div></div><div class="
_navigations_133ho_96
_navigations__pc_133ho_118"><div class="_navigations__top_133ho_155"><ul class="_langSwitch_14x13_18"><li class="_langSwitch__lang_14x13_24"><a data-prefetch-disabled="true" class="_langSwitch__link_14x13_37" href="/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/">日本語</a></li><li class="_langSwitch__lang_14x13_24"><a data-prefetch-disabled="true" class="_langSwitch__link_14x13_37" aria-selected="true">English</a></li></ul><div class="_header_sns_133ho_176"><div class="_sns_16o34_18"><a href="https://twitter.com/MercariDev" rel="noopener" target="_blank"><img src="/img/x_black.svg" class="_sns__X_16o34_24" alt="X" width="27" height="22"/></a><a href="https://www.linkedin.com/company/mercari-inc-/" rel="noopener" target="_blank"><img src="/img/linkedin_black.svg" alt="LinkedIn" width="27" height="22"/></a><a href="/en/blog/feed.xml" rel="noopener" target="_blank"><img src="/img/rss_black.svg" alt="RSS" width="27" height="22"/></a></div></div></div><nav><ul class="_navigation_1sjtz_18"><li class="_navigation__item_1sjtz_23 undefined"><div class="_menu__heading_1sjtz_28">Organization</div><ul class="_menu__list_1sjtz_33"><li class="_menu__item_1sjtz_40"><a href="/en/culture" class="menu__link _menu__link_1sjtz_60 ">Culture</a></li><li class="_menu__item_1sjtz_40"><a href="/en/roles" class="menu__link _menu__link_1sjtz_60 ">Roles</a></li></ul></li><li class="_navigation__item_1sjtz_23 undefined"><div class="_menu__heading_1sjtz_28">Technology</div><ul class="_menu__list_1sjtz_33"><li class="_menu__item_1sjtz_40"><a href="/en/technology-stack" class="menu__link _menu__link_1sjtz_60 ">Technology-stack</a></li><li class="_menu__item_1sjtz_40"><a href="/en/open-source" class="menu__link _menu__link_1sjtz_60 ">Open-source</a></li><li class="_menu__item_1sjtz_40"><a href="/en/output" class="menu__link _menu__link_1sjtz_60 ">Output</a></li><li class="_menu__item_1sjtz_40"><a href="/en/learning-materials" class="menu__link _menu__link_1sjtz_60 ">Learning-materials</a></li></ul></li><li class="_navigation__item_1sjtz_23 undefined"><div class="_menu__heading_1sjtz_28">Other</div><ul class="_menu__list_1sjtz_33"><li class="_menu__item_1sjtz_40"><a href="/en/events" class="menu__link _menu__link_1sjtz_60 ">Event</a></li><li class="_menu__item_1sjtz_40 _blog_1sjtz_46"><a href="/en/blog" class="menu__link _menu__link_1sjtz_60 ">Blog</a><div class="_dropdown_1sjtz_90"><nav><ul class="_navDropdown_1l90c_18"><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/ai/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>AI</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/backend/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Backend</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/client-side/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Client side</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/development/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Development</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/infrastructure/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Infrastructure</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/organization/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Organization</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/qa/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>QA</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/research-advanced-tech/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Research &amp; Advanced Tech</span></p></a></li><li class="_navDropdown_item_1l90c_27"><a href="/en/blog/category/security/"><p class="_catItem_15cy3_18"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="20" height="16" viewBox="0 0 20 16" class="undefined undefined _RnBRw_15cy3_25 RnBRw"><path fill="currentColor" fill-rule="nonzero" d="M18.799 15.25h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zm0-6h-11.5a1.25 1.25 0 1 1 0-2.5h11.5a1.25 1.25 0 0 1 0 2.5zM2 16a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm0-6a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"></path></svg><span>Security</span></p></a></li></ul></nav></div></li><li class="_menu__item_1sjtz_40"><a href="https://careers.mercari.com/job-categories/engineering/" class="menu__link _menu__link_1sjtz_60 " rel="noopener" target="_blank">Careers</a></li></ul></li></ul></nav></div><div class="_hamburgerWrap_133ho_193"><button class="
_hamburger_wmr22_18
false" aria-label="Menu"><span></span><span></span><span></span></button></div></div><div class="
_navigations_133ho_96
_navigations__sp_133ho_123
false"><nav class="_navigation_7gm6v_18"><dl class="_navigation__inner_7gm6v_23"><div class="
_navigation__inner__item_7gm6v_30
_menu_7gm6v_38" style="flex:
3
3
0%"><dt class="_menu__heading_7gm6v_53">Organization</dt><dd><a href="/en/culture" class="
menu__link _menu__link_7gm6v_58
">Culture</a></dd><dd><a href="/en/roles" class="
menu__link _menu__link_7gm6v_58
">Roles</a></dd></div><div class="
_navigation__inner__item_7gm6v_30
_menu_7gm6v_38" style="flex:
5
5
0%"><dt class="_menu__heading_7gm6v_53">Technology</dt><dd><a href="/en/technology-stack" class="
menu__link _menu__link_7gm6v_58
">Technology-stack</a></dd><dd><a href="/en/open-source" class="
menu__link _menu__link_7gm6v_58
">Open-source</a></dd><dd><a href="/en/output" class="
menu__link _menu__link_7gm6v_58
">Output</a></dd><dd><a href="/en/learning-materials" class="
menu__link _menu__link_7gm6v_58
">Learning-materials</a></dd></div><div class="
_navigation__inner__item_7gm6v_30
_menu_7gm6v_38" style="flex:
4
4
0%"><dt class="_menu__heading_7gm6v_53">Other</dt><dd><a href="/en/events" class="
menu__link _menu__link_7gm6v_58
">Event</a></dd><dd><a href="/en/blog" class="
menu__link _menu__link_7gm6v_58
">Blog</a></dd><dd><a href="https://careers.mercari.com/job-categories/engineering/" class="menu__link _menu__link_7gm6v_58" target="_blank">Careers</a></dd></div></dl></nav><div class="_sp_bottom_133ho_162"><ul class="_langSwitch_14x13_18"><li class="_langSwitch__lang_14x13_24"><a data-prefetch-disabled="true" class="_langSwitch__link_14x13_37" href="/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/">日本語</a></li><li class="_langSwitch__lang_14x13_24"><a data-prefetch-disabled="true" class="_langSwitch__link_14x13_37" aria-selected="true">English</a></li></ul><div class="_sns_16o34_18"><a href="https://twitter.com/MercariDev" rel="noopener" target="_blank"><img src="/img/x_black.svg" class="_sns__X_16o34_24" alt="X" width="27" height="22"/></a><a href="https://www.linkedin.com/company/mercari-inc-/" rel="noopener" target="_blank"><img src="/img/linkedin_black.svg" alt="LinkedIn" width="27" height="22"/></a><a href="/en/blog/feed.xml" rel="noopener" target="_blank"><img src="/img/rss_black.svg" alt="RSS" width="27" height="22"/></a></div></div></div></header><!--astro:end--></astro-island> <main> <div class="_hero_xz05m_18 _pageHeroEntry_1eyul_18"><div class="container _container_xz05m_44"><time datetime="2024-12-06">2024/12/06</time><div><div class="_post-meta_1jn14_18"><h1 class="_post-title_1jn14_23 "><div>Keeping User Journey SLOs Up-to-Date with E2E Testing in a Microservices Architecture</div></h1><ul class="_tag-list_d76db_18 tag-list"><li class="_tag-list__item_d76db_29"><a href="/en/blog/category/client-side/">Client side</a></li><li class="_tag-list__item_d76db_29"><a href="/en/blog/category/development/">Development</a></li><li class="_tag-list__item_d76db_29"><a href="/en/blog/category/infrastructure/">Infrastructure</a></li></ul><dl class="_post-author_1c1i9_18"><dt>Author:</dt><dd><a href="/en/blog/author/yakenji/"><span class="_post-author_name_1c1i9_28 post-author_name">yakenji</span></a></dd></dl><span> , <time datetime="2024-12-06">2024/12/06</time></span></div></div><img src="https://storage.googleapis.com/prd-engineering-asset/2024/11/1f5fdacb-advent_calendar_2024_mercari.png" alt="Keeping User Journey SLOs Up-to-Date with E2E Testing in a Microservices Architecture" class="_post__thumbnail_1eyul_24"/><div class="_lang-switch_1eyul_40"><div class="_link_3t7h3_18 undefined"><a data-prefetch-disabled="true" href="/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/" class="_link__tag_3t7h3_34">日本語で読む</a><img src="/img/arrow.svg" width="20" height="13" class="_link__arrow_3t7h3_28"/></div></div></div></div> <section> <div class="container _container_11e9j_22 container--inner"> <astro-island uid="1Vn2a2" component-url="/_astro/PageContent.CfXlRJsU.js" component-export="PageContent" renderer-url="/_astro/client.DNGgaD7G.js" props="{&quot;html&quot;:[0,&quot;&lt;p&gt;This post is for Day 3 of &lt;a href=\&quot;https://engineering.mercari.com/en/blog/entry/20241125-mercari-advent-calendar-2024/\&quot;&gt;Mercari Advent Calendar 2024&lt;/a&gt;, brought to you by &lt;a href=\&quot;https://www.linkedin.com/in/kenji-tsuchiya-5395a518a/\&quot;&gt;@yakenji&lt;/a&gt; from the Mercari Site Reliability Engineering (SRE) team.&lt;/p&gt;\n&lt;p&gt;At Mercari, our SRE team is dedicated to maintaining and enhancing the reliability of our core product, the Mercari marketplace app, by measuring its availability and latency. We establish Service Level Objectives (SLOs) for these metrics and monitor their adherence, as well as whether availability and latency are degrading due to temporary outages or other issues.&lt;/p&gt;\n&lt;p&gt;To achieve this, our SLOs are based on Critical User Journeys (CUJs). We recently revamped these SLOs, redefining them as &amp;quot;User Journey SLOs&amp;quot; to achieve the following:&lt;/p&gt;\n&lt;ol&gt;\n&lt;li&gt;Clarify the definition of CUJs.&lt;/li&gt;\n&lt;li&gt;Establish a one-to-one relationship between each CUJ and its corresponding Service Level Indicator (SLI).&lt;/li&gt;\n&lt;li&gt;Automate the maintenance of CUJs and SLOs.&lt;/li&gt;\n&lt;li&gt;Visualize the behavior of each CUJ during incidents through dashboards.&lt;/li&gt;\n&lt;/ol&gt;\n&lt;p&gt;This initiative resulted in a &lt;strong&gt;99% reduction&lt;/strong&gt; in SLO maintenance time and enabled &lt;strong&gt;near-zero time triage&lt;/strong&gt;, meaning we can now start assessing impact within seconds of incident detection.&lt;/p&gt;\n&lt;p&gt;This article details the rationale behind revising our CUJ-based SLOs and explains each of the four objectives mentioned above, focusing on how we achieved continuous updates using end-to-end (E2E) tests and leveraged them effectively.&lt;/p&gt;\n&lt;h2&gt;Current Challenges&lt;/h2&gt;\n&lt;p&gt;Before delving into the main topic, let&amp;#8217;s examine the two types of SLOs used at Mercari and the challenges they presented. This section explains the motivation and goals behind the User Journey SLO initiative.&lt;/p&gt;\n&lt;h3&gt;Microservice SLOs and Their Challenges&lt;/h3&gt;\n&lt;p&gt;At Mercari, our backend architecture utilizes microservices. For example, user data is handled by the User service, and item data by the Item service. Each domain has its own independent microservice (these are simplified examples and may not reflect the actual implementation). Each service is managed by a dedicated team responsible for its development and operation. Each team sets SLOs for their services and is responsible for meeting these objectives. These SLOs also drive monitoring and alerting, enabling development teams to respond to service incidents.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/16f77d8f-01_microservices.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;p&gt;While defining SLOs for individual services is crucial for teams operating and developing independently, relying solely on these microservice SLOs presents challenges. One of the major challenges is the difficulty of evaluating the product&amp;#8217;s overall reliability from the user&amp;#8217;s perspective.&lt;/p&gt;\n&lt;p&gt;Microservices handle specific domain functions. For simple scenarios confined to a single domain, like &amp;quot;editing user information,&amp;quot; only one service (e.g., the User service) might be involved. In these cases, assessing SLO&amp;#8217;s attainment is straightforward. However, more complex scenarios like &amp;quot;shipping a purchased item&amp;quot; involve multiple services, making it difficult to evaluate the overall reliability of the user journey.&lt;/p&gt;\n&lt;p&gt;Furthermore, not all APIs within each service are used in each scenario. Development teams may not have a complete understanding of which APIs are used where, as APIs are generally designed for flexibility and reusability. Conversely, frontend developers typically aren’t overly concerned with which service is being accessed.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/33734adf-02_3services-e1733301620126.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;p&gt;For these reasons, assessing end-user experience, such as successfully shipping purchased items, becomes difficult using only microservice-specific SLOs. Even if services A, B, and C individually meet their availability targets, the user-perceived availability might be lower. During incident response, an alert from Service A doesn&amp;#8217;t necessarily indicate the user impact, hindering prioritization and mitigation efforts.&lt;/p&gt;\n&lt;h3&gt;SRE and SLOs&lt;/h3&gt;\n&lt;p&gt;To address the challenges posed by microservice SLOs, our SRE team monitors our overall marketplace service based on Critical User Journeys (CUJs), independently of the microservice-specific SLOs. CUJs represent the most critical sequences of actions frequently performed by users. However, this approach also presented challenges:&lt;/p&gt;\n&lt;ol&gt;\n&lt;li&gt;&lt;strong&gt;Unclear Definition:&lt;/strong&gt; The definition of CUJs and the rationale for selecting associated APIs were undocumented, making it difficult to add or maintain CUJs.&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Multiple SLOs per CUJ:&lt;/strong&gt; Directly monitoring the SLOs of each related API resulted in multiple SLOs for a single CUJ, hindering accurate assessment of user-perceived reliability.&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Cumbersome Updates:&lt;/strong&gt; Frequent functional developments and API changes led to high maintenance costs and difficulty in keeping CUJ definitions and their corresponding SLOs up-to-date.&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Opaque Impact of SLO Degradation:&lt;/strong&gt; When SLOs were not met, the impact on users was unclear, making it difficult to prioritize responses and hindering broader utilization of CUJ-based SLOs across Mercari.&lt;/li&gt;\n&lt;/ol&gt;\n&lt;p&gt;Challenge 3, in particular, resulted in a lack of comprehensive maintenance since the initial implementation around 2021, potentially leading to gaps in monitored APIs. To address these issues and enable effective use of CUJ-based SLOs across Mercari for reliability improvements and incident response, we decided on a complete rebuild.&lt;/p&gt;\n&lt;h2&gt;Overview of the User Journey SLO&lt;/h2&gt;\n&lt;p&gt;To address the first two challenges—unclear CUJ definitions and multiple SLOs per CUJ—I&amp;#8217;ll explain how we defined and managed CUJs within our User Journey SLO framework and how we established corresponding Service Level Indicators (SLIs).&lt;/p&gt;\n&lt;h3&gt;Defining Critical User Journeys (CUJs)&lt;/h3&gt;\n&lt;p&gt;For User Journey SLOs, we maintained a similar level of granularity to our previously defined CUJs, encompassing tasks like product listing, purchasing, and searching. We revisited and redefined approximately 40 CUJs, covering both major and minor user flows. To address the unclear definition challenge, we documented each CUJ using screen operation transition diagrams, explicitly outlining the expected screen transitions resulting from user actions. We also defined the available states for each screen. A CUJ is considered available if these states are met and unavailable if not. Generally, if the core functions of a CUJ are available, the CUJ is considered available. Secondary features, such as suggestions, that don&amp;#8217;t impact core functionality are not considered in the availability calculation.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/2bf78c3d-03_lite-listing.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;h3&gt;Defining the SLI&lt;/h3&gt;\n&lt;p&gt;To address the multiple SLOs per CUJ challenge, we defined SLIs to establish a one-to-one relationship between each CUJ and its availability and latency metrics. These SLIs are measurable using our existing observability tools. At Mercari, a single customer operation typically involves multiple API calls, as we generally don&amp;#8217;t utilize a Backend for Frontend (BFF) architecture.&lt;/p&gt;\n&lt;p&gt;Ideally, we would directly measure the success of each screen transition within a CUJ. However, we currently lack the infrastructure for such granular measurement. While we considered implementing new mechanisms, the engineering cost of covering approximately 40 CUJs across all clients (iOS, Android, and web) was prohibitive. We also explored leveraging Real-Time User Monitoring (RUM) data from our Application Performance Management (APM) tools, but sampling rates, cost, and feasibility concerns made this approach impractical.&lt;/p&gt;\n&lt;p&gt;Therefore, we opted to associate the critical APIs called during a CUJ with the CUJ&amp;#8217;s SLI. We categorized API calls within a CUJ into two types: (1) those whose failure directly results in CUJ unavailability, and (2) those whose failure does not. To create more accurate and robust SLIs, we focused solely on those in the first category—the critical APIs—for our SLI calculations.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/2e8c670a-04_critical_api-e1733301725194.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;p&gt;Using metrics from these critical APIs, we uniquely defined the availability and latency SLIs for each CUJ as follows:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&lt;strong&gt;Availability:&lt;/strong&gt; The CUJ&amp;#8217;s success rate is the product of the success rates of its critical APIs. For example, if critical APIs A and B have success rates &lt;em&gt;S&lt;sub&gt;A&lt;/sub&gt;&lt;/em&gt; and &lt;em&gt;S&lt;sub&gt;B&lt;/sub&gt;&lt;/em&gt;, respectively, the CUJ success rate &lt;em&gt;S&lt;sub&gt;CUJ&lt;/sub&gt;&lt;/em&gt; is calculated as :&lt;br /&gt;\n&lt;em&gt;S&lt;sub&gt;CUJ&lt;/sub&gt;&lt;/em&gt; = &lt;em&gt;S&lt;sub&gt;A&lt;/sub&gt;&lt;/em&gt; × &lt;em&gt;S&lt;sub&gt;B&lt;/sub&gt;&lt;/em&gt;&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Latency:&lt;/strong&gt;The CUJ&amp;#8217;s achievement rate for its latency target is the lowest target achievement rate among its critical APIs. For example, if critical APIs A and B have achievement rates &lt;em&gt;A&lt;sub&gt;A&lt;/sub&gt;&lt;/em&gt; and &lt;em&gt;A&lt;sub&gt;B&lt;/sub&gt;&lt;/em&gt; for their respective latency targets, the CUJ achievement rate &lt;em&gt;A&lt;sub&gt;CUJ&lt;/sub&gt;&lt;/em&gt; is calculated as:&lt;br /&gt;\n&lt;em&gt;A&lt;sub&gt;CUJ&lt;/sub&gt;&lt;/em&gt; = min(&lt;em&gt;A&lt;sub&gt;A&lt;/sub&gt;&lt;/em&gt;, &lt;em&gt;A&lt;sub&gt;B&lt;/sub&gt;&lt;/em&gt;)&lt;/li&gt;\n&lt;/ul&gt;\n&lt;h3&gt;Identifying Critical APIs&lt;/h3&gt;\n&lt;p&gt;To implement the SLI calculations described above, we needed to identify the critical APIs for each CUJ. We considered various methods, including static code analysis, but ultimately chose a hands-on approach using a real application to balance practicality, feasibility, and accuracy. This process involved the following steps:&lt;/p&gt;\n&lt;ol&gt;\n&lt;li&gt;&lt;strong&gt;Proxy and Record:&lt;/strong&gt; We placed a proxy between a development build of our iOS app and a development environment. We then executed each CUJ, recording all API calls made during the process.&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Fault Injection and Validation:&lt;/strong&gt; Using the proxy, we injected faults by forcing specific APIs to return 500 errors. We then re-executed the CUJ to determine whether the failure of each API resulted in the CUJ becoming unavailable according to our defined criteria.&lt;/li&gt;\n&lt;/ol&gt;\n&lt;p&gt;We used a development build of our iOS app for this process, as it is our most frequently used client.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/9c0d93b7-05_proxy-e1733301842561.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;p&gt;Communication between our client apps and servers is typically encrypted. Therefore, we selected a proxy capable of inspecting and modifying encrypted traffic. We chose the open-source tool &lt;a href=\&quot;https://mitmproxy.org/\&quot;&gt;mitmproxy&lt;/a&gt; for its interactive web interface and extensibility through add-on development.&lt;/p&gt;\n&lt;p&gt;The User Journey SLO framework, established with the approach described above, enables us to detect incidents affecting specific CUJs, allowing for immediate identification of the impact scope and faster prioritization of incident response efforts.&lt;/p&gt;\n&lt;h2&gt;Continuous Update and Visualization Using E2E Test&lt;/h2&gt;\n&lt;p&gt;Next, to address the third challenge—cumbersome updates—I&amp;#8217;ll explain how we maintain critical API information using iOS end-to-end (E2E) tests. I&amp;#8217;ll also describe our dashboard visualization approach, which resolves the fourth challenge—opaque impact of SLO degradation.&lt;/p&gt;\n&lt;h3&gt;The Need for Automation&lt;/h3&gt;\n&lt;p&gt;The Mercari client app undergoes multiple releases each month. Additionally, &lt;a href=\&quot;https://engineering.mercari.com/blog/entry/20231211-large-team-development-at-mercari-ios/\&quot;&gt;trunk-based development&lt;/a&gt; and feature flags allow us to release new features without requiring app store updates. Tracking all these changes manually is impractical for the SRE team. Manually investigating frequent changes to critical APIs is also infeasible. Undetected changes could lead to monitoring gaps or unnecessary monitoring of deprecated APIs. Therefore, automating the update process for critical APIs is essential to keep up with the changes in application&lt;/p&gt;\n&lt;h3&gt;Automating with iOS E2E Tests&lt;/h3&gt;\n&lt;p&gt;We leveraged our existing iOS app E2E test suite, built using the &lt;a href=\&quot;“https://developer.apple.com/documentation/xctest”\&quot;&gt;XCTest framework&lt;/a&gt;, to automate the extraction of critical APIs.&lt;/p&gt;\n&lt;p&gt;Specifically, we implemented each CUJ as an XCTest test case, executable on simulators. Each test case includes assertions to verify the availability of the CUJ according to our defined criteria. This setup automatically distinguishes between available and unavailable CUJs. Furthermore, the test cases are version-controlled alongside the app&amp;#8217;s source code.&lt;/p&gt;\n&lt;p&gt;We developed a mitmproxy add-on to retrieve the list of APIs called during each test and to inject failures into specific APIs. This add-on provides an API to control the proxy, allowing us to manage it directly from our test cases and scripts.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/82b2bbc5-06_proxy_addon-e1733301902654.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;p&gt;We automated the critical API identification process by scripting the execution of these XCTest tests and controlling the proxy through the add-on. The results, including whether each called API is critical to the CUJ, are logged to BigQuery. Screenshots of the app&amp;#8217;s behavior during fault injection are stored in Google Cloud Storage (GCS).&lt;/p&gt;\n&lt;p&gt;Test results logged in BigQuery are identified by unique IDs, allowing for efficient comparison with previous test runs. We also use Terraform modules, specifically designed for User Journey SLOs, to define and manage SLOs, monitors, and dashboards in our APM system. This allows us to seamlessly integrate changes and easily add new CUJs.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/45bc74df-07_workflow-e1733301956779.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;p&gt;This automation provides several key benefits:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&lt;strong&gt;Reduced Maintenance:&lt;/strong&gt; The process is almost entirely automated, aside from code maintenance for the tests themselves.&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Version Control:&lt;/strong&gt; Both the test cases and the app code are version-controlled in the same repository, ensuring consistency.&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Efficient Integration:&lt;/strong&gt; ID-based management of test results facilitates seamless integration with our APM system.&lt;/li&gt;\n&lt;/ul&gt;\n&lt;p&gt;Ultimately, we created approximately 60 test cases covering around 40 CUJs. This automation drastically reduced the manual effort required, achieving a 99% reduction in maintenance time compared to manual SLO management.&lt;/p&gt;\n&lt;h3&gt;Dashboard Visualization&lt;/h3&gt;\n&lt;p&gt;A key goal of the User Journey SLO framework is to empower teams beyond SRE, such as incident response and customer support, with actionable insights. To achieve this, we needed to present up-to-date information about critical APIs and CUJ behavior during outages in an easily accessible format. We used Looker Studio to visualize this data, providing dashboards that display the list of API calls for each CUJ and screenshots of the app&amp;#8217;s behavior during API failures.&lt;/p&gt;\n&lt;p&gt;&lt;img src=\&quot;https://storage.googleapis.com/prd-engineering-asset/2024/12/1fa0a74c-08_dashboard.png\&quot; alt=\&quot;\&quot; /&gt;&lt;/p&gt;\n&lt;h2&gt;Current Status and Future Directions&lt;/h2&gt;\n&lt;p&gt;Through the initiatives described above, we successfully implemented the following for our User Journey SLOs:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Clarifying the definition of CUJs&lt;/li&gt;\n&lt;li&gt;Establishing a one-to-one relationship between each CUJ and its corresponding Service Level Indicator (SLI)&lt;/li&gt;\n&lt;li&gt;Automating the maintenance of CUJs and SLOs&lt;/li&gt;\n&lt;li&gt;Visualizing the behavior of each CUJ during incidents through dashboards&lt;/li&gt;\n&lt;/ul&gt;\n&lt;p&gt;We currently operate SLOs for approximately 40 CUJs, utilizing around 60 test cases. While currently undergoing trial usage within the SRE team, even at this stage, the new SLOs have significantly improved:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Incident detection speed and accuracy&lt;/li&gt;\n&lt;li&gt;Accuracy of impact assessment&lt;/li&gt;\n&lt;li&gt;Speed of root cause identification&lt;/li&gt;\n&lt;li&gt;Overall quality visibility&lt;/li&gt;\n&lt;/ul&gt;\n&lt;p&gt;Quantitatively, we&amp;#8217;ve observed the following improvements:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;&lt;strong&gt;Immediate impact assessment:&lt;/strong&gt; Achieved &lt;strong&gt;near-zero time triage&lt;/strong&gt;, meaning we can now start assessing impact within seconds of an incident being detected&lt;/li&gt;\n&lt;li&gt;&lt;strong&gt;Reduced maintenance overhead:&lt;/strong&gt; Achieved a &lt;strong&gt;99% reduction&lt;/strong&gt; in SLO maintenance time.&lt;/li&gt;\n&lt;/ul&gt;\n&lt;p&gt;Building on these positive results, we plan to expand the use of User Journey SLOs beyond the SRE team, focusing on:&lt;/p&gt;\n&lt;ul&gt;\n&lt;li&gt;Integrating SLOs into our internal incident management criteria&lt;/li&gt;\n&lt;li&gt;Leveraging User Journey SLOs to improve customer support responses&lt;/li&gt;\n&lt;/ul&gt;\n&lt;h2&gt;Conclusion&lt;/h2&gt;\n&lt;p&gt;This article explored how Mercari implements and operates User Journey SLOs based on CUJs, detailing the specifics of our SLI/SLO definitions and our automated maintenance process using iOS end-to-end testing. We hope this provides valuable insights into managing SLIs and SLOs for complex systems.&lt;/p&gt;\n&lt;p&gt;Tomorrow&amp;#8217;s article will be by &amp;#8230;.rina&amp;#8230;. . Look forward to it!&lt;/p&gt;\n&quot;]}" ssr="" client="load" opts="{&quot;name&quot;:&quot;PageContent&quot;,&quot;value&quot;:true}" await-children=""><div class="_body_1o0xy_19"><div class="page-content undefined"><p>This post is for Day 3 of <a href="https://engineering.mercari.com/en/blog/entry/20241125-mercari-advent-calendar-2024/">Mercari Advent Calendar 2024</a>, brought to you by <a href="https://www.linkedin.com/in/kenji-tsuchiya-5395a518a/">@yakenji</a> from the Mercari Site Reliability Engineering (SRE) team.</p>
<p>At Mercari, our SRE team is dedicated to maintaining and enhancing the reliability of our core product, the Mercari marketplace app, by measuring its availability and latency. We establish Service Level Objectives (SLOs) for these metrics and monitor their adherence, as well as whether availability and latency are degrading due to temporary outages or other issues.</p>
<p>To achieve this, our SLOs are based on Critical User Journeys (CUJs). We recently revamped these SLOs, redefining them as &quot;User Journey SLOs&quot; to achieve the following:</p>
<ol>
<li>Clarify the definition of CUJs.</li>
<li>Establish a one-to-one relationship between each CUJ and its corresponding Service Level Indicator (SLI).</li>
<li>Automate the maintenance of CUJs and SLOs.</li>
<li>Visualize the behavior of each CUJ during incidents through dashboards.</li>
</ol>
<p>This initiative resulted in a <strong>99% reduction</strong> in SLO maintenance time and enabled <strong>near-zero time triage</strong>, meaning we can now start assessing impact within seconds of incident detection.</p>
<p>This article details the rationale behind revising our CUJ-based SLOs and explains each of the four objectives mentioned above, focusing on how we achieved continuous updates using end-to-end (E2E) tests and leveraged them effectively.</p>
<h2>Current Challenges</h2>
<p>Before delving into the main topic, let&#8217;s examine the two types of SLOs used at Mercari and the challenges they presented. This section explains the motivation and goals behind the User Journey SLO initiative.</p>
<h3>Microservice SLOs and Their Challenges</h3>
<p>At Mercari, our backend architecture utilizes microservices. For example, user data is handled by the User service, and item data by the Item service. Each domain has its own independent microservice (these are simplified examples and may not reflect the actual implementation). Each service is managed by a dedicated team responsible for its development and operation. Each team sets SLOs for their services and is responsible for meeting these objectives. These SLOs also drive monitoring and alerting, enabling development teams to respond to service incidents.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/16f77d8f-01_microservices.png" alt="" /></p>
<p>While defining SLOs for individual services is crucial for teams operating and developing independently, relying solely on these microservice SLOs presents challenges. One of the major challenges is the difficulty of evaluating the product&#8217;s overall reliability from the user&#8217;s perspective.</p>
<p>Microservices handle specific domain functions. For simple scenarios confined to a single domain, like &quot;editing user information,&quot; only one service (e.g., the User service) might be involved. In these cases, assessing SLO&#8217;s attainment is straightforward. However, more complex scenarios like &quot;shipping a purchased item&quot; involve multiple services, making it difficult to evaluate the overall reliability of the user journey.</p>
<p>Furthermore, not all APIs within each service are used in each scenario. Development teams may not have a complete understanding of which APIs are used where, as APIs are generally designed for flexibility and reusability. Conversely, frontend developers typically aren’t overly concerned with which service is being accessed.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/33734adf-02_3services-e1733301620126.png" alt="" /></p>
<p>For these reasons, assessing end-user experience, such as successfully shipping purchased items, becomes difficult using only microservice-specific SLOs. Even if services A, B, and C individually meet their availability targets, the user-perceived availability might be lower. During incident response, an alert from Service A doesn&#8217;t necessarily indicate the user impact, hindering prioritization and mitigation efforts.</p>
<h3>SRE and SLOs</h3>
<p>To address the challenges posed by microservice SLOs, our SRE team monitors our overall marketplace service based on Critical User Journeys (CUJs), independently of the microservice-specific SLOs. CUJs represent the most critical sequences of actions frequently performed by users. However, this approach also presented challenges:</p>
<ol>
<li><strong>Unclear Definition:</strong> The definition of CUJs and the rationale for selecting associated APIs were undocumented, making it difficult to add or maintain CUJs.</li>
<li><strong>Multiple SLOs per CUJ:</strong> Directly monitoring the SLOs of each related API resulted in multiple SLOs for a single CUJ, hindering accurate assessment of user-perceived reliability.</li>
<li><strong>Cumbersome Updates:</strong> Frequent functional developments and API changes led to high maintenance costs and difficulty in keeping CUJ definitions and their corresponding SLOs up-to-date.</li>
<li><strong>Opaque Impact of SLO Degradation:</strong> When SLOs were not met, the impact on users was unclear, making it difficult to prioritize responses and hindering broader utilization of CUJ-based SLOs across Mercari.</li>
</ol>
<p>Challenge 3, in particular, resulted in a lack of comprehensive maintenance since the initial implementation around 2021, potentially leading to gaps in monitored APIs. To address these issues and enable effective use of CUJ-based SLOs across Mercari for reliability improvements and incident response, we decided on a complete rebuild.</p>
<h2>Overview of the User Journey SLO</h2>
<p>To address the first two challenges—unclear CUJ definitions and multiple SLOs per CUJ—I&#8217;ll explain how we defined and managed CUJs within our User Journey SLO framework and how we established corresponding Service Level Indicators (SLIs).</p>
<h3>Defining Critical User Journeys (CUJs)</h3>
<p>For User Journey SLOs, we maintained a similar level of granularity to our previously defined CUJs, encompassing tasks like product listing, purchasing, and searching. We revisited and redefined approximately 40 CUJs, covering both major and minor user flows. To address the unclear definition challenge, we documented each CUJ using screen operation transition diagrams, explicitly outlining the expected screen transitions resulting from user actions. We also defined the available states for each screen. A CUJ is considered available if these states are met and unavailable if not. Generally, if the core functions of a CUJ are available, the CUJ is considered available. Secondary features, such as suggestions, that don&#8217;t impact core functionality are not considered in the availability calculation.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/2bf78c3d-03_lite-listing.png" alt="" /></p>
<h3>Defining the SLI</h3>
<p>To address the multiple SLOs per CUJ challenge, we defined SLIs to establish a one-to-one relationship between each CUJ and its availability and latency metrics. These SLIs are measurable using our existing observability tools. At Mercari, a single customer operation typically involves multiple API calls, as we generally don&#8217;t utilize a Backend for Frontend (BFF) architecture.</p>
<p>Ideally, we would directly measure the success of each screen transition within a CUJ. However, we currently lack the infrastructure for such granular measurement. While we considered implementing new mechanisms, the engineering cost of covering approximately 40 CUJs across all clients (iOS, Android, and web) was prohibitive. We also explored leveraging Real-Time User Monitoring (RUM) data from our Application Performance Management (APM) tools, but sampling rates, cost, and feasibility concerns made this approach impractical.</p>
<p>Therefore, we opted to associate the critical APIs called during a CUJ with the CUJ&#8217;s SLI. We categorized API calls within a CUJ into two types: (1) those whose failure directly results in CUJ unavailability, and (2) those whose failure does not. To create more accurate and robust SLIs, we focused solely on those in the first category—the critical APIs—for our SLI calculations.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/2e8c670a-04_critical_api-e1733301725194.png" alt="" /></p>
<p>Using metrics from these critical APIs, we uniquely defined the availability and latency SLIs for each CUJ as follows:</p>
<ul>
<li><strong>Availability:</strong> The CUJ&#8217;s success rate is the product of the success rates of its critical APIs. For example, if critical APIs A and B have success rates <em>S<sub>A</sub></em> and <em>S<sub>B</sub></em>, respectively, the CUJ success rate <em>S<sub>CUJ</sub></em> is calculated as :<br />
<em>S<sub>CUJ</sub></em> = <em>S<sub>A</sub></em> × <em>S<sub>B</sub></em></li>
<li><strong>Latency:</strong>The CUJ&#8217;s achievement rate for its latency target is the lowest target achievement rate among its critical APIs. For example, if critical APIs A and B have achievement rates <em>A<sub>A</sub></em> and <em>A<sub>B</sub></em> for their respective latency targets, the CUJ achievement rate <em>A<sub>CUJ</sub></em> is calculated as:<br />
<em>A<sub>CUJ</sub></em> = min(<em>A<sub>A</sub></em>, <em>A<sub>B</sub></em>)</li>
</ul>
<h3>Identifying Critical APIs</h3>
<p>To implement the SLI calculations described above, we needed to identify the critical APIs for each CUJ. We considered various methods, including static code analysis, but ultimately chose a hands-on approach using a real application to balance practicality, feasibility, and accuracy. This process involved the following steps:</p>
<ol>
<li><strong>Proxy and Record:</strong> We placed a proxy between a development build of our iOS app and a development environment. We then executed each CUJ, recording all API calls made during the process.</li>
<li><strong>Fault Injection and Validation:</strong> Using the proxy, we injected faults by forcing specific APIs to return 500 errors. We then re-executed the CUJ to determine whether the failure of each API resulted in the CUJ becoming unavailable according to our defined criteria.</li>
</ol>
<p>We used a development build of our iOS app for this process, as it is our most frequently used client.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/9c0d93b7-05_proxy-e1733301842561.png" alt="" /></p>
<p>Communication between our client apps and servers is typically encrypted. Therefore, we selected a proxy capable of inspecting and modifying encrypted traffic. We chose the open-source tool <a href="https://mitmproxy.org/">mitmproxy</a> for its interactive web interface and extensibility through add-on development.</p>
<p>The User Journey SLO framework, established with the approach described above, enables us to detect incidents affecting specific CUJs, allowing for immediate identification of the impact scope and faster prioritization of incident response efforts.</p>
<h2>Continuous Update and Visualization Using E2E Test</h2>
<p>Next, to address the third challenge—cumbersome updates—I&#8217;ll explain how we maintain critical API information using iOS end-to-end (E2E) tests. I&#8217;ll also describe our dashboard visualization approach, which resolves the fourth challenge—opaque impact of SLO degradation.</p>
<h3>The Need for Automation</h3>
<p>The Mercari client app undergoes multiple releases each month. Additionally, <a href="https://engineering.mercari.com/blog/entry/20231211-large-team-development-at-mercari-ios/">trunk-based development</a> and feature flags allow us to release new features without requiring app store updates. Tracking all these changes manually is impractical for the SRE team. Manually investigating frequent changes to critical APIs is also infeasible. Undetected changes could lead to monitoring gaps or unnecessary monitoring of deprecated APIs. Therefore, automating the update process for critical APIs is essential to keep up with the changes in application</p>
<h3>Automating with iOS E2E Tests</h3>
<p>We leveraged our existing iOS app E2E test suite, built using the <a href="“https://developer.apple.com/documentation/xctest”">XCTest framework</a>, to automate the extraction of critical APIs.</p>
<p>Specifically, we implemented each CUJ as an XCTest test case, executable on simulators. Each test case includes assertions to verify the availability of the CUJ according to our defined criteria. This setup automatically distinguishes between available and unavailable CUJs. Furthermore, the test cases are version-controlled alongside the app&#8217;s source code.</p>
<p>We developed a mitmproxy add-on to retrieve the list of APIs called during each test and to inject failures into specific APIs. This add-on provides an API to control the proxy, allowing us to manage it directly from our test cases and scripts.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/82b2bbc5-06_proxy_addon-e1733301902654.png" alt="" /></p>
<p>We automated the critical API identification process by scripting the execution of these XCTest tests and controlling the proxy through the add-on. The results, including whether each called API is critical to the CUJ, are logged to BigQuery. Screenshots of the app&#8217;s behavior during fault injection are stored in Google Cloud Storage (GCS).</p>
<p>Test results logged in BigQuery are identified by unique IDs, allowing for efficient comparison with previous test runs. We also use Terraform modules, specifically designed for User Journey SLOs, to define and manage SLOs, monitors, and dashboards in our APM system. This allows us to seamlessly integrate changes and easily add new CUJs.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/45bc74df-07_workflow-e1733301956779.png" alt="" /></p>
<p>This automation provides several key benefits:</p>
<ul>
<li><strong>Reduced Maintenance:</strong> The process is almost entirely automated, aside from code maintenance for the tests themselves.</li>
<li><strong>Version Control:</strong> Both the test cases and the app code are version-controlled in the same repository, ensuring consistency.</li>
<li><strong>Efficient Integration:</strong> ID-based management of test results facilitates seamless integration with our APM system.</li>
</ul>
<p>Ultimately, we created approximately 60 test cases covering around 40 CUJs. This automation drastically reduced the manual effort required, achieving a 99% reduction in maintenance time compared to manual SLO management.</p>
<h3>Dashboard Visualization</h3>
<p>A key goal of the User Journey SLO framework is to empower teams beyond SRE, such as incident response and customer support, with actionable insights. To achieve this, we needed to present up-to-date information about critical APIs and CUJ behavior during outages in an easily accessible format. We used Looker Studio to visualize this data, providing dashboards that display the list of API calls for each CUJ and screenshots of the app&#8217;s behavior during API failures.</p>
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2024/12/1fa0a74c-08_dashboard.png" alt="" /></p>
<h2>Current Status and Future Directions</h2>
<p>Through the initiatives described above, we successfully implemented the following for our User Journey SLOs:</p>
<ul>
<li>Clarifying the definition of CUJs</li>
<li>Establishing a one-to-one relationship between each CUJ and its corresponding Service Level Indicator (SLI)</li>
<li>Automating the maintenance of CUJs and SLOs</li>
<li>Visualizing the behavior of each CUJ during incidents through dashboards</li>
</ul>
<p>We currently operate SLOs for approximately 40 CUJs, utilizing around 60 test cases. While currently undergoing trial usage within the SRE team, even at this stage, the new SLOs have significantly improved:</p>
<ul>
<li>Incident detection speed and accuracy</li>
<li>Accuracy of impact assessment</li>
<li>Speed of root cause identification</li>
<li>Overall quality visibility</li>
</ul>
<p>Quantitatively, we&#8217;ve observed the following improvements:</p>
<ul>
<li><strong>Immediate impact assessment:</strong> Achieved <strong>near-zero time triage</strong>, meaning we can now start assessing impact within seconds of an incident being detected</li>
<li><strong>Reduced maintenance overhead:</strong> Achieved a <strong>99% reduction</strong> in SLO maintenance time.</li>
</ul>
<p>Building on these positive results, we plan to expand the use of User Journey SLOs beyond the SRE team, focusing on:</p>
<ul>
<li>Integrating SLOs into our internal incident management criteria</li>
<li>Leveraging User Journey SLOs to improve customer support responses</li>
</ul>
<h2>Conclusion</h2>
<p>This article explored how Mercari implements and operates User Journey SLOs based on CUJs, detailing the specifics of our SLI/SLO definitions and our automated maintenance process using iOS end-to-end testing. We hope this provides valuable insights into managing SLIs and SLOs for complex systems.</p>
<p>Tomorrow&#8217;s article will be by &#8230;.rina&#8230;. . Look forward to it!</p>
</div></div><!--astro:end--></astro-island> <div class="_contents_shareButtons_11e9j_18"> <astro-island uid="WFcdj" component-url="/_astro/ShareButtons.Dw0B3qRt.js" component-export="ShareButtons" renderer-url="/_astro/client.DNGgaD7G.js" props="{&quot;pathname&quot;:[0,&quot;/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/&quot;],&quot;title&quot;:[0,&quot;Keeping User Journey SLOs Up-to-Date with E2E Testing in a Microservices Architecture&quot;],&quot;tags&quot;:[1,[[0,{&quot;name&quot;:[0,&quot;AdventCalendar&quot;],&quot;slug&quot;:[0,&quot;adventcalendar&quot;]}],[0,{&quot;name&quot;:[0,&quot;iOS&quot;],&quot;slug&quot;:[0,&quot;ios&quot;]}],[0,{&quot;name&quot;:[0,&quot;microservices&quot;],&quot;slug&quot;:[0,&quot;microservices&quot;]}],[0,{&quot;name&quot;:[0,&quot;SLO&quot;],&quot;slug&quot;:[0,&quot;slo&quot;]}],[0,{&quot;name&quot;:[0,&quot;sre&quot;],&quot;slug&quot;:[0,&quot;sre&quot;]}]]]}" ssr="" client="load" opts="{&quot;name&quot;:&quot;ShareButtons&quot;,&quot;value&quot;:true}" await-children=""><div class="_share-button_siy4t_18"><ul class="_share-button_list_siy4t_18"><li class="_share-button_item_siy4t_23"><a href="https://twitter.com/intent/tweet?url=https://engineering.mercari.com%0a&amp;text=Keeping%20User%20Journey%20SLOs%20Up-to-Date%20with%20E2E%20Testing%20in%20a%20Microservices%20Architecture%20%7C%20Mercari%20Engineering&amp;via=MercariDev&amp;hashtags=SLO,iOS%0a&amp;related=MercariDev" rel="noopener" target="_blank" class="_share-button_link_siy4t_27"><img src="/img/x.svg" class="_share-button_img_siy4t_42 _img_x_siy4t_54" alt="X"/></a></li><li class="_share-button_item_siy4t_23"><a href="https://www.facebook.com/sharer/sharer.php?u=https://engineering.mercari.com" rel="noopener" target="_blank" class="_share-button_link_siy4t_27"><img src="/img/share_icon_facebook.svg" class="_share-button_img_siy4t_42" alt="Facebook"/></a></li><li class="_share-button_item_siy4t_23"><a href="https://www.linkedin.com/sharing/share-offsite/?url=https://engineering.mercari.com" rel="noopener" target="_blank" class="_share-button_link_siy4t_27"><img src="/img/In-Blue-128@2x.png" class="_share-button_img_siy4t_42" alt="linkedin"/></a></li><li class="_share-button_item_siy4t_23"><a href="https://b.hatena.ne.jp/entry/" class="hatena-bookmark-button" data-hatena-bookmark-layout="basic-counter" data-hatena-bookmark-width="50" data-hatena-bookmark-height="30" title="このエントリーをはてなブックマークに追加"><img src="https://b.st-hatena.com/images/v4/public/entry-button/button-only@2x.png" alt="このエントリーをはてなブックマークに追加" width="20" height="20" style="border:none;"/></a></li></ul></div><!--astro:end--></astro-island> </div> <ul class="_tagList_wl3e1_18"><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/adventcalendar/"><svg xmlns="http://www.w3.org/2000/svg" width="25.027" height="25.027" viewBox="0 0 25.027 25.027" class="_icon_tag_wl3e1_29"><path id="パス_1041" data-name="パス 1041" d="M517.478,303.493l-4.679-4.679a.669.669,0,0,0-.942,0l-4.678,4.679a1.854,1.854,0,0,0-.472,1.138v17.475a.669.669,0,0,0,.667.666h9.909a.668.668,0,0,0,.666-.666V304.631A1.853,1.853,0,0,0,517.478,303.493Zm-5.15,4.168a2.347,2.347,0,1,1,2.347-2.347A2.348,2.348,0,0,1,512.328,307.661Z" transform="translate(-130.062 -569.453) rotate(45)" fill="currentColor"></path></svg><span><div>AdventCalendar</div></span></a></li><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/ios/"><svg xmlns="http://www.w3.org/2000/svg" width="25.027" height="25.027" viewBox="0 0 25.027 25.027" class="_icon_tag_wl3e1_29"><path id="パス_1041" data-name="パス 1041" d="M517.478,303.493l-4.679-4.679a.669.669,0,0,0-.942,0l-4.678,4.679a1.854,1.854,0,0,0-.472,1.138v17.475a.669.669,0,0,0,.667.666h9.909a.668.668,0,0,0,.666-.666V304.631A1.853,1.853,0,0,0,517.478,303.493Zm-5.15,4.168a2.347,2.347,0,1,1,2.347-2.347A2.348,2.348,0,0,1,512.328,307.661Z" transform="translate(-130.062 -569.453) rotate(45)" fill="currentColor"></path></svg><span><div>iOS</div></span></a></li><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/microservices/"><svg xmlns="http://www.w3.org/2000/svg" width="25.027" height="25.027" viewBox="0 0 25.027 25.027" class="_icon_tag_wl3e1_29"><path id="パス_1041" data-name="パス 1041" d="M517.478,303.493l-4.679-4.679a.669.669,0,0,0-.942,0l-4.678,4.679a1.854,1.854,0,0,0-.472,1.138v17.475a.669.669,0,0,0,.667.666h9.909a.668.668,0,0,0,.666-.666V304.631A1.853,1.853,0,0,0,517.478,303.493Zm-5.15,4.168a2.347,2.347,0,1,1,2.347-2.347A2.348,2.348,0,0,1,512.328,307.661Z" transform="translate(-130.062 -569.453) rotate(45)" fill="currentColor"></path></svg><span><div>microservices</div></span></a></li><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/slo/"><svg xmlns="http://www.w3.org/2000/svg" width="25.027" height="25.027" viewBox="0 0 25.027 25.027" class="_icon_tag_wl3e1_29"><path id="パス_1041" data-name="パス 1041" d="M517.478,303.493l-4.679-4.679a.669.669,0,0,0-.942,0l-4.678,4.679a1.854,1.854,0,0,0-.472,1.138v17.475a.669.669,0,0,0,.667.666h9.909a.668.668,0,0,0,.666-.666V304.631A1.853,1.853,0,0,0,517.478,303.493Zm-5.15,4.168a2.347,2.347,0,1,1,2.347-2.347A2.348,2.348,0,0,1,512.328,307.661Z" transform="translate(-130.062 -569.453) rotate(45)" fill="currentColor"></path></svg><span><div>SLO</div></span></a></li><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/sre/"><svg xmlns="http://www.w3.org/2000/svg" width="25.027" height="25.027" viewBox="0 0 25.027 25.027" class="_icon_tag_wl3e1_29"><path id="パス_1041" data-name="パス 1041" d="M517.478,303.493l-4.679-4.679a.669.669,0,0,0-.942,0l-4.678,4.679a1.854,1.854,0,0,0-.472,1.138v17.475a.669.669,0,0,0,.667.666h9.909a.668.668,0,0,0,.666-.666V304.631A1.853,1.853,0,0,0,517.478,303.493Zm-5.15,4.168a2.347,2.347,0,1,1,2.347-2.347A2.348,2.348,0,0,1,512.328,307.661Z" transform="translate(-130.062 -569.453) rotate(45)" fill="currentColor"></path></svg><span><div>sre</div></span></a></li></ul> </div> </section> <section class="_relatedPosts_1e0te_18"><div class="container"><h2>Related article</h2><ul class="_post-list_1e0te_25"><li class="_post-list__item_1e0te_28"><a href="/en/blog/entry/20260619-scaling-myself-how-i-run-22-claude-code-sessions-for-ds4-migration/" class="_post-list__link_1e0te_35"><div class="_card_p1it6_19 false"><time datetime="2026-06-22">2026/06/22</time><div class="_post_p1it6_28"><img class="_post__thumbnail_p1it6_82" src="https://storage.googleapis.com/prd-engineering-asset/2026/05/36c24ace-merpaymercoin_ogp.png" alt="Scaling Myself: How I Run 22 Claude Code Sessions for DS4 Migration"/><div class="_post__text_p1it6_93"><h3 class="_post__title_p1it6_105">Scaling Myself: How I Run 22 Claude Code Sessions for DS4 Migration</h3><div class="_post__meta_p1it6_117"><div class="_meta-wrap_p1it6_148"><ul class="_tag-list_d76db_18 tag-list"><li class="_tag-list__item_d76db_29"><p>AI</p></li><li class="_tag-list__item_d76db_29"><p>Client side</p></li></ul><p class="_author_p1it6_168">Author:<span class="_author__name_p1it6_176"> cyan</span></p></div><div class="_post__to-post_p1it6_128"><div class="_post__link_p1it6_28"><img src="/img/arrow.svg" width="14" height="9" alt="To post"/></div></div></div></div></div></div></a></li><li class="_post-list__item_1e0te_28"><a href="/en/blog/entry/20260108-naventryscope-the-missing-scope-in-android-hilt/" class="_post-list__link_1e0te_35"><div class="_card_p1it6_19 false"><time datetime="2026-01-13">2026/01/13</time><div class="_post_p1it6_28"><img class="_post__thumbnail_p1it6_82" src="https://storage.googleapis.com/prd-engineering-asset/2025/06/d232f046-eyecatch.png" alt="NavEntryScope: The missing scope in Android Hilt"/><div class="_post__text_p1it6_93"><h3 class="_post__title_p1it6_105">NavEntryScope: The missing scope in Android Hilt</h3><div class="_post__meta_p1it6_117"><div class="_meta-wrap_p1it6_148"><ul class="_tag-list_d76db_18 tag-list"><li class="_tag-list__item_d76db_29"><p>Client side</p></li><li class="_tag-list__item_d76db_29"><p>Development</p></li></ul><p class="_author_p1it6_168">Author:<span class="_author__name_p1it6_176"> luca</span></p></div><div class="_post__to-post_p1it6_128"><div class="_post__link_p1it6_28"><img src="/img/arrow.svg" width="14" height="9" alt="To post"/></div></div></div></div></div></div></a></li><li class="_post-list__item_1e0te_28"><a href="/en/blog/entry/20251225-building-egp-cards-at-merpay/" class="_post-list__link_1e0te_35"><div class="_card_p1it6_19 false"><time datetime="2025-12-25">2025/12/25</time><div class="_post_p1it6_28"><img class="_post__thumbnail_p1it6_82" src="https://storage.googleapis.com/prd-engineering-asset/2025/12/cf971c51-img_selfie-mercari-landscape.png" alt="Building EGP Cards at Merpay: Lessons from a Frontend Internship"/><div class="_post__text_p1it6_93"><h3 class="_post__title_p1it6_105">Building EGP Cards at Merpay: Lessons from a Frontend Internship</h3><div class="_post__meta_p1it6_117"><div class="_meta-wrap_p1it6_148"><ul class="_tag-list_d76db_18 tag-list"><li class="_tag-list__item_d76db_29"><p>Client side</p></li></ul><p class="_author_p1it6_168">Author:<span class="_author__name_p1it6_176"> Yusaku Miyata</span></p></div><div class="_post__to-post_p1it6_128"><div class="_post__link_p1it6_28"><img src="/img/arrow.svg" width="14" height="9" alt="To post"/></div></div></div></div></div></div></a></li></ul></div></section> <script>(()=>{var e=async t=>{await(await t())()};(self.Astro||(self.Astro={})).only=e;window.dispatchEvent(new Event("astro:only"));})();</script><astro-island uid="gmbUv" component-url="/_astro/ButtonToTop.DpQxT0b_.js" component-export="ButtonToTop" renderer-url="/_astro/client.DNGgaD7G.js" props="{}" ssr="" client="only" opts="{&quot;name&quot;:&quot;ButtonToTop&quot;,&quot;value&quot;:&quot;preact&quot;}"></astro-island> </main> <footer id="the-footer" class="_footer_zthyf_19"> <div class="container"> <ul class="_navigation_zthyf_32"> <li class="_navigation__item_zthyf_43 undefined"> <div class="_menu__heading_zthyf_46">Company</div> <ul> <li class="_menu__item_zthyf_60"> <a href="https://about.mercari.com/en/" rel="noopener" target="_blank"> Mercari, Inc </a> </li><li class="_menu__item_zthyf_60"> <a href="https://en.merpay.com/" rel="noopener" target="_blank"> Merpay, Inc </a> </li><li class="_menu__item_zthyf_60"> <a href="https://www.mercari.com/about/" rel="noopener" target="_blank"> Mercari US </a> </li><li class="_menu__item_zthyf_60"> <a href="https://about.mercoin.com/en/" rel="noopener" target="_blank"> Mercoin </a> </li><li class="_menu__item_zthyf_60"> <a href="https://about.in.mercari.com/" rel="noopener" target="_blank"> Mercari India </a> </li> </ul> </li><li class="_navigation__item_zthyf_43 undefined"> <div class="_menu__heading_zthyf_46">Owned media</div> <ul> <li class="_menu__item_zthyf_60"> <a href="https://mercan.mercari.com/en/" rel="noopener" target="_blank"> mercan </a> </li><li class="_menu__item_zthyf_60"> <a href="https://note.com/mercari_design/" rel="noopener" target="_blank"> Design blog </a> </li><li class="_menu__item_zthyf_60"> <a href="https://ai.mercari.com/en/" rel="noopener" target="_blank"> AI Web </a> </li><li class="_menu__item_zthyf_60"> <a href="https://note.com/mercari_data" rel="noopener" target="_blank"> Analytics blog </a> </li><li class="_menu__item_zthyf_60"> <a href="https://r4d.mercari.com/en/" rel="noopener" target="_blank"> mercari R4D </a> </li><li class="_menu__item_zthyf_60"> <a href="https://blog.mercari.com/making-mercari/home" rel="noopener" target="_blank"> Engineering blog (USA) </a> </li> </ul> </li><li class="_navigation__item_zthyf_43 undefined"> <div class="_menu__heading_zthyf_46">Careers</div> <ul> <li class="_menu__item_zthyf_60"> <a href="https://careers.mercari.com/job-categories/engineering/" rel="noopener" target="_blank"> Engineering </a> </li><li class="_menu__item_zthyf_60"> <a href="https://careers.mercari.com/" rel="noopener" target="_blank"> Mercari (JP) </a> </li><li class="_menu__item_zthyf_60"> <a href="https://www.mercari.com/careers/" rel="noopener" target="_blank"> Mercari (USA) </a> </li><li class="_menu__item_zthyf_60"> <a href="https://about.in.mercari.com/join-us/" rel="noopener" target="_blank"> Mercari (India) </a> </li> </ul> </li><li class="_navigation__item_zthyf_43 undefined"> <div class="_menu__heading_zthyf_46">Resources</div> <ul> <li class="_menu__item_zthyf_60"> <a href="https://github.com/mercari" rel="noopener" target="_blank"> GitHub - mercari </a> </li><li class="_menu__item_zthyf_60"> <a href="https://speakerdeck.com/mercari" rel="noopener" target="_blank"> Speakerdeck - mercari </a> </li> </ul> </li><li class="_navigation__item_zthyf_43 undefined"> <div class="_menu__heading_zthyf_46">Events</div> <ul> <li class="_menu__item_zthyf_60"> <a href="https://mercari.connpass.com/" rel="noopener" target="_blank"> connpass - Mercari </a> </li><li class="_menu__item_zthyf_60"> <a href="https://www.meetup.com/ja-JP/MercariDev/" rel="noopener" target="_blank"> Meetup.com </a> </li> </ul> </li> </ul> <div class="_brand_zthyf_98"> <a href="/en/"> <img src="/img/mercari_white.svg" alt="mercari" width="140" height="29"> </a> </div> <small class="_copyright_zthyf_108"> <span class="_copyright__mark_zthyf_121">&copy;</span>2020 Mercari, Inc.
</small> </div> </footer> <script>(function(){const pageViewEvent = {"routeName":"/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/","pageType":"PageView","pageUrl":"/en/blog/entry/20241204-keeping-user-journey-slos-up-to-date-with-e2e-testing-in-a-microservices-architecture/","event":"page_view"};
/**
* `@nuxtjs/gtm` から移行
* @see https://github.com/nuxt-community/gtm-module/blob/ae9199e6cab39485bcc85758bdfb36ebace3cdcf/lib/plugin.mock.js#L8-L20
*/
dataLayer.push({ ...pageViewEvent, pageTitle: document.title });
})();</script> </body> </html> <script>(function(){const contentGroup = {"Categories":"Client side,Development,Infrastructure","Tags":"AdventCalendar,iOS,microservices,SLO,sre","Authors":"yakenji"};
// コンテンツグループをセット(GA4)
dataLayer.push(contentGroup);
})();</script>