189 lines
76 KiB
HTML
189 lines
76 KiB
HTML
<!DOCTYPE html><html lang="en-US"> <head><title>Moving to cloud: How to do Migrations the wrong way | 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/20221218-migrations-the-wrong-way/"><meta name="description" content="This post is for Day 18 of Mercari Advent Calendar 2022, brought to you by @kaustubh from the Metadata Ecosystem team.M"><meta name="robots" content="index, follow"><meta property="og:title" content="Moving to cloud: How to do Migrations the wrong way | Mercari Engineering"><meta property="og:type" content="website"><meta property="og:image" content="https://storage.googleapis.com/prd-engineering-asset/2022/12/df7322a7-chris-briggs-v72hk6ljjji-unsplash-scaled.jpg"><meta property="og:url" content="https://engineering.mercari.com/en/blog/entry/20221218-migrations-the-wrong-way/"><meta property="og:description" content="This post is for Day 18 of Mercari Advent Calendar 2022, brought to you by @kaustubh from the Metadata Ecosystem team.M"><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="" hreflang="ja"><link rel="alternate" href="" hreflang="ja-JP"><link rel="alternate" href="https://engineering.mercari.com/en/blog/entry/20221218-migrations-the-wrong-way/" hreflang="en"><link rel="alternate" href="https://engineering.mercari.com/en/blog/entry/20221218-migrations-the-wrong-way/" 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 18 of Mercari Advent Calendar 2022, brought to you by @kaustubh from the Metadata Ecosystem team.M"><meta property="og:description" content="This post is for Day 18 of Mercari Advent Calendar 2022, brought to you by @kaustubh from the Metadata Ecosystem team.M"><meta property="og:url" content="https://engineering.mercari.com/en/blog/entry/20221218-migrations-the-wrong-way/"><meta property="og:image" content="https://storage.googleapis.com/prd-engineering-asset/2022/12/df7322a7-chris-briggs-v72hk6ljjji-unsplash-scaled.jpg"><meta property="og:title" content="Moving to cloud: How to do Migrations the wrong way"><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="Z1VLuDo" component-url="/_astro/TheHeader.ByGQ2pxB.js" component-export="TheHeader" renderer-url="/_astro/client.DNGgaD7G.js" props="{"currentPath":[0,"/en/blog/entry/20221218-migrations-the-wrong-way/"],"categories":[0,{"jp":[1,[[0,{"uri":[0,"/category/ai/"],"name":[0,"AI"],"totalPosts":[0,116]}],[0,{"uri":[0,"/category/backend/"],"name":[0,"Backend"],"totalPosts":[0,275]}],[0,{"uri":[0,"/category/client-side/"],"name":[0,"Client side"],"totalPosts":[0,161]}],[0,{"uri":[0,"/category/development/"],"name":[0,"Development"],"totalPosts":[0,234]}],[0,{"uri":[0,"/category/infrastructure/"],"name":[0,"Infrastructure"],"totalPosts":[0,149]}],[0,{"uri":[0,"/category/organization/"],"name":[0,"Organization"],"totalPosts":[0,195]}],[0,{"uri":[0,"/category/qa/"],"name":[0,"QA"],"totalPosts":[0,89]}],[0,{"uri":[0,"/category/research-advanced-tech/"],"name":[0,"Research &amp; Advanced Tech"],"totalPosts":[0,31]}],[0,{"uri":[0,"/category/security/"],"name":[0,"Security"],"totalPosts":[0,34]}]]],"en":[1,[[0,{"uri":[0,"/category/ai/"],"name":[0,"AI"],"totalPosts":[0,59]}],[0,{"uri":[0,"/category/backend/"],"name":[0,"Backend"],"totalPosts":[0,88]}],[0,{"uri":[0,"/category/client-side/"],"name":[0,"Client side"],"totalPosts":[0,85]}],[0,{"uri":[0,"/category/development/"],"name":[0,"Development"],"totalPosts":[0,117]}],[0,{"uri":[0,"/category/infrastructure/"],"name":[0,"Infrastructure"],"totalPosts":[0,84]}],[0,{"uri":[0,"/category/organization/"],"name":[0,"Organization"],"totalPosts":[0,74]}],[0,{"uri":[0,"/category/qa/"],"name":[0,"QA"],"totalPosts":[0,25]}],[0,{"uri":[0,"/category/research-advanced-tech/"],"name":[0,"Research &amp; Advanced Tech"],"totalPosts":[0,11]}],[0,{"uri":[0,"/category/security/"],"name":[0,"Security"],"totalPosts":[0,40]}]]]}]}" ssr="" client="load" opts="{"name":"TheHeader","value":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/20221218-migrations-the-wrong-way/">日本語</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 & 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/20221218-migrations-the-wrong-way/">日本語</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="2022-12-18">2022/12/18</time><div><div class="_post-meta_1jn14_18"><h1 class="_post-title_1jn14_23 "><div>Moving to cloud: How to do Migrations the wrong way</div></h1><ul class="_tag-list_d76db_18 tag-list"><li class="_tag-list__item_d76db_29"><a href="/en/blog/category/development/">Development</a></li></ul><dl class="_post-author_1c1i9_18"><dt>Author:</dt><dd><a href="/en/blog/author/kaustubh/"><span class="_post-author_name_1c1i9_28 post-author_name">Kaustubh Hiware</span></a></dd></dl><span> , <time datetime="2022-12-18">2022/12/18</time></span></div></div><img src="https://storage.googleapis.com/prd-engineering-asset/2022/12/df7322a7-chris-briggs-v72hk6ljjji-unsplash-scaled.jpg" alt="Moving to cloud: How to do Migrations the wrong way" class="_post__thumbnail_1eyul_24"/><div class="_lang-switch_1eyul_40"></div></div></div> <section> <div class="container _container_11e9j_22 container--inner"> <astro-island uid="Z2aYXYI" component-url="/_astro/PageContent.CfXlRJsU.js" component-export="PageContent" renderer-url="/_astro/client.DNGgaD7G.js" props="{"html":[0,"<p>This post is for Day 18 of <a href=\"https://engineering.mercari.com/en/blog/entry/20221124-mercari-advent-calendar-2022/\">Mercari Advent Calendar 2022</a>, brought to you by <a href=\"https://twitter.com/_ofkaus\">@kaustubh</a> from the Metadata Ecosystem team.</p>\n<p>My team recently moved databases from local files in the codebase to an online Database. It took longer than expected but with good reason.</p>\n<p>Wait, did you say local files?<br />\nOne of the services my team maintains started as a proof-of-concept, focusing on a few e-commerce categories only. But unfortunately, we suffered from success. That meant we needed to expand our Metadata dataset to a large number of categories rather quickly.</p>\n<p>Since serving the data had higher priority, and new data was added only once a month, data addition was not really a mission-critical feature to have. Until we struggled under the massive weight of positive results, and needed to effectively 10x our data size and 10x our traffic, at the same time.</p>\n<p style=\"font-size:0.7em\">\n(Cover photo by <a href=\"https://unsplash.com/fr/@cgbriggs19?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Chris Briggs</a> on <a href=\"https://unsplash.com/s/photos/migration?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a>)\n</p>\n<h2>Data addition as it was in the past</h2>\n<p>Mercari is a C2C marketplace, meaning there could be multiple listings of iPhones. A lot of details about these iPhones can be different (price, description) but some of the details will always have a finite set of options (like brand, color, iphone storage size), which we call metadata. My team manages &amp; serves such finite sets and details. </p>\n<p>You can see everything in the Mercari system that our team affects <a href=\"https://engineering.mercari.com/en/blog/entry/20211201-why-is-metadata-important/\">here</a>. </p>\n<p>Any time a new brand or a product is launched in the market, we should have that new brand or product details available as metadata.We had a few bots and automations in place for the new data addition workflow. </p>\n<ol>\n<li>New data was aggregated manually (needs manual checks before addition)</li>\n<li>The product manager prepared the data in a specified sheet format.</li>\n<li>A slack bot first validates this spreadsheet, and then converts the spreadsheet into files to be added to the code repository as a PR.</li>\n<li>An engineer approves the PR, and deploys it to the dev environment.</li>\n<li>QA for sanity checks</li>\n<li>Engineer releases it to production</li>\n</ol>\n<p><kbd></p>\n<p><img src=\"https://storage.googleapis.com/prd-engineering-asset/2022/12/eb67e31e-new-metadata-old.png\" width=\"800\"><figcaption align=\"center\">Data addition workflow in the past</figcaption><p></kbd></p>\n<h2>Why don’t we leave it at that ?</h2>\n<p>The workflow can be stopped at any of these points:</p>\n<ol>\n<li>Data validation required new rules, pretty much every time we added data. </li>\n<li>If data isn’t the issue, the PM is blocked by both engineer approval and dev release to start the QA the new data.</li>\n<li>If dev QA fails? Start over.</li>\n</ol>\n<p>The first point may seem a bit odd, but in reality similar brand names exist with just the slightest of differences so that each of them can be unique. For example, there may already be a brand named “Brand” in the dataset, but if a new brand called &quot;Brãnd&quot; is launched, we&#8217;ll have to add an exception to our validation rules to allow this ã.</p>\n<p>The above points would not have been a concern if we’re adding data in just two batches every quarter. But things changed. We progressed further along the <a href=\"https://www.stratechi.com/adoption-curves/\">adoption curve</a>, and more teams wanted additional data. Which meant data addition was going to happen every 2-3 weeks. So the local storage solution wasn’t gonna cut it.</p>\n<h2>The task at hand</h2>\n<p>What we wanted to achieve:</p>\n<ol>\n<li>Product Manager should be able to add data </li>\n<li>PM should be able to roll it out to production (without engineer intervention)</li>\n<li>The service should work with no performance drops, latency changes within bounds.</li>\n</ol>\n<p>So our proposed solution was this:</p>\n<ol>\n<li>Build a bare bones UI that PMs can use to manipulate data.\n<ul>\n<li>This UI could be used by external collaborators, because a permalink is better than a SQL query.</li>\n</ul>\n</li>\n<li>Update the service to call an online DB, instead of local variables. (that was not a db)</li>\n</ol>\n<p>We figured the UI can directly manipulate dev data, and once QA is done, there would be a big red button to sync dev and prod data. The team decided the functional requirements, and solidified the solution with a design doc. The team arrived on a consensus and the PM also seemed happy about it</p>\n<p>On the backend, our service performs the following tasks:</p>\n<ol>\n<li>Validation\n<ul>\n<li>Check whether we’re storing the right metadata for each item. This is important because certain metadata options might be disabled, or made temporarily unavailable. </li>\n</ul>\n</li>\n<li>Listing\n<ul>\n<li>There are multiple sources for metadata for an item: the only one from users is when sellers add it for listing.</li>\n</ul>\n</li>\n<li>Worker\n<ul>\n<li>Mercari uses PubSub for communicating between services / workers owned by different teams. This worker listened to listing events, and published to a few consumers.</li>\n</ul>\n</li>\n</ol>\n<p>These were the 3 tasks that we came up with: 3 tasks that 3 engineers can work on. Another engineer can work on the UI part.</p>\n<p><kbd></p>\n<p><img src=\"https://storage.googleapis.com/prd-engineering-asset/2022/12/ac2887dd-data-addition-new-metadata.png\" width=\"800\"><figcaption align=\"center\">Proposed Data addition workflow</figcaption><p></kbd></p>\n<p>Sounds straightforward, right ? Few sprints and we should be done, or at least this is what we sold to our Engineering Manager.</p>\n<h2>Hiccups before start</h2>\n<p><em>Anything that can go wrong will go wrong &#8211; Murphy.</em></p>\n<p><strong>Plug and Pause</strong>: Our initial plan was to write the UI / backend for UI in Node.js, because another team had already written what we wanted in JS. The problem with that approach was:</p>\n<ol>\n<li>The UI was too tightly coupled with the other team’s architecture, making it harder to adapt.</li>\n<li>The UI had different use cases than what we were looking for.</li>\n<li>Our codebase was in go &amp; python only, and just 1-2 members in the team were comfortable with JS.</li>\n</ol>\n<p><strong>Rations &amp; responsibilities</strong>: Our team was a backend team, we didn’t have any web engineers in our team, which meant that the UI must be maintained by people who were not too familiar with frontend development. </p>\n<p>At the time, Mercari was working on a <a href=\"https://mercan.mercari.com/en/articles/35887/\">major rewrite</a> so we weren’t going to get any web-side help for some time. This becomes relevant later.</p>\n<hr />\n<p>Regardless of the challenges we knew upfront, the team had a positive outlook and we were pumped to roll this out.</p>\n<h2>Engineers at work</h2>\n<figure>\n<img src=\"https://storage.googleapis.com/prd-engineering-asset/2022/12/7e9af0cb-mark-konig-uu5fnokfada-unsplash-1024x576.jpg\" style=\"width:100%\"><figcaption align=\"right\">Photo by <a href=\"https://unsplash.com/@markkoenig?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\"> Mark König</a> on <a href=\"https://unsplash.com/s/photos/arrow-quiver?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></figcaption></figure>\n<p>We had a new data schema ready. Most of the code was written, reviewed, and ready to release. We expected a smooth rollout. </p>\n<h4>Put a pin in it</h4>\n<p>As mentioned above, we planned to release the 3 major chunks of rewrite as 3 tasks. The first one (validation) was already in production, working well. As our planned release date approached, a new complication showed up. The company level rewrite was to go live in the coming days. To truly assess if the rewrite was effective, all releases were put on hold for some time. That meant our plans for gradual releases had to be replaced with a one-shot release.</p>\n<h4>One-shot release</h4>\n<p>This wasn’t something we wanted to do, but numbers were crunched, traffic was estimated, and the release tag cut. To start off, the migrated release seemed to handle traffic well. But as peak traffic arrived, we were greeted by pagerduty alerts. &#8211; an increasing amount of requests were timed out.</p>\n<h4>Just sprinkle some replicas on it</h4>\n<p>For the data set we had, we predicted the db had enough computing resources to serve at peak traffic. That was not the case. During peak traffic, requests kept getting timed out by the DB. We decided to add three large replicas, and scale them down as required &#8211; but that was not sufficient either. </p>\n<h4>Cache me outside</h4>\n<p>We’d predicted we’d need a cache to improve our latency, so this was in our plan anyway &#8211; but as an improvement task. We started off with an external cache that all server and worker pods would access. We started with using an external cache, however it would turn out to be more complicated than a quick in-memory cache for each service pod. After spending an uncomfortably long period of time on implementing a single external cache, we instead implemented a rather quick in-memory cache that would get the job done.</p>\n<h4>Trust nobody &#8211; not even your own SQL code</h4>\n<p>Before we implemented the cache, the team agreed that the cache should not be a system-critical component of the architecture; it should be an enhancement. So we beefed up our DBs and replicas and did a last hail-mary release before releasing the cache. As traffic came in, so did the pagerduty alerts but the DB and replicas were not showing any problems.<br />\nAfter some service profiling, our Tech lead led us to glorious redemption with a few optimized SQL calls. The cause: We initially started with the simplest SQL query, and added <a href=\"https://leafo.net/guides/postgresql-preloading.html\">preloading</a> with the expectation it would speed up response time. It was doing the opposite in a few cases, so we removed preloading in a few non-service-critical queries, and that stabilized the performance. The cache further helped improve costs and performance, and we all lived happily ever after.</p>\n<h2>Conclusion: Making better mistakes</h2>\n<figure>\n<img src=\"https://storage.googleapis.com/prd-engineering-asset/2022/12/1ff43e65-motoki-tonn-zs4x24uiy9o-unsplash-1024x662.jpg\" style=\"width:100%\"><figcaption align=\"right\">Photo by <a href=\"https://unsplash.com/@motoki?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\"> Motoki Tonn</a> on <a href=\"https://unsplash.com/s/photos/arrow-quiver?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText\">Unsplash</a></figcaption></figure>\n<p>I organized a <a href=\"https://code-artisan.io/retrospective-method-kpt/\">KPT retrospective</a> for the project, to understand what we could have done better. </p>\n<h4>Under-promise, over-deliver</h4>\n<p>Communicating with the end users with just a design doc is not enough. Sometimes they don’t know what features they want unless they see actual mockups of the final product &#8211; then it’s easier for them to point out what they want or what they don’t want. As a result we had to continuously improve our data manipulation UI when PMs actually started using it, because they were not aware of some details.</p>\n<h4>Track everything</h4>\n<p>Before the release, we had 30 monitors and 6 observability dashboards. Now we have 40 monitors and 8 dashboards. For a project like this, a few metrics that we should have tracked from the beginning were:</p>\n<ul>\n<li>DB query time (the time to actually perform the query) and DB response time (the time between receiving the request and sending a response)</li>\n<li>Avg CPU, Memory, numbers of containers running &#8211; for the DB, not just the service</li>\n<li>Make better calculations &#8211; Back-of-the-envelope calculations should be restricted to non production releases, probably involving the architects and platform team to understand what metrics you need to calculate.</li>\n</ul>\n<h4>Granular releases</h4>\n<p>This was something we wanted to do from the start, but could not due to external factors. We should have not tried to release everything at once. We also should have questioned and reviewed our own code more, instead of having our releases reveal them to us.</p>\n<h4>Make your mistakes public</h4>\n<p>We intend to share our findings at an org-level internally so that other teams can save a lot of precious time, money, resources, ~sleep~ that we overspent. </p>\n<hr />\n<p>One of the things I truly appreciate about being at Mercari is the ability to own up to your mistakes and being able to write this kind of an article. The environment is friendly, yet nurturing, lenient yet accountable. If that does not sound like your current workplace,that can change. Here’s my post from our 2021 advent calendar about <a href=\"https://engineering.mercari.com/en/blog/entry/20211224-career-change-is-the-only-constant/\">career change</a>, and here is <a href=\"https://careers.mercari.com/\">our job portal</a>. Come join us, we have snacks!</p>\n<p>Tomorrow&#8217;s article will be presented by the US DRE team. Please look forward to it! </p>\n"]}" ssr="" client="load" opts="{"name":"PageContent","value":true}" await-children=""><div class="_body_1o0xy_19"><div class="page-content undefined"><p>This post is for Day 18 of <a href="https://engineering.mercari.com/en/blog/entry/20221124-mercari-advent-calendar-2022/">Mercari Advent Calendar 2022</a>, brought to you by <a href="https://twitter.com/_ofkaus">@kaustubh</a> from the Metadata Ecosystem team.</p>
|
||
<p>My team recently moved databases from local files in the codebase to an online Database. It took longer than expected but with good reason.</p>
|
||
<p>Wait, did you say local files?<br />
|
||
One of the services my team maintains started as a proof-of-concept, focusing on a few e-commerce categories only. But unfortunately, we suffered from success. That meant we needed to expand our Metadata dataset to a large number of categories rather quickly.</p>
|
||
<p>Since serving the data had higher priority, and new data was added only once a month, data addition was not really a mission-critical feature to have. Until we struggled under the massive weight of positive results, and needed to effectively 10x our data size and 10x our traffic, at the same time.</p>
|
||
<p style="font-size:0.7em">
|
||
(Cover photo by <a href="https://unsplash.com/fr/@cgbriggs19?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Chris Briggs</a> on <a href="https://unsplash.com/s/photos/migration?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>)
|
||
</p>
|
||
<h2>Data addition as it was in the past</h2>
|
||
<p>Mercari is a C2C marketplace, meaning there could be multiple listings of iPhones. A lot of details about these iPhones can be different (price, description) but some of the details will always have a finite set of options (like brand, color, iphone storage size), which we call metadata. My team manages & serves such finite sets and details. </p>
|
||
<p>You can see everything in the Mercari system that our team affects <a href="https://engineering.mercari.com/en/blog/entry/20211201-why-is-metadata-important/">here</a>. </p>
|
||
<p>Any time a new brand or a product is launched in the market, we should have that new brand or product details available as metadata.We had a few bots and automations in place for the new data addition workflow. </p>
|
||
<ol>
|
||
<li>New data was aggregated manually (needs manual checks before addition)</li>
|
||
<li>The product manager prepared the data in a specified sheet format.</li>
|
||
<li>A slack bot first validates this spreadsheet, and then converts the spreadsheet into files to be added to the code repository as a PR.</li>
|
||
<li>An engineer approves the PR, and deploys it to the dev environment.</li>
|
||
<li>QA for sanity checks</li>
|
||
<li>Engineer releases it to production</li>
|
||
</ol>
|
||
<p><kbd></p>
|
||
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2022/12/eb67e31e-new-metadata-old.png" width="800"><figcaption align="center">Data addition workflow in the past</figcaption><p></kbd></p>
|
||
<h2>Why don’t we leave it at that ?</h2>
|
||
<p>The workflow can be stopped at any of these points:</p>
|
||
<ol>
|
||
<li>Data validation required new rules, pretty much every time we added data. </li>
|
||
<li>If data isn’t the issue, the PM is blocked by both engineer approval and dev release to start the QA the new data.</li>
|
||
<li>If dev QA fails? Start over.</li>
|
||
</ol>
|
||
<p>The first point may seem a bit odd, but in reality similar brand names exist with just the slightest of differences so that each of them can be unique. For example, there may already be a brand named “Brand” in the dataset, but if a new brand called "Brãnd" is launched, we’ll have to add an exception to our validation rules to allow this ã.</p>
|
||
<p>The above points would not have been a concern if we’re adding data in just two batches every quarter. But things changed. We progressed further along the <a href="https://www.stratechi.com/adoption-curves/">adoption curve</a>, and more teams wanted additional data. Which meant data addition was going to happen every 2-3 weeks. So the local storage solution wasn’t gonna cut it.</p>
|
||
<h2>The task at hand</h2>
|
||
<p>What we wanted to achieve:</p>
|
||
<ol>
|
||
<li>Product Manager should be able to add data </li>
|
||
<li>PM should be able to roll it out to production (without engineer intervention)</li>
|
||
<li>The service should work with no performance drops, latency changes within bounds.</li>
|
||
</ol>
|
||
<p>So our proposed solution was this:</p>
|
||
<ol>
|
||
<li>Build a bare bones UI that PMs can use to manipulate data.
|
||
<ul>
|
||
<li>This UI could be used by external collaborators, because a permalink is better than a SQL query.</li>
|
||
</ul>
|
||
</li>
|
||
<li>Update the service to call an online DB, instead of local variables. (that was not a db)</li>
|
||
</ol>
|
||
<p>We figured the UI can directly manipulate dev data, and once QA is done, there would be a big red button to sync dev and prod data. The team decided the functional requirements, and solidified the solution with a design doc. The team arrived on a consensus and the PM also seemed happy about it</p>
|
||
<p>On the backend, our service performs the following tasks:</p>
|
||
<ol>
|
||
<li>Validation
|
||
<ul>
|
||
<li>Check whether we’re storing the right metadata for each item. This is important because certain metadata options might be disabled, or made temporarily unavailable. </li>
|
||
</ul>
|
||
</li>
|
||
<li>Listing
|
||
<ul>
|
||
<li>There are multiple sources for metadata for an item: the only one from users is when sellers add it for listing.</li>
|
||
</ul>
|
||
</li>
|
||
<li>Worker
|
||
<ul>
|
||
<li>Mercari uses PubSub for communicating between services / workers owned by different teams. This worker listened to listing events, and published to a few consumers.</li>
|
||
</ul>
|
||
</li>
|
||
</ol>
|
||
<p>These were the 3 tasks that we came up with: 3 tasks that 3 engineers can work on. Another engineer can work on the UI part.</p>
|
||
<p><kbd></p>
|
||
<p><img src="https://storage.googleapis.com/prd-engineering-asset/2022/12/ac2887dd-data-addition-new-metadata.png" width="800"><figcaption align="center">Proposed Data addition workflow</figcaption><p></kbd></p>
|
||
<p>Sounds straightforward, right ? Few sprints and we should be done, or at least this is what we sold to our Engineering Manager.</p>
|
||
<h2>Hiccups before start</h2>
|
||
<p><em>Anything that can go wrong will go wrong – Murphy.</em></p>
|
||
<p><strong>Plug and Pause</strong>: Our initial plan was to write the UI / backend for UI in Node.js, because another team had already written what we wanted in JS. The problem with that approach was:</p>
|
||
<ol>
|
||
<li>The UI was too tightly coupled with the other team’s architecture, making it harder to adapt.</li>
|
||
<li>The UI had different use cases than what we were looking for.</li>
|
||
<li>Our codebase was in go & python only, and just 1-2 members in the team were comfortable with JS.</li>
|
||
</ol>
|
||
<p><strong>Rations & responsibilities</strong>: Our team was a backend team, we didn’t have any web engineers in our team, which meant that the UI must be maintained by people who were not too familiar with frontend development. </p>
|
||
<p>At the time, Mercari was working on a <a href="https://mercan.mercari.com/en/articles/35887/">major rewrite</a> so we weren’t going to get any web-side help for some time. This becomes relevant later.</p>
|
||
<hr />
|
||
<p>Regardless of the challenges we knew upfront, the team had a positive outlook and we were pumped to roll this out.</p>
|
||
<h2>Engineers at work</h2>
|
||
<figure>
|
||
<img src="https://storage.googleapis.com/prd-engineering-asset/2022/12/7e9af0cb-mark-konig-uu5fnokfada-unsplash-1024x576.jpg" style="width:100%"><figcaption align="right">Photo by <a href="https://unsplash.com/@markkoenig?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText"> Mark König</a> on <a href="https://unsplash.com/s/photos/arrow-quiver?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption></figure>
|
||
<p>We had a new data schema ready. Most of the code was written, reviewed, and ready to release. We expected a smooth rollout. </p>
|
||
<h4>Put a pin in it</h4>
|
||
<p>As mentioned above, we planned to release the 3 major chunks of rewrite as 3 tasks. The first one (validation) was already in production, working well. As our planned release date approached, a new complication showed up. The company level rewrite was to go live in the coming days. To truly assess if the rewrite was effective, all releases were put on hold for some time. That meant our plans for gradual releases had to be replaced with a one-shot release.</p>
|
||
<h4>One-shot release</h4>
|
||
<p>This wasn’t something we wanted to do, but numbers were crunched, traffic was estimated, and the release tag cut. To start off, the migrated release seemed to handle traffic well. But as peak traffic arrived, we were greeted by pagerduty alerts. – an increasing amount of requests were timed out.</p>
|
||
<h4>Just sprinkle some replicas on it</h4>
|
||
<p>For the data set we had, we predicted the db had enough computing resources to serve at peak traffic. That was not the case. During peak traffic, requests kept getting timed out by the DB. We decided to add three large replicas, and scale them down as required – but that was not sufficient either. </p>
|
||
<h4>Cache me outside</h4>
|
||
<p>We’d predicted we’d need a cache to improve our latency, so this was in our plan anyway – but as an improvement task. We started off with an external cache that all server and worker pods would access. We started with using an external cache, however it would turn out to be more complicated than a quick in-memory cache for each service pod. After spending an uncomfortably long period of time on implementing a single external cache, we instead implemented a rather quick in-memory cache that would get the job done.</p>
|
||
<h4>Trust nobody – not even your own SQL code</h4>
|
||
<p>Before we implemented the cache, the team agreed that the cache should not be a system-critical component of the architecture; it should be an enhancement. So we beefed up our DBs and replicas and did a last hail-mary release before releasing the cache. As traffic came in, so did the pagerduty alerts but the DB and replicas were not showing any problems.<br />
|
||
After some service profiling, our Tech lead led us to glorious redemption with a few optimized SQL calls. The cause: We initially started with the simplest SQL query, and added <a href="https://leafo.net/guides/postgresql-preloading.html">preloading</a> with the expectation it would speed up response time. It was doing the opposite in a few cases, so we removed preloading in a few non-service-critical queries, and that stabilized the performance. The cache further helped improve costs and performance, and we all lived happily ever after.</p>
|
||
<h2>Conclusion: Making better mistakes</h2>
|
||
<figure>
|
||
<img src="https://storage.googleapis.com/prd-engineering-asset/2022/12/1ff43e65-motoki-tonn-zs4x24uiy9o-unsplash-1024x662.jpg" style="width:100%"><figcaption align="right">Photo by <a href="https://unsplash.com/@motoki?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText"> Motoki Tonn</a> on <a href="https://unsplash.com/s/photos/arrow-quiver?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a></figcaption></figure>
|
||
<p>I organized a <a href="https://code-artisan.io/retrospective-method-kpt/">KPT retrospective</a> for the project, to understand what we could have done better. </p>
|
||
<h4>Under-promise, over-deliver</h4>
|
||
<p>Communicating with the end users with just a design doc is not enough. Sometimes they don’t know what features they want unless they see actual mockups of the final product – then it’s easier for them to point out what they want or what they don’t want. As a result we had to continuously improve our data manipulation UI when PMs actually started using it, because they were not aware of some details.</p>
|
||
<h4>Track everything</h4>
|
||
<p>Before the release, we had 30 monitors and 6 observability dashboards. Now we have 40 monitors and 8 dashboards. For a project like this, a few metrics that we should have tracked from the beginning were:</p>
|
||
<ul>
|
||
<li>DB query time (the time to actually perform the query) and DB response time (the time between receiving the request and sending a response)</li>
|
||
<li>Avg CPU, Memory, numbers of containers running – for the DB, not just the service</li>
|
||
<li>Make better calculations – Back-of-the-envelope calculations should be restricted to non production releases, probably involving the architects and platform team to understand what metrics you need to calculate.</li>
|
||
</ul>
|
||
<h4>Granular releases</h4>
|
||
<p>This was something we wanted to do from the start, but could not due to external factors. We should have not tried to release everything at once. We also should have questioned and reviewed our own code more, instead of having our releases reveal them to us.</p>
|
||
<h4>Make your mistakes public</h4>
|
||
<p>We intend to share our findings at an org-level internally so that other teams can save a lot of precious time, money, resources, ~sleep~ that we overspent. </p>
|
||
<hr />
|
||
<p>One of the things I truly appreciate about being at Mercari is the ability to own up to your mistakes and being able to write this kind of an article. The environment is friendly, yet nurturing, lenient yet accountable. If that does not sound like your current workplace,that can change. Here’s my post from our 2021 advent calendar about <a href="https://engineering.mercari.com/en/blog/entry/20211224-career-change-is-the-only-constant/">career change</a>, and here is <a href="https://careers.mercari.com/">our job portal</a>. Come join us, we have snacks!</p>
|
||
<p>Tomorrow’s article will be presented by the US DRE team. Please look forward to it! </p>
|
||
</div></div><!--astro:end--></astro-island> <div class="_contents_shareButtons_11e9j_18"> <astro-island uid="Z18ixJI" component-url="/_astro/ShareButtons.Dw0B3qRt.js" component-export="ShareButtons" renderer-url="/_astro/client.DNGgaD7G.js" props="{"pathname":[0,"/en/blog/entry/20221218-migrations-the-wrong-way/"],"title":[0,"Moving to cloud: How to do Migrations the wrong way"],"tags":[1,[[0,{"name":[0,"Advent Calendar"],"slug":[0,"advent-calendar"]}],[0,{"name":[0,"databases"],"slug":[0,"databases"]}],[0,{"name":[0,"Migration"],"slug":[0,"migration"]}]]]}" ssr="" client="load" opts="{"name":"ShareButtons","value":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&text=Moving%20to%20cloud%3A%20How%20to%20do%20Migrations%20the%20wrong%20way%20%7C%20Mercari%20Engineering&via=MercariDev&hashtags=databases,Migration%0a&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/advent-calendar/"><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>Advent Calendar</div></span></a></li><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/databases/"><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>databases</div></span></a></li><li class="_tagList_item_wl3e1_22"><a href="/en/blog/tag/migration/"><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>Migration</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/20260730-bridging-the-gap-between-passwords-and-passkeys-with-risk-based-authentication/" class="_post-list__link_1e0te_35"><div class="_card_p1it6_19 false"><time datetime="2026-07-30">2026/07/30</time><div class="_post_p1it6_28"><img class="_post__thumbnail_p1it6_82" src="https://storage.googleapis.com/prd-engineering-asset/2026/07/94e23530-2026-06-26-20.59.16-1024x351-1.png" alt="Bridging the Gap Between Passwords and Passkeys with Risk-Based Authentication"/><div class="_post__text_p1it6_93"><h3 class="_post__title_p1it6_105">Bridging the Gap Between Passwords and Passkeys with Risk-Based Authentication</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>Development</p></li><li class="_tag-list__item_d76db_29"><p>Security</p></li></ul><p class="_author_p1it6_168">Author:<span class="_author__name_p1it6_176"> Tatsuya Karino</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/20260615-build-first-discuss-later/" class="_post-list__link_1e0te_35"><div class="_card_p1it6_19 false"><time datetime="2026-06-15">2026/06/15</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="Build First, Discuss Later: How Prototypes Speed Up Product Decisions"/><div class="_post__text_p1it6_93"><h3 class="_post__title_p1it6_105">Build First, Discuss Later: How Prototypes Speed Up Product Decisions</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>Development</p></li></ul><p class="_author_p1it6_168">Author:<span class="_author__name_p1it6_176"> kubomi</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/20260608-partner-credit-service/" class="_post-list__link_1e0te_35"><div class="_card_p1it6_19 false"><time datetime="2026-06-09">2026/06/09</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="Designing a Credit-Management Microservice for Partner Invoice Payment"/><div class="_post__text_p1it6_93"><h3 class="_post__title_p1it6_105">Designing a Credit-Management Microservice for Partner Invoice Payment</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>Backend</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"> imamura</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="{"name":"ButtonToTop","value":"preact"}"></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">©</span>2020 Mercari, Inc.
|
||
</small> </div> </footer> <script>(function(){const pageViewEvent = {"routeName":"/en/blog/entry/20221218-migrations-the-wrong-way/","pageType":"PageView","pageUrl":"/en/blog/entry/20221218-migrations-the-wrong-way/","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":"Development","Tags":"Advent Calendar,databases,Migration","Authors":"Kaustubh Hiware"};
|
||
|
||
// コンテンツグループをセット(GA4)
|
||
dataLayer.push(contentGroup);
|
||
})();</script> |