CINXE.COM

0 → 1, Shipping Threads in 5 Months - InfoQ

<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <!-- Google Optimize Anti-flicker snippet (recommended) --> <style>.async-hide { opacity: 0 !important} </style> <style>.promo{background:#222528;position:fixed;z-index:1001!important;left:0;top:0;right:0;max-height:48px;min-height:48px;padding-top:0!important;padding-bottom:0!important}.promo,.promo p{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.promo p{font-size:.8125rem;line-height:1rem;color:#fff;margin-bottom:0;margin-top:0;margin:0 auto;display:-webkit-box;display:-ms-flexbox;display:flex;font-weight:700}@media only screen and (max-width:650px){.promo p{font-size:.6875rem}}.promo span{overflow:hidden;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical}.promo a{color:#fff!important;text-decoration:underline!important}.promo a.btn{background:#d0021b;padding:7px 20px;text-decoration:none!important;font-weight:700;margin-left:10px;margin-right:10px;white-space:nowrap;border-radius:5px}@media only screen and (max-width:650px){.promo a.btn{font-size:.6875rem;padding:7px 10px}}.promo.container{padding-top:8px;padding-bottom:8px}@media only screen and (min-width:1050px){.promo.container{padding-top:0;padding-bottom:0}}.promo .actions{-ms-flex-wrap:nowrap;flex-wrap:nowrap}.promo .actions__left{-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.promo .actions__right{-ms-flex-preferred-size:40px;flex-basis:40px;margin-top:0;margin-bottom:0;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.promo.hidden{display:none}.promo.show{display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important}.promo.show .container__inner{-webkit-box-flex:1;-ms-flex:1;flex:1}.promo.fixed{position:fixed}.promo.show+header.header{margin-top:48px}.header{background:#fff;-webkit-box-shadow:0 1px 0 #dde2e5;box-shadow:0 1px 0 #dde2e5}.header .actions__left,.header__bottom__events{max-width:100%!important;margin:0}.header .header__events-all{margin:0;display:-webkit-box;display:-ms-flexbox;display:flex;position:relative}.header .header__events-all .header__event-slot{-webkit-box-flex:1;-ms-flex:1 100%;flex:1 100%;border-right:1px solid #dde2e5;margin-top:3px;margin-bottom:3px;padding-left:15px;text-align:left;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-right:5px;min-width:300px}.header .header__events-all .header__event-slot:hover{text-decoration:none!important}.header .header__events-all .header__event-slot img{min-width:40px;height:40px}.header .header__events-all .header__event-slot div{margin-left:10px}.header .header__events-all .header__event-slot span{font-weight:700!important;font-size:.75rem;margin-bottom:0!important;margin-top:0;display:block;line-height:1.125rem;text-align:left}.header .header__events-all .header__event-slot p{font-weight:400;font-size:.625rem;line-height:130%!important;color:#495057!important;margin:0}@media only screen and (min-width:1050px){.header .header__events-all .header__event-slot p{font-size:.625rem}}.header .header__events-all .header__event-slot:first-child{padding-left:0}.header .header__events-all .header__event-slot:last-child{padding-right:0;border-right:0}@media only screen and (min-width:1050px){.header__bottom,.header__middle,.header__top{position:relative;white-space:nowrap}}.header__top{padding:10px 0}@media only screen and (min-width:800px){.header__top{padding:5px 0}}.header__bottom{padding:5px 0;z-index:29;max-width:100%}.header__bottom a{font-size:.8125rem}.header__bottom .trending{margin-left:0;margin-right:0}.header__bottom .actions{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.header__bottom .actions__left{max-width:calc(100% + 8px)}@media only screen and (min-width:800px){.header__bottom .actions__left{max-width:calc(100% + 24px)}}.header__bottom .actions__right{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;display:none}@media only screen and (min-width:1050px){.header__bottom .actions__right{display:-webkit-box;display:-ms-flexbox;display:flex}}.header__middle{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}@media only screen and (min-width:1050px){.header__middle{-ms-flex-wrap:nowrap;flex-wrap:nowrap}}.header__top .actions__left{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center}@media only screen and (min-width:1050px){.header__top .actions__right{max-width:430px}}.no-style.header__nav li:nth-child(3){font-weight:700}.no-style.header__nav li:nth-child(3) a{color:#0e5ef1!important}.header__bottom__events::after{background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,0)),to(#fff));background:linear-gradient(90deg,rgba(255,255,255,0) 0,#fff 100%);content:'';position:absolute;height:60px;right:10px;width:25px}@media only screen and (min-width:1050px){.header__bottom__events::after{display:none}}.contribute-link{font-weight:400;font-size:.6875rem;color:#000!important;position:relative;padding-left:10px}.contribute-link:hover{color:#00791d!important;text-decoration:none!important}.contribute-link::before{content:'';width:1px;height:12px;position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);background:rgba(0,0,0,.1);left:-1px}.my-0{margin-top:0!important;margin-bottom:0!important}.header__desc.my-0{margin-left:0}.header__bottom__events .actions__left{max-width:100%!important;overflow-x:scroll;-ms-overflow-style:none;scrollbar-width:none;display:block;scroll-behavior:smooth;min-width:100%}.header__bottom__events .actions__left::-webkit-scrollbar{display:none}.header__bottom__events .actions__left:-webkit-scrollbar-thumb{background:#fff}.logo{line-height:1rem}.header{position:relative;z-index:41;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.header .input:focus,.header input[type=password]:focus,.header input[type=text]:focus{border:1px solid #00791d}.header a:not(.button):not(.login__action):not(.active){text-decoration:none;color:#222}.header a:not(.button):not(.login__action):not(.active):hover{text-decoration:underline;color:#222}.header__items{display:none;-ms-flex-wrap:wrap;flex-wrap:wrap}@media only screen and (min-width:1050px){.header__items{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.header__items nav{position:relative;background:0 0;padding:0;left:0;top:0;line-height:inherit;display:block;-webkit-box-shadow:none;box-shadow:none;max-width:100%;max-height:80px}}.header__items>div{width:100%;margin-bottom:32px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column nowrap;flex-flow:column nowrap}@media only screen and (min-width:552px){.header__items>div:not(:nth-last-child(-n+2)){margin-bottom:32px}}@media only screen and (min-width:552px) and (max-width:1050px){.header__items>div{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;-ms-flex-preferred-size:calc(99.7% * 1/2 - (32px - 32px * 1/2));flex-basis:calc(99.7% * 1/2 - (32px - 32px * 1/2));max-width:calc(99.7% * 1/2 - (32px - 32px * 1/2));width:calc(99.7% * 1/2 - (32px - 32px * 1/2))}.header__items>div:nth-child(1n){margin-right:32px;margin-left:0}.header__items>div:last-child{margin-right:0}.header__items>div:nth-child(2n){margin-right:0;margin-left:auto}}@media only screen and (min-width:800px) and (max-width:1050px){.header__items>div{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;-ms-flex-preferred-size:calc(99.7% * 1/4 - (32px - 32px * 1/4));flex-basis:calc(99.7% * 1/4 - (32px - 32px * 1/4));max-width:calc(99.7% * 1/4 - (32px - 32px * 1/4));width:calc(99.7% * 1/4 - (32px - 32px * 1/4))}.header__items>div:nth-child(1n){margin-right:32px;margin-left:0}.header__items>div:last-child{margin-right:0}.header__items>div:nth-child(4n){margin-right:0;margin-left:auto}}@media only screen and (min-width:1050px){.header__items>div{margin-bottom:0!important;margin-right:0!important;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}}.header__items .language__switcher{display:none}.header__items .language__switcher .li-nav.active>a,.header__items .language__switcher>li.active>a{color:#fff!important}.header__items .language__switcher .li-nav.active>a:hover,.header__items .language__switcher>li.active>a:hover{color:#fff!important;background:#0e5ef1}.header__items .language__switcher .li-nav:hover>a,.header__items .language__switcher>li:hover>a{color:#fff}.header+main{display:block;min-height:210px;-webkit-transition:margin .15s ease;transition:margin .15s ease;margin-top:0!important}.header--hide .header+main{margin-top:50px}.header--hide .header__toggle{opacity:0;top:20px;visibility:hidden}.header--hide .header__logo{max-height:0}.header--hide .header__middle,.header--hide .header__top{max-height:0;overflow:hidden;padding-top:0;padding-bottom:0;border-color:transparent}.header--hide .header__bottom .vue-portal-target{top:3px;right:0;bottom:auto;left:auto;position:absolute}.header__middle,.header__top{-webkit-transition:all .15s ease;transition:all .15s ease}.header__middle{border-bottom:1px solid rgba(0,0,0,.1);z-index:33}.header__middle .vue-portal-target{width:100%}@media only screen and (min-width:1050px){.header__middle .vue-portal-target{display:none}}@media only screen and (min-width:1050px){.header__middle{line-height:5.75rem;text-align:left;padding:0;z-index:30}.header__middle .widget__heading{display:none}}.header__top>.actions__left{display:none}@media only screen and (min-width:1050px){.header__top>.actions__left{display:-webkit-box;display:-ms-flexbox;display:flex}}.header__top>.actions__right{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;margin-right:0;margin-top:0;margin-bottom:0;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.header__top>.actions__right .dropdown__holder{width:calc(100vw - 16px);max-height:80vh}@media only screen and (min-width:600px){.header__top>.actions__right .dropdown__holder{width:auto}}.header__top>.actions__right>*{margin:0}.header__top>.actions__right .search{display:none}@media only screen and (min-width:1050px){.header__top>.actions__right>*{display:-webkit-box;display:-ms-flexbox;display:flex;white-space:nowrap}.header__top>.actions__right .search{display:block}}.header__top .user__login{display:block}.header__top .user__login>.button,.header__top .user__login>button{border-top-right-radius:0;border-bottom-right-radius:0}@media only screen and (min-width:1050px){.header__top{position:relative;right:auto;width:100%}}.header__logo{max-width:165px;position:absolute;top:8px;overflow:hidden;-webkit-transition:all .1s ease;transition:all .1s ease;z-index:32;line-height:2.25rem;height:36px;width:100px;margin-left:50px;-ms-flex-preferred-size:190px;flex-basis:190px}@media only screen and (min-width:800px){.header__logo{top:4px}}@media only screen and (min-width:1050px){.header__logo{position:relative;top:0;overflow:visible;margin-right:20px;margin-left:0;line-height:3.125rem;height:50px}.header__logo>*{width:165px}}@media only screen and (min-width:1280px){.header__logo{margin-right:30px}}.header__desc,.header__more>button{text-transform:capitalize;color:#666;letter-spacing:0;font-size:0;font-weight:400;line-height:1.5rem;vertical-align:top;font-smoothing:antialiased;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI Variable","Segoe UI",system-ui,ui-sans-serif,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";-webkit-transition:font-size .15s ease-in-out;transition:font-size .15s ease-in-out}@media only screen and (min-width:1050px){.header__desc,.header__more>button{font-size:.6875rem}}.header__desc{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;position:relative;width:auto}.header__topics{white-space:nowrap;float:right;position:relative}.header__topics *{display:inline-block;vertical-align:top}.header__topics a{font-size:.8125rem}@media only screen and (min-width:1050px){.header__topics{float:none}}.header__more{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:top}.header__more:before{left:-12px}.header__more:after,.header__more:before{content:'';width:1px;height:12px;position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);background:rgba(0,0,0,.1)}.header__more:after{right:-12px}.header__more:hover{cursor:pointer;color:rgba(0,0,0,.75)}.header__user{display:inline-block;vertical-align:top;white-space:nowrap;margin-left:8px}@media only screen and (min-width:1050px){.header__user{margin-left:0}}.header__user>div{display:inline-block;vertical-align:top}.header__user-nav a:not(.button){text-transform:uppercase;font-size:.75rem;font-weight:600}.header__user-nav a:not(.button):not(.active){opacity:.5}.header__user-nav a:not(.button):not(.active):hover{opacity:.75}.header__user-nav a:not(.button):hover{text-decoration:none}.header__user-nav a:not(.button).active{color:#222;cursor:default;text-decoration:none}.header__user-nav a:not(.button):before{margin-right:0}.header__user-nav a:not(.button):not(:last-child){margin-right:16px}@media only screen and (min-width:1050px){.header__user-nav a:not(.button):not(:last-child){margin-right:32px}}@media only screen and (min-width:1050px){.header__user-nav+.header__topics{margin-left:56px}}.header__search{display:none;vertical-align:top;margin-right:0}@media only screen and (min-width:1050px){.header__search{display:inline-block}}.header__search,.header__user{line-height:inherit}.header__nav{border-bottom:1px solid rgba(0,0,0,.1)}@media only screen and (min-width:800px){.header__nav{border-bottom:0}}.header__nav .button{margin-left:0}.header__nav .button__more{margin-right:20px}.header__nav .li-nav,.header__nav>li{-webkit-transition:all .15s ease;transition:all .15s ease}@media only screen and (min-width:1050px){.header__nav .li-nav,.header__nav>li{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;vertical-align:middle;position:static;border:none;min-height:65px}.header__nav .li-nav:hover.has--subnav .nav .li-nav,.header__nav .li-nav:hover.has--subnav .nav>li,.header__nav>li:hover.has--subnav .nav .li-nav,.header__nav>li:hover.has--subnav .nav>li{white-space:normal}.header__nav .li-nav:hover.has--subnav .nav__subnav,.header__nav>li:hover.has--subnav .nav__subnav{opacity:1;top:100%;visibility:visible;-webkit-transition-delay:.25s;transition-delay:.25s}.header__nav .li-nav:hover.has--subnav .nav__category,.header__nav>li:hover.has--subnav .nav__category{width:100%}.header__nav .li-nav:hover.has--subnav .nav__category:after,.header__nav .li-nav:hover.has--subnav .nav__category:before,.header__nav>li:hover.has--subnav .nav__category:after,.header__nav>li:hover.has--subnav .nav__category:before{-webkit-transition-delay:.25s;transition-delay:.25s;opacity:1}}@media only screen and (min-width:1080px){.header__nav .li-nav:not(:last-child),.header__nav>li:not(:last-child){margin-right:23px;margin-left:23px}}@media only screen and (min-width:1280px){.header__nav .li-nav:not(:last-child),.header__nav>li:not(:last-child){margin-right:23px;margin-left:23px}}@media only screen and (min-width:1338px){.header__nav .li-nav:not(:last-child),.header__nav>li:not(:last-child){margin-right:23px;margin-left:23px}}.header__nav .li-nav>a,.header__nav>li>a{font-size:.875rem;line-height:1.5rem;padding:12px 0;color:#000;display:inline-block;max-width:100%;position:relative;z-index:61;white-space:normal}@media only screen and (min-width:1050px){.header__nav .li-nav>a,.header__nav>li>a{padding:8px 0 0;font-weight:700}}.header__nav .li-nav>a:after,.header__nav .li-nav>a:before,.header__nav>li>a:after,.header__nav>li>a:before{content:'';position:absolute;bottom:-1px;left:50%;width:0;height:0;opacity:0;-webkit-transform:translateX(-50%);transform:translateX(-50%);border-style:solid;border-width:0 5px 5px 5px;-webkit-transition:opacity .15s ease-in-out;transition:opacity .15s ease-in-out;border-color:transparent transparent #fff transparent}.header__nav .li-nav>a:before,.header__nav>li>a:before{left:50%;bottom:0;border-width:0 6px 6px 6px;border-color:transparent transparent #f5f7f8 transparent}@media only screen and (min-width:1050px){.header__nav .li-nav>a,.header__nav>li>a{font-size:1rem}}@media only screen and (min-width:1800px){.header__nav .li-nav>a,.header__nav>li>a{font-size:1.125rem}}.header--open{overflow:hidden}@media only screen and (min-width:600px){.header--open{overflow:visible}}.header--open .content-items{max-height:215px;margin:12px 0 24px}.header--open .search{margin-top:16px;display:block}.header--open .header__toggle:before{z-index:10}.header--open .header__toggle>span:nth-child(1){top:50%;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.header--open .header__toggle>span:nth-child(2){opacity:0}.header--open .header__toggle>span:nth-child(3){top:50%;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.header--open .header__items,.header--open .header__items .language__switcher{display:-webkit-box;display:-ms-flexbox;display:flex}.header--open .header__top{z-index:100;position:absolute;left:0;right:8px;background:#fff}@media only screen and (min-width:800px){.header--open .header__top{right:20px}}.header--open .header__top .search{display:none}.header--open .header__logo{z-index:101}.header--open .header__middle{padding-top:60px}.header--open .header__bottom{display:none}.header--open .header__container{max-height:90vh;overflow-x:hidden;overflow-y:auto}@media only screen and (min-width:1050px){.header--open .header__container{overflow:visible}}.header .subnav{position:absolute;-webkit-box-shadow:0 5px 25px 1px rgba(0,0,0,.15);box-shadow:0 5px 25px 1px rgba(0,0,0,.15);background:#fff;visibility:hidden;line-height:1.75rem;max-width:100%;width:100%;left:0;opacity:0;overflow:hidden;border:1px solid #f5f7f8;border-radius:2px;-webkit-transition:all .15s ease-in-out;transition:all .15s ease-in-out;top:105%;z-index:60;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row nowrap;flex-flow:row nowrap;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.header .subnav .subnav__categories{-webkit-box-flex:0;-ms-flex:0 1 280px;flex:0 1 280px;padding:24px 0;background:#f5f7f8;margin-right:0!important}.header .subnav .subnav__categories>li{display:block;font-size:.9375rem;padding:2px 48px 2px 24px}.header .subnav .subnav__categories>li a{display:block;font-weight:700}.header .subnav .subnav__categories>li:hover{background:#e1e1e1}.header .subnav .subnav__heading{margin-bottom:20px}.header .subnav .subnav__content{position:relative;-ms-flex-item-align:start;align-self:flex-start;padding:24px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}@media only screen and (min-width:1050px){.header .subnav .subnav__content{padding-left:32px;padding-right:32px;margin:0 auto;-webkit-box-flex:1;-ms-flex:1 1 600px;flex:1 1 600px}}.header .subnav .subnav__content .heading__container{-ms-flex-preferred-size:100%;flex-basis:100%}.header .subnav .subnav__content:before{content:'';position:absolute;left:0;top:0;bottom:-100%;width:1px;background:rgba(0,0,0,.1)}.languagesEdition .active{font-weight:700}.header__more.dropdown:after{content:'';display:inline-block;vertical-align:middle;-ms-flex-item-align:center;-ms-grid-row-align:center;align-self:center;background-repeat:no-repeat;background-position:center;margin-bottom:2px;width:7px;height:7px;-webkit-transition:-webkit-transform .15s ease;transition:-webkit-transform .15s ease;transition:transform .15s ease;transition:transform .15s ease,-webkit-transform .15s ease;background-color:#fff!important;background-size:contain}.header__more.dropdown button{color:#000!important;margin-right:-20px;padding-right:20px;z-index:1000}.header__more.dropdown .dropdown__holder{width:165px}.header__more.dropdown .dropdown__content{padding:13px;padding-top:5px;padding-bottom:5px}.header__more.dropdown .languagesEdition li{border-bottom:1px solid #e6e6e6}.header__more.dropdown .languagesEdition li:last-child{border:0}.logo__data{display:none;color:#666;font-size:.6875rem}@media only screen and (min-width:1050px){.logo__data{display:block;line-height:.8125rem}}.container{padding-left:12px;padding-right:12px;margin:0 auto;min-width:320px;-webkit-transition:padding .15s ease-in-out;transition:padding .15s ease-in-out}@media only screen and (min-width:600px){.container{padding-left:16px;padding-right:16px}}@media only screen and (min-width:800px){.container{padding-left:20px;padding-right:20px}}@media only screen and (min-width:1250px){.container{padding-left:60px;padding-right:60px}}@media only screen and (min-width:1400px){.container{padding-left:20px;padding-right:20px}}.container.white{background:#fff}.container__inner{max-width:1290px;margin:0 auto;-webkit-transition:max-width .15s ease-out;transition:max-width .15s ease-out}.search{display:block;position:relative;z-index:33;width:100%;max-width:100%;margin:0}.search:before{position:absolute;top:50%;right:24px;-webkit-transform:translateY(-50%);transform:translateY(-50%);margin-right:0;z-index:34}.search__bar{display:block;border-radius:2px;position:relative;z-index:33}.search__bar #search{margin-bottom:0;max-width:100%;background:#fff}.search__go{top:50%;right:0;bottom:0;left:auto;position:absolute;-webkit-transform:translateY(-50%);transform:translateY(-50%);z-index:32;-webkit-appearance:none;-moz-appearance:none;appearance:none;width:36px;height:36px;line-height:2.25rem;-webkit-box-shadow:none;box-shadow:none;display:block;background:0 0;border:0;font-size:0}@media only screen and (min-width:600px){.search__go{z-index:35}}.header #search,.search__go:hover{cursor:pointer}.header #search{height:36px;position:relative;max-width:100%;background-color:#f5f7f8!important}@media only screen and (min-width:600px){.header #search{font-size:.8125rem;min-width:165px;max-width:100%;opacity:1}}.header #search:hover{cursor:auto}@media only screen and (min-width:1050px){.header #search{margin-left:auto;border-top-right-radius:0;border-bottom-right-radius:0;border-right:0}.header #search:focus{min-width:215px}}.header #search:focus{cursor:auto}.header #search .field__desc{display:none}.header #searchForm{width:100%;margin-top:8px}.header #searchForm:before{right:8px}@media only screen and (min-width:600px){.header #searchForm{margin-top:16px}}@media only screen and (min-width:1050px){.header #searchForm{margin-top:0}}</style> <script>(function(a,s,y,n,c,h,i,d,e){s.className+=' '+y;h.start=1*new Date; h.end=i=function(){s.className=s.className.replace(RegExp(' ?'+y),'')}; (a[n]=a[n]||[]).hide=h;setTimeout(function(){i();h.end=null},c);h.timeout=c; })(window,document.documentElement,'async-hide','dataLayer',4000, {'GTM-W9GJ5DL':true});</script> <script type="text/javascript"> var loggedIn = false; if (loggedIn) { var userCountryId = ''; } </script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('config', 'G-VMVPD4D2JY'); //CookieControl tool recomendation // Call the default command before gtag.js or Tag Manager runs to // adjust how the tags operate when they run. Modify the defaults // per your business requirements and prior consent granted/denied, e.g.: gtag('consent', 'default', { 'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied' }); if((typeof loggedIn != "undefined") && loggedIn){ window.dataLayer.push({'logged_in': 'true'}); } else { window.dataLayer.push({'logged_in': 'false'}); } window.dataLayer.push({'show_queryz': ''}); </script> <!-- Google Tag Manager --> <script> var gtmProfile="GTM-W9GJ5DL"; (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', gtmProfile);</script> <!-- End Google Tag Manager --> <title>0 → 1, Shipping Threads in 5 Months - InfoQ</title> <link rel="canonical" href="https://www.infoq.com/presentations/threads-meta/"/> <link rel="alternate" href="https://www.infoq.com/presentations/threads-meta/" hreflang="en"/> <link rel="alternate" href="https://www.infoq.com/presentations/threads-meta/" hreflang="x-default" /> <meta http-equiv="pragma" content="no-cache" /> <meta http-equiv="cache-control" content="private,no-cache,no-store,must-revalidate" /> <meta http-equiv="expires" content="0" /> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <meta name="copyright" content="&copy; 2006 C4Media" /> <meta name="google-site-verification" content="0qInQx_1WYOeIIbxnh7DnXlw1XOxNgAYakO2k4GhNnY" /> <meta name="msapplication-TileColor" content="#ffffff"/> <meta name="msapplication-TileImage" content="/styles/static/images/logo/logo.jpg"/> <meta property="wb:webmaster" content="3eac1729a8bbe046" /> <meta content="width=device-width,initial-scale=1" name="viewport"> <meta http-equiv="X-UA-Compatible" content="IE=10, IE=edge"> <link rel="stylesheet" type="text/css" media="screen" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/style.css"/> <link rel="stylesheet" type="text/css" media="print" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/print.css"/> <link rel="preload" type="text/css" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/style_en.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <link rel="preload" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/icons.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <link rel="preload" type="text/css" media="screen" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/style_extra.css" as="style" onload="this.onload=null;this.rel='stylesheet'"> <noscript> <link rel="stylesheet" type="text/css" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/style_en.css"/> <link rel="stylesheet" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/icons.css"> <link rel="stylesheet" type="text/css" media="screen" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/style_extra.css"/> </noscript> <link rel="stylesheet" type="text/css" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/fonts/font.css"/> <link rel="shortcut icon" href="https://cdn.infoq.com/statics_s2_20250228123450/favicon.ico" type="image/x-icon" /> <link rel="apple-touch-icon" href="https://cdn.infoq.com/statics_s2_20250228123450/apple-touch-icon.png"/> <script type="text/javascript"> var device='desktop'; var InfoQConstants = {}; InfoQConstants.language = 'en'; InfoQConstants.countryCode = ''; InfoQConstants.scp = 'eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6IioiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3NDEwODU3Nzh9LCJJcEFkZHJlc3MiOnsiQVdTOlNvdXJjZUlwIjoiMC4wLjAuMC8wIn19fV19'; InfoQConstants.scs = 'cHixqYhrmY9NzLn6jsJTWXoVYt0YZKI0dunjdVpiCuLWNAg9sJsdC2gp7KF4GqTMQN6jme~8RTR6GuS4QK68zjctZHskK2mDKmZRIIN9G2B5rv1bPtMhu6teGhP14myAaWY93nF8jZX79FRUODnCrdediL74gI-2xbxjP1l-SiA_'; InfoQConstants.sck = 'APKAIMZVI7QH4C5YKH6Q'; InfoQConstants.scd = '.infoq.com'; InfoQConstants.sct = '7200'; InfoQConstants.pageUrl = (typeof window.location != 'undefined' && window.location && typeof window.location.href != 'undefined' && window.location.href) ? window.location.href : "URL_UNAVAILABLE"; InfoQConstants.cet='FaHUbNSfqo0L4vv3'; InfoQConstants.userDetectedCountryCode = 'SG'; InfoQConstants.bpadb = 'oCOjWmPC4BS3qhTDkqXP'; </script> <script type="text/javascript" src="https://cdn.infoq.com/statics_s2_20250228123450/scripts/combinedJs.min.js"></script> <script type="text/javascript"> var JSi18n = JSi18n || {}; // define only if not already defined JSi18n.error='Error'; JSi18n.login_unverifiedAccount='Unverified account'; JSi18n.contentSummary_showPresentations_1=''; JSi18n.contentSummary_showPresentations_2=''; JSi18n.contentSummary_showPresentations_3=''; JSi18n.contentSummary_showInterviews_1=''; JSi18n.contentSummary_showInterviews_2=''; JSi18n.contentSummary_showInterviews_3=''; JSi18n.contentSummary_showMinibooks_1=''; JSi18n.contentSummary_showMinibooks_2=''; JSi18n.login_sendingRequest='Sending request ...'; JSi18n.bookmark_saved='<q>&nbsp;&nbsp;&nbsp;Saved&nbsp;&nbsp;&nbsp;&nbsp;</q>'; JSi18n.bookmark_error='<q style=color:black;>&nbsp;&nbsp;&nbsp;Error&nbsp;&nbsp;&nbsp;&nbsp;</q>'; JSi18n.categoryManagement_showpopup_viewAllLink_viewAllPrefix='View All'; JSi18n.categoryManagement_showpopup_viewAllLink_viewAllSuffix=''; JSi18n.categoryManagement_showpopup_includeExcludeLink_Exclude='Exclude'; JSi18n.categoryManagement_showpopup_includeExcludeLink_Include='Include'; JSi18n.login_invalid_email='Please specify a valid email'; JSi18n.login_email_not_found = 'No user found with that email'; JSi18n.content_datetime_format='MMM dd, yyyy'; // used by frontend JSi18n.FE = { labels: { follow: "Follow", followTopic: "Follow Topic", unfollow: "Unfollow", unfollowTopic: "Unfollow Topic", following: "Following", followers: "Followers", like: "Like", liked: "Liked", authors: "Peers", users : "Users", topics: "Topics", hide: "Hide Item", hidden: "%s was hidden on your profile page.", undo: "Undo", showLess: "Show less", showMore: "Show more", moreAuthors: "And %s more", bookmarked: "Content Bookmarked", unbookmarked: "Content Unbookmarked", characterLimit: "Characters Remaining" } } var usersInPage = JSON.parse('[{\"id\":\"62671158\",\"ref\":\"author-Monica-Beckwith\",\"url\":\"\/profile\/Monica-Beckwith\",\"followedByCurrentUser\":false,\"minibio\":\"\",\"name\":\"Monica Beckwith\",\"bio\":\"\",\"followers\":1717,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/QhDv7pXEUK1sdLsYArFmnLxecH4rYhAc.jpg\"},{\"id\":\"45723890\",\"ref\":\"author-Rags-Srinivas\",\"url\":\"\/profile\/Rags-Srinivas\",\"followedByCurrentUser\":false,\"minibio\":\"\",\"name\":\"Rags Srinivas\",\"bio\":\"\",\"followers\":265,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/t4nyfgw1THkp4wMZ9EZ59RGJx8Hf9Rk8.jpg\"},{\"id\":\"126658110\",\"ref\":\"author-Zahan-Malkani\",\"url\":\"\/profile\/Zahan-Malkani\",\"followedByCurrentUser\":false,\"minibio\":\"Software Engineer @Meta\",\"name\":\"Zahan Malkani\",\"bio\":\"\",\"followers\":3,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/5777a3454585d07ebb60bca5ab3406ba.jpg\"},{\"id\":\"87551248\",\"ref\":\"author-Steef~Jan-Wiggers\",\"url\":\"\/profile\/Steef~Jan-Wiggers\",\"followedByCurrentUser\":false,\"minibio\":\"Cloud Queue Lead Editor\",\"name\":\"Steef-Jan Wiggers\",\"bio\":\"\",\"followers\":700,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/BhZx03k3Hj0pZVXmTzGqItwZxtJ06oIb.jpeg\"},{\"id\":\"80977916\",\"ref\":\"author-Thomas-Betts\",\"url\":\"\/profile\/Thomas-Betts\",\"followedByCurrentUser\":false,\"minibio\":\"Laureate Application Architect at Blackbaud\",\"name\":\"Thomas Betts\",\"bio\":\"\",\"followers\":976,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/pSqI6HrU3k9rmmVjwS34OHG0bOMYiE6a.jpg\"},{\"id\":\"72028228\",\"ref\":\"author-Sergio-De-Simone\",\"url\":\"\/profile\/Sergio-De-Simone\",\"followedByCurrentUser\":false,\"minibio\":\"\",\"name\":\"Sergio De Simone\",\"bio\":\"\",\"followers\":629,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/NovciOoQOAYWqYqRQBFo97SuMm0xbUiC.jpg\"},{\"id\":\"126467140\",\"ref\":\"author-Renato-Losio\",\"url\":\"\/profile\/Renato-Losio\",\"followedByCurrentUser\":false,\"minibio\":\"Cloud Expert | AWS Data Hero \",\"name\":\"Renato Losio\",\"bio\":\"\",\"followers\":646,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/ptroF8HdI2vWXm0NDaKeS0JdiPxMOAra.jpg\"},{\"id\":\"126464202\",\"ref\":\"author-Johan-Janssen\",\"url\":\"\/profile\/Johan-Janssen\",\"followedByCurrentUser\":false,\"minibio\":\"Architect at ASML\",\"name\":\"Johan Janssen\",\"bio\":\"\",\"followers\":401,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/Fb4eZ0mtvMf6MhsmBIhsUVueV4xAs2FD.jpg\"},{\"id\":\"39485652\",\"ref\":\"author-Daniel-Bryant\",\"url\":\"\/profile\/Daniel-Bryant\",\"followedByCurrentUser\":false,\"minibio\":\"InfoQ News Manager | Building Platforms at Syntasso\",\"name\":\"Daniel Bryant\",\"bio\":\"\",\"followers\":2595,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/tSe5dczMaSGtRUm18VkTR2tcF4W3SogA.jpg\"},{\"id\":\"63268344\",\"ref\":\"author-Chris-Swan\",\"url\":\"\/profile\/Chris-Swan\",\"followedByCurrentUser\":false,\"minibio\":\"Engineer, Atsign\",\"name\":\"Chris Swan\",\"bio\":\"\",\"followers\":1763,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/8PE76nOujWAoCM8yqLn9Hfv2HqW3VlIP.jpg\"},{\"id\":\"4927376\",\"ref\":\"author-Karsten-Silz\",\"url\":\"\/profile\/Karsten-Silz\",\"followedByCurrentUser\":false,\"minibio\":\"Full-Stack Java Developer &amp; Contractor\",\"name\":\"Karsten Silz\",\"bio\":\"\",\"followers\":306,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/p6zmOdOcqXiRj09iiZNeDZap7f0IglQW.jpg\"},{\"id\":\"343314\",\"ref\":\"author-Jonathan-Allen\",\"url\":\"\/profile\/Jonathan-Allen\",\"followedByCurrentUser\":false,\"minibio\":\"Software Architect\",\"name\":\"Jonathan Allen\",\"bio\":\"\",\"followers\":1733,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/Wk_C09_mzwK23YkTkKMXResJv3LKUN5D.jpg\"},{\"id\":\"114725059\",\"ref\":\"author-Holly-Cummins\",\"url\":\"\/profile\/Holly-Cummins\",\"followedByCurrentUser\":false,\"minibio\":\"Senior Principal Software Engineer, Red Hat\",\"name\":\"Holly Cummins\",\"bio\":\"\",\"followers\":459,\"imgSrc\":\"https:\/\/cdn.infoq.com\/statics_s2_20250228123450\/images\/profiles\/cRsuGlFgKyGmGfEHvafpMO63CxbrEm22.jpg\"}]'); var topicsInPage = JSON.parse('[{\"name\":\"Architecture & Design\",\"id\":\"6816\",\"followers\":9544,\"url\":\"\/architecture-design\",\"followedByCurrentUser\":false},{\"name\":\"Culture & Methods\",\"id\":\"6817\",\"followers\":3732,\"url\":\"\/culture-methods\",\"followedByCurrentUser\":false},{\"name\":\".NET Core\",\"id\":\"15683\",\"followers\":7351,\"url\":\"\/Net-Core\",\"followedByCurrentUser\":false},{\"name\":\"InfoQ\",\"id\":\"134\",\"followers\":84,\"url\":\"\/InfoQ\",\"followedByCurrentUser\":false},{\"name\":\"Machine Learning\",\"id\":\"5449\",\"followers\":13396,\"url\":\"\/MachineLearning\",\"followedByCurrentUser\":false},{\"name\":\"Microservices\",\"id\":\"15274\",\"followers\":20718,\"url\":\"\/microservices\",\"followedByCurrentUser\":false},{\"name\":\"Social Networking\",\"id\":\"140\",\"followers\":12,\"url\":\"\/socialNetworking\",\"followedByCurrentUser\":false},{\"name\":\"Facebook\",\"id\":\"3535\",\"followers\":17,\"url\":\"\/Facebook\",\"followedByCurrentUser\":false},{\"name\":\"Case Study\",\"id\":\"7313\",\"followers\":300,\"url\":\"\/Case_Study\",\"followedByCurrentUser\":false},{\"name\":\"AI, ML & Data Engineering\",\"id\":\"16690\",\"followers\":5163,\"url\":\"\/ai-ml-data-eng\",\"followedByCurrentUser\":false},{\"name\":\"QCon Software Development Conference\",\"id\":\"597\",\"followers\":242,\"url\":\"\/qcon\",\"followedByCurrentUser\":false},{\"name\":\"QCon London 2024\",\"id\":\"18549\",\"followers\":7,\"url\":\"\/qcon-london-2024\",\"followedByCurrentUser\":false},{\"name\":\"Java9\",\"id\":\"7097\",\"followers\":5022,\"url\":\"\/Java9\",\"followedByCurrentUser\":false},{\"name\":\"DevOps\",\"id\":\"6043\",\"followers\":4749,\"url\":\"\/Devops\",\"followedByCurrentUser\":false},{\"name\":\"Thread\",\"id\":\"6428\",\"followers\":1,\"url\":\"\/thread\",\"followedByCurrentUser\":false},{\"name\":\"Reactive Programming\",\"id\":\"15453\",\"followers\":11592,\"url\":\"\/reactive-programming\",\"followedByCurrentUser\":false},{\"name\":\"Transcripts\",\"id\":\"17662\",\"followers\":21,\"url\":\"\/transcripts\",\"followedByCurrentUser\":false},{\"name\":\"Development\",\"id\":\"6815\",\"followers\":3810,\"url\":\"\/development\",\"followedByCurrentUser\":false}]'); var userContentLikesInPage = []; var userCommentsLikesInPage = []; var currentUserId = 2; </script> <script type="application/ld+json"> { "@context": "http://schema.org", "@type": "NewsArticle", "mainEntityOfPage": { "@type": "WebPage", "@id": "https://www.infoq.com/presentations/threads-meta/" }, "headline": "0 → 1, Shipping Threads in 5 Months", "image": ["https://res.infoq.com/presentations/threads-meta/en/mediumimage/ZahanMalkani-medium-1723461991582.jpg" ], "datePublished": "2024-10-10", "dateModified": "2024-10-10", "author": [ { "@type": "Person", "name": "Zahan Malkani" } ], "publisher": { "@type": "Organization", "name": "InfoQ", "logo": { "@type": "ImageObject", "url": "https://assets.infoq.com/resources/en/logo_scrubber_big_4_3.jpg" } }, "description": "Zahan Malkani shares how they built a microblogging service to compete with Twitter with a small team that shipped a new social network in a few months.", "video": { "@type": "VideoObject", "name": "0 → 1, Shipping Threads in 5 Months", "description": "Zahan Malkani shares how they built a microblogging service to compete with Twitter with a small team that shipped a new social network in a few months.", "thumbnailUrl": [ "https://res.infoq.com/presentations/threads-meta/en/mediumimage/ZahanMalkani-medium-1723461991582.jpg" ], "uploadDate": "2024-10-10", "duration": "PT48M43S" }, "isAccessibleForFree": "False", "hasPart": { "@type": "WebPageElement", "isAccessibleForFree": "False", "cssSelector" : ".paywallPdf" } } </script> <meta name="ifq:pageType" content="PRESENTATION_PAGE"/> <script type="text/javascript"> InfoQConstants.pageType = 'PRESENTATION_PAGE'; </script> <meta property="og:type" content="website" /> <meta property="og:image" content="https://res.infoq.com/presentations/threads-meta/en/card_header_image/01shippingThreadsin5months-twitter_card-1723461991582.jpg"/> <meta property="twitter:image" content="https://res.infoq.com/presentations/threads-meta/en/card_header_image/01shippingThreadsin5months-twitter_card-1723461991582.jpg"/> <meta property="og:title" content="0 → 1, Shipping Threads in 5 Months "/> <meta property="og:description" content="Zahan Malkani shares how they built a microblogging service to compete with Twitter with a small team that shipped a new social network in a few months." /> <meta property="og:site_name" content="InfoQ"/> <meta property="og:url" content="https://www.infoq.com/presentations/threads-meta/"/> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content="0 → 1, Shipping Threads in 5 Months "/> <meta name="twitter:description" content="Zahan Malkani shares how they built a microblogging service to compete with Twitter with a small team that shipped a new social network in a few months." /> <link rel="image_src" href="https://res.infoq.com/presentations/threads-meta/en/mediumimage/ZahanMalkani-medium-1723461991582.jpg"/> <meta name="keywords" content="threads meta,Architecture &amp; Design,Facebook,QCon London 2024,Social Networking,Transcripts,QCon Software Development Conference,Thread,Case Study,InfoQ,"/> <meta name="description" content="Zahan Malkani shares how they built a microblogging service to compete with Twitter with a small team that shipped a new social network in a few months."/> <meta name="tprox" content="1728561600000" /> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/swfobject/2.1/swfobject.js"></script> <script type="text/javascript"> var slides = new Array('https://imgopt.infoq.com/fit-in/1288x0/filters:quality(80)/presentations/threads-meta/en/slides/Zah-1728560783548.jpg'), TIMES = new Array(0,2923), EXPRESSINSTALL_SWF = 'https://cdn.infoq.com/statics_s2_20250228123450/scripts/video/flash/expressinstall.swf', SVMPLAYER_SWF = 'https://cdn.infoq.com/statics_s2_20250228123450/scripts/video/flash/svmplayer.swf', isWideScreen = true, // i18n text for the to full view/minimize button i18nFullScreen = 'Full', i18nMinimize = 'Minimize', demoTimings = '5,2922'; var playerSplash = 'https://cdn.infoq.com/statics_s2_20250228123450/styles/static/images/logo/logo_scrubber_16_9.jpg'; var vhf = 'cnRtcGU6Ly92aWRlb2YuaW5mb3EuY29tL2NmeC9zdC8='; var jsclassref = 'cHJlc2VudGF0aW9ucy8yNC1hcHItc2hpcHBpbmd0aHJlYWRzLm1wNA=='; </script> <script type="text/javascript" src="https://cdn.infoq.com/statics_s2_20250228123450/scripts/video/player/PlayerPresentation_mobile.js"></script> <script type="text/javascript"> $(document).ready(function() { init(); }); </script> <script type='text/javascript' src='https://cdn.infoq.com/statics_s2_20250228123450/scripts/video/videoPlayercombinedJsPresentation.js'></script> <script type='text/javascript' src='https://cdn.infoq.com/statics_s2_20250228123450/scripts/video/PresentationUI.js'></script> <script type='text/javascript' src='https://cdn.infoq.com/statics_s2_20250228123450/scripts/ui/jquery.tipsy.js'></script> <link rel="stylesheet" href="https://cdn.infoq.com/statics_s2_20250228123450/styles/tipsy.css" type="text/css" /> <script type="text/javascript"> P.s = 'https://videoh.infoq.com/presentations/24-apr-shippingthreads.mp4'; </script> <script type="text/javascript" src="https://cdn.infoq.com/statics_s2_20250228123450/scripts/relatedVcr.min.js"></script> <script type="application/javascript"> var communityIds = "2498"; var topicIds = "922,7029,137,6218,593,2210,2843,131"; VCR.loadAllVcrs(communityIds, topicIds); </script> <script type="text/javascript" src="https://cdn.infoq.com/statics_s2_20250228123450/scripts/infoq.js"></script> <script type="text/javascript"> document.addEventListener('DOMContentLoaded', function() { if (!window || !window.infoq) return infoq.init() }) </script> </head> <body > <!-- Google Tag Manager (noscript) --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W9GJ5DL" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <!-- End Google Tag Manager (noscript) --> <div class="intbt"> <a href="/int/bt/" title="bt">BT</a> </div> <script type="text/javascript"> var allCountries = [{"id":3,"name":"Afghanistan"},{"id":244,"name":"Åland"},{"id":6,"name":"Albania"},{"id":61,"name":"Algeria"},{"id":13,"name":"American Samoa"},{"id":1,"name":"Andorra"},{"id":9,"name":"Angola"},{"id":5,"name":"Anguilla"},{"id":11,"name":"Antarctica"},{"id":4,"name":"Antigua and Barbuda"},{"id":12,"name":"Argentina"},{"id":7,"name":"Armenia"},{"id":16,"name":"Aruba"},{"id":15,"name":"Australia"},{"id":14,"name":"Austria"},{"id":17,"name":"Azerbaijan"},{"id":31,"name":"Bahamas"},{"id":24,"name":"Bahrain"},{"id":20,"name":"Bangladesh"},{"id":19,"name":"Barbados"},{"id":35,"name":"Belarus"},{"id":21,"name":"Belgium"},{"id":36,"name":"Belize"},{"id":26,"name":"Benin"},{"id":27,"name":"Bermuda"},{"id":32,"name":"Bhutan"},{"id":29,"name":"Bolivia"},{"id":254,"name":"Bonaire, Sint Eustatius, and Saba"},{"id":18,"name":"Bosnia and Herzegovina"},{"id":34,"name":"Botswana"},{"id":33,"name":"Bouvet Island"},{"id":30,"name":"Brazil"},{"id":104,"name":"British Indian Ocean Territory"},{"id":28,"name":"Brunei Darussalam"},{"id":23,"name":"Bulgaria"},{"id":22,"name":"Burkina Faso"},{"id":25,"name":"Burundi"},{"id":114,"name":"Cambodia"},{"id":46,"name":"Cameroon"},{"id":37,"name":"Canada"},{"id":52,"name":"Cape Verde"},{"id":121,"name":"Cayman Islands"},{"id":40,"name":"Central African Republic"},{"id":207,"name":"Chad"},{"id":45,"name":"Chile"},{"id":47,"name":"China"},{"id":53,"name":"Christmas Island"},{"id":38,"name":"Cocos (Keeling) Islands"},{"id":48,"name":"Colombia"},{"id":116,"name":"Comoros"},{"id":39,"name":"Congo (Democratic Republic)"},{"id":41,"name":"Congo (People\u0027s Republic)"},{"id":44,"name":"Cook Islands"},{"id":49,"name":"Costa Rica"},{"id":43,"name":"Cote D\u0027Ivoire"},{"id":97,"name":"Croatia"},{"id":51,"name":"Cuba"},{"id":253,"name":"Curaçao"},{"id":54,"name":"Cyprus"},{"id":55,"name":"Czech Republic"},{"id":58,"name":"Denmark"},{"id":57,"name":"Djibouti"},{"id":59,"name":"Dominica"},{"id":60,"name":"Dominican Republic"},{"id":213,"name":"East Timor"},{"id":62,"name":"Ecuador"},{"id":64,"name":"Egypt"},{"id":203,"name":"El Salvador"},{"id":87,"name":"Equatorial Guinea"},{"id":66,"name":"Eritrea"},{"id":63,"name":"Estonia"},{"id":68,"name":"Ethiopia"},{"id":72,"name":"Falkland Islands (Malvinas)"},{"id":74,"name":"Faroe Islands"},{"id":71,"name":"Fiji"},{"id":70,"name":"Finland"},{"id":75,"name":"France"},{"id":80,"name":"French Guiana"},{"id":170,"name":"French Polynesia"},{"id":208,"name":"French Southern Territories"},{"id":76,"name":"Gabon"},{"id":84,"name":"Gambia"},{"id":79,"name":"Georgia"},{"id":56,"name":"Germany"},{"id":81,"name":"Ghana"},{"id":82,"name":"Gibraltar"},{"id":88,"name":"Greece"},{"id":83,"name":"Greenland"},{"id":78,"name":"Grenada"},{"id":86,"name":"Guadeloupe"},{"id":91,"name":"Guam"},{"id":90,"name":"Guatemala"},{"id":249,"name":"Guernsey"},{"id":85,"name":"Guinea"},{"id":92,"name":"Guinea-Bissau"},{"id":93,"name":"Guyana"},{"id":98,"name":"Haiti"},{"id":95,"name":"Heard Island and McDonald Islands"},{"id":96,"name":"Honduras"},{"id":94,"name":"Hong Kong"},{"id":99,"name":"Hungary"},{"id":107,"name":"Iceland"},{"id":103,"name":"India"},{"id":100,"name":"Indonesia"},{"id":106,"name":"Iran"},{"id":105,"name":"Iraq"},{"id":101,"name":"Ireland"},{"id":245,"name":"Isle of Man"},{"id":102,"name":"Israel"},{"id":108,"name":"Italy"},{"id":109,"name":"Jamaica"},{"id":111,"name":"Japan"},{"id":250,"name":"Jersey"},{"id":110,"name":"Jordan"},{"id":122,"name":"Kazakhstan"},{"id":112,"name":"Kenya"},{"id":115,"name":"Kiribati"},{"id":243,"name":"Kosovo"},{"id":120,"name":"Kuwait"},{"id":113,"name":"Kyrgyzstan"},{"id":123,"name":"Laos"},{"id":132,"name":"Latvia"},{"id":124,"name":"Lebanon"},{"id":129,"name":"Lesotho"},{"id":128,"name":"Liberia"},{"id":133,"name":"Libya"},{"id":126,"name":"Liechtenstein"},{"id":130,"name":"Lithuania"},{"id":131,"name":"Luxembourg"},{"id":143,"name":"Macau"},{"id":139,"name":"Macedonia"},{"id":137,"name":"Madagascar"},{"id":151,"name":"Malawi"},{"id":153,"name":"Malaysia"},{"id":150,"name":"Maldives"},{"id":140,"name":"Mali"},{"id":148,"name":"Malta"},{"id":138,"name":"Marshall Islands"},{"id":145,"name":"Martinique"},{"id":146,"name":"Mauritania"},{"id":149,"name":"Mauritius"},{"id":238,"name":"Mayotte"},{"id":152,"name":"Mexico"},{"id":73,"name":"Micronesia"},{"id":136,"name":"Moldova"},{"id":135,"name":"Monaco"},{"id":142,"name":"Mongolia"},{"id":246,"name":"Montenegro"},{"id":147,"name":"Montserrat"},{"id":134,"name":"Morocco"},{"id":154,"name":"Mozambique"},{"id":141,"name":"Myanmar"},{"id":155,"name":"Namibia"},{"id":164,"name":"Nauru"},{"id":163,"name":"Nepal"},{"id":161,"name":"Netherlands"},{"id":8,"name":"Netherlands Antilles"},{"id":156,"name":"New Caledonia"},{"id":166,"name":"New Zealand"},{"id":160,"name":"Nicaragua"},{"id":157,"name":"Niger"},{"id":159,"name":"Nigeria"},{"id":165,"name":"Niue"},{"id":158,"name":"Norfolk Island"},{"id":118,"name":"North Korea"},{"id":144,"name":"Northern Mariana Islands"},{"id":162,"name":"Norway"},{"id":167,"name":"Oman"},{"id":173,"name":"Pakistan"},{"id":180,"name":"Palau"},{"id":178,"name":"Palestinian Territory"},{"id":168,"name":"Panama"},{"id":171,"name":"Papua New Guinea"},{"id":181,"name":"Paraguay"},{"id":169,"name":"Peru"},{"id":172,"name":"Philippines"},{"id":176,"name":"Pitcairn"},{"id":174,"name":"Poland"},{"id":179,"name":"Portugal"},{"id":177,"name":"Puerto Rico"},{"id":182,"name":"Qatar"},{"id":183,"name":"Reunion"},{"id":184,"name":"Romania"},{"id":185,"name":"Russian Federation"},{"id":186,"name":"Rwanda"},{"id":193,"name":"Saint Helena"},{"id":117,"name":"Saint Kitts and Nevis"},{"id":125,"name":"Saint Lucia"},{"id":251,"name":"Saint Martin"},{"id":175,"name":"Saint Pierre and Miquelon"},{"id":229,"name":"Saint Vincent and the Grenadines"},{"id":247,"name":"Saint-Barthélemy"},{"id":236,"name":"Samoa"},{"id":198,"name":"San Marino"},{"id":202,"name":"Sao Tome and Principe"},{"id":187,"name":"Saudi Arabia"},{"id":199,"name":"Senegal"},{"id":248,"name":"Serbia"},{"id":189,"name":"Seychelles"},{"id":197,"name":"Sierra Leone"},{"id":192,"name":"Singapore"},{"id":252,"name":"Sint Maarten"},{"id":196,"name":"Slovakia"},{"id":194,"name":"Slovenia"},{"id":188,"name":"Solomon Islands"},{"id":200,"name":"Somalia"},{"id":239,"name":"South Africa"},{"id":89,"name":"South Georgia and the South Sandwich Islands"},{"id":119,"name":"South Korea"},{"id":255,"name":"South Sudan"},{"id":67,"name":"Spain"},{"id":127,"name":"Sri Lanka"},{"id":190,"name":"Sudan"},{"id":201,"name":"Suriname"},{"id":195,"name":"Svalbard and Jan Mayen"},{"id":205,"name":"Swaziland"},{"id":191,"name":"Sweden"},{"id":42,"name":"Switzerland"},{"id":204,"name":"Syria"},{"id":220,"name":"Taiwan"},{"id":211,"name":"Tajikistan"},{"id":221,"name":"Tanzania"},{"id":210,"name":"Thailand"},{"id":209,"name":"Togo"},{"id":212,"name":"Tokelau"},{"id":216,"name":"Tonga"},{"id":218,"name":"Trinidad and Tobago"},{"id":215,"name":"Tunisia"},{"id":217,"name":"Turkey"},{"id":214,"name":"Turkmenistan"},{"id":206,"name":"Turks and Caicos Islands"},{"id":219,"name":"Tuvalu"},{"id":223,"name":"Uganda"},{"id":222,"name":"Ukraine"},{"id":2,"name":"United Arab Emirates"},{"id":77,"name":"United Kingdom"},{"id":224,"name":"United States Minor Outlying Islands"},{"id":226,"name":"Uruguay"},{"id":225,"name":"USA"},{"id":227,"name":"Uzbekistan"},{"id":234,"name":"Vanuatu"},{"id":228,"name":"Vatican City (Holy See)"},{"id":230,"name":"Venezuela"},{"id":233,"name":"Vietnam"},{"id":231,"name":"Virgin Islands (British)"},{"id":232,"name":"Virgin Islands (U.S.)"},{"id":235,"name":"Wallis and Futuna"},{"id":65,"name":"Western Sahara"},{"id":237,"name":"Yemen"},{"id":241,"name":"Zaire"},{"id":240,"name":"Zambia"},{"id":242,"name":"Zimbabwe"}]; var gdprCountriesIds = [196,194,191,184,179,174,161,148,132,131,130,108,101,99,97,88,77,75,70,67,63,58,56,55,54,37,23,21,14]; </script> <section data-nosnippet class="section container subscribe-box hidden"> <div class="container__inner"> <div class="actions"> <div class="actions__left"> <h2>InfoQ Software Architects' Newsletter</h2> <span><p>A monthly overview of things you need to know as an architect or aspiring architect.</p> <p><a href="https://www.infoq.com/software-architects-newsletter#placeholderPastIssues">View an example</a></p> </span> <div class="newsletter__subscribe"> <form class="form gdpr" name="dataCollectCampaignNewsletterForm" id="dataCollectCampaignNewsletterForm" action="#" onsubmit="dataCollectNewsletter.saveSubscription(); return false;"> <div class="field newsletter__mail input__text input__no-label input__medium email"> <label for="email-dataCollectnewsletter-infoq" class="label field__label">Enter your e-mail address</label> <input id="email-dataCollectnewsletter-infoq" name="footerNewsletterEmail" placeholder="Enter your e-mail address" class="input field__input" type="email"/> <input type="text" name="emailH" id="input_email_h_d" aria-required="false" style="display:none !important" tabindex="-1" autocomplete="off"/> <input type="hidden" id="fnt_d" name="fnt_d" value="FaHUbNSfqo0L4vv3"/> <input type="hidden" id="dataCollectNewsletterType" name="dataCollectNewsletterType" value="regular"/> <input type="hidden" id="cmpi_d" name="cmpi_d" value="4"/> </div> <div class="hidden"> <span class="input__select field country"> <label for="input-dataCollect-newsletter-country" class="label field__label">Select your country</label> <select id="input-dataCollect-newsletter-country" class="select field__input"> <option value="" class="select__option">Select a country</option> </select> <p class="input__message field__desc"></p> </span> <span class="input__checkbox field hidden"> <input type="checkbox" id="gdpr-consent-campaign"> <label for="gdpr-consent-campaign" class="label"><span>I consent to InfoQ.com handling my data as explained in this <a href="https://www.infoq.com/privacy-notice">Privacy Notice</a>.</span></label> </span> </div> <input type="submit" role="button" value="Subscribe" class="button button__medium button__red" onclick="return dataCollectNewsletter.validateEmail('Invalid email address');"/> </form> <p class="meta"> <a href="/privacy-notice/" target="_blank">We protect your privacy.</a> </p> <span class="success" style="display:none;" id="dataCollectNewsletterMessage"></span> </div> </div> <div class="actions__right"> <button aria-label="Close" class="close closeBox button button__unstyled button__icon icon icon__close-black icon--only">Close</button> </div> </div> </div> </section> <script type="text/javascript"> var dataCollectNewsletter = new Newsletter('Enter your e-mail address', 'email-dataCollectnewsletter-infoq', 'dataCollectNewsletterType','dataCollectNewsletterMessage', 'fnt_d', 'input_email_h_d', 'input-dataCollect-newsletter-country', 'cmpi_d','popup_all_pages'); </script> <div class="infoq" id="infoq"> <!-- ####### SITE START ######### --> <section class="section container promo hidden"> <div class="container__inner"> <div class="actions"> <div class="actions__left"> <p> <span>Live Webinar and Q&amp;A: Architecting Scalable, Secure Multi-Agent Systems (Apr 8, 2025)</span> <a class="btn" href="/url/pb/cb7a965f-cf00-403d-9b45-779d1f95dd3f/" target="_blank" rel="nofollow"> Save Your Seat </a> </p> </div> <div class="actions__right"> <button aria-label="Close" class="close button button__unstyled button__icon icon icon__close-white icon--only close-top-promo">Close </button> </div> </div> </div> </section> <header class="header"> <button aria-label="Toggle Navigation" tabindex="0" class="burger header__toggle button">Toggle Navigation <span></span><span></span><span></span></button> <div class="header__container container"> <div class="container__inner"> <div data-nosnippet class="actions header__top"> <div class="actions__left"> <p class="header__desc my-0"> Facilitating the Spread of Knowledge and Innovation in Professional Software Development </p> <div class="button__dropdown dropdown header__more my-0 dropdown__center"> <button aria-label="English edition" class="button button__unstyled button__small">English edition </button> <div class="dropdown__holder"> <!----> <div class="dropdown__content"> <ul class="no-style dropdown__nav languagesEdition"> <li class="active"><a href="#" onclick="return false;">English edition</a></li> <li><a href="https://www.infoq.cn">Chinese edition</a></li> <li><a href="/jp/">Japanese edition</a></li> <li><a href="/fr/">French edition</a></li> </ul> </div> <!----> </div> </div> <a class="my-0 contribute-link" role="button" href="/write-for-infoq/" title="Write for InfoQ"> Write for InfoQ </a> </div> <div class="actions__right"> <div> <form id="searchForm" name="search-form" action="/search.action" enctype="multipart/form-data" class="search icon__search icon icon__green"> <div class="field search__bar input__text input__no-label input__small"> <label for="search" class="label field__label">Search</label> <input name="queryString" type="text" id="search" value="" placeholder="Search" class="input field__input"> <input type="hidden" name="page" value="1"/> <input type="hidden" size="15" name="searchOrder"> </div> <input value="Search" type="submit" class="search__go"> </form> </div> <div class="button__dropdown dropdown user__login"> <button aria-label="Sign Up / Login" class="button button__small button__green button__arrow arrow__true button__icon icon icon__user icon--only">Sign Up / Login</button> <div class="dropdown__holder"> <div class="dropdown__content"> <div class="login__dropdown"> <div class="login__module"> <div class="login__username"> <form id="login-form" data-vv-scope="login" class="login__form form" action="/login.action"> <input type="hidden" id="loginWidgetOrigin" name="loginWidgetOrigin" value="mainLogin"/> <input type="hidden" name="fromP13N" id="isP13n" value="false"/> <input type="hidden" name="fromP13NId" id="p13n-id" value=""/> <input type="hidden" name="fromP13NType" id="p13n-type" value=""/> <div class="field form__row input__text input__small" data-vv-as="Email" data-vv-scope="login"> <label for="email" class="label field__label">Email</label> <input type="text" id="email" placeholder="" class="input field__input" name="username"> </div> <div class="field form__row input__password input__small" data-vv-as="Password" data-vv-scope="login"> <label for="password" class="label field__label">Password</label> <input type="password" id="password" placeholder="" class="input field__input" name="password"> <p data-message="resultMessage"></p> </div> <input type="submit" value="Login" class="form__row button button__medium button__green"> <div class="login__actions"> <button aria-label="Forgot password ?" class="forgot button button__unstyled">Forgot password ?</button> </div> </form> <form id="forgot-password-form" data-vv-scope="forgot" class="forgot__form form" action="/resetpasswordinit.action" onsubmit="UserActions_Login.showMessage($(this),JSi18n.login_sendingRequest);"> <div data-vv-as="Email" data-vv-scope="forgot" class="field form__row input__text input__small"> <label for="forgotten_email" class="label field__label">InfoQ Account Email</label> <input id="forgotten_email" name="email" placeholder="" class="input field__input" type="text" onkeyup="UserActions_ResetPass.checkInputStatus('forgotten_email','forgotPassMessage',JSi18n.login_invalid_email,'submit_resetPass');"> <p id="forgotPassMessage" data-message="resultMessage"></p> </div> <input type="submit" id="submit_resetPass" value="Send Recovery Email" class="button button__medium button__green" onclick="return UserActions_ResetPass.checkInputStatus('forgotten_email','forgotPassMessage',JSi18n.login_invalid_email,'submit_resetPass');"> <p class="login__actions"> <button aria-label="Back to login" class="back-to-login button button__unstyled">Back to login</button> </p> </form> <form id="email-revalidation-form" data-vv-scope="revalidation" class="revalidation__form form" action="/reactivate.action" onsubmit="UserActions_Login.showMessage($(this),JSi18n.login_sendingRequest);"> <div data-vv-as="Email" data-vv-scope="revalidation" class="field form__row input__text input__small"> <label for="revalidated_email" class="label field__label">Resend Activation</label> <input id="revalidated_email" name="email" placeholder="" class="input field__input" type="text" onkeyup="UserActions_ResetPass.checkInputStatus('revalidated_email','emailRevalidMessage',JSi18n.login_invalid_email,'submit_resetPass');"> <p id="emailRevalidMessage" data-message="resultMessage"></p> </div> <input type="submit" value="Resend" class="button button__medium button__green" onclick="return UserActions_ResetPass.checkInputStatus('revalidated_email','emailRevalidMessage',JSi18n.login_invalid_email,'submit_resetPass');"> <p class="login__actions"> <button id="show-login" aria-label="Back to login" class="back-to-login button button__unstyled">Back to login</button> </p> </form> </div> <div class="login__social"> <h4 class="heading">Login with:</h4> <div class="social__connect form__row login__socials"> <a href="/social/googleLogin.action?fl=login" onclick="return UserActions_Login.addLoginInfo(this);" class="button button__medium button__gray button__icon icon icon__google" title="Login with Google">Google</a> <a href="/social/liveLogin.action?fl=login" onclick="return UserActions_Login.addLoginInfo(this);" class="button button__medium button__icon icon icon__microsoft" title="Login with Microsoft">Microsoft</a> <a href="/twitter-info" class="button button__medium button__icon icon icon__twitter" title="Login with Twitter">Twitter</a> <a href="/social/facebookLogin.action?fl=login" onclick="return UserActions_Login.addLoginInfo(this);" class="button button__medium button__icon icon icon__fb" title="Login with Facebook">Facebook</a> </div> </div> <div class="login__signup"> <h4 class="heading">Don't have an InfoQ account?</h4> <a href="/reginit.action?" onclick="return UserActions_Login.addLoginInfo(this);" class="button button__medium button__green">Sign Up</a> </div> </div> </div> </div> </div> </div> </div> </div> <div class="header__middle"> <div class="logo header__logo"> <a href="/" class="logo__symbol active"> Logo - Back to homepage </a> </div> <div class="content-items"> <a href="/news/" class="icon icon__news">News</a> <a href="/articles/" class="icon icon__articles">Articles</a> <a href="/presentations/" class="icon icon__presentations">Presentations</a> <a href="/podcasts/" class="icon icon__podcasts">Podcasts</a> <a href="/minibooks/" class="icon icon__guides">Guides</a> </div> <div class="header__items columns"> <div> <h3 class="widget__heading">Topics</h3> <nav class="nav header__nav topics" data-trk-ref="header_personas"> <div class="has--subnav li-nav"> <a href="/development/" title="Development" class="nav__category">Development</a> <div class="nav__subnav subnav"> <ul class="subnav__categories no-style"> <li><a href="/java/" title="Java">Java</a></li> <li><a href="/kotlin/" title="Kotlin">Kotlin</a></li> <li><a href="/dotnet/" title=".Net">.Net</a></li> <li><a href="/c_sharp/" title="C#">C#</a></li> <li><a href="/swift/" title="Swift">Swift</a></li> <li><a href="/golang/" title="Go">Go</a></li> <li><a href="/rust/" title="Rust">Rust</a></li> <li><a href="/javascript/" title="JavaScript">JavaScript</a></li> </ul> <div class="subnav__content" data-id="6815"> <div class="heading__container actions"> <div class="actions__left"> <h3 class="heading section__heading">Featured in Development</h3> </div> </div> <ul data-size="large" data-horizontal="true" data-tax="" taxonomy="articles" class="cards no-style"> <li> <div class="card__content"> <div class="card__data"> <h4 class="card__title"> <a href="/presentations/zero-trust-devsecops">A Zero Trust Future for Applications: Practical Implementation and Pitfalls</a> </h4> <p class="card__excerpt">Ashish Rajan shares a practical guide to working on zero trust, exploring where it fails even before it starts and where engineers should see quick wins. Surprisingly, the answer is not really DevSecOps.</p> <div class="card__footer"></div> </div> <a href="/presentations/zero-trust-devsecops" class="card__header"> <img loading="lazy" alt="A Zero Trust Future for Applications: Practical Implementation and Pitfalls" src="https://imgopt.infoq.com/fit-in/100x100/filters:quality(80)/presentations/zero-trust-devsecops/en/smallimage/ashish-rajan-small-1738148760241.jpeg" class="card__image"/> </a> </div> </li> </ul> <a href="/development/" class="button__more button button__large button__arrow arrow__right">All in development</a> </div> </div> </div> <div class="has--subnav li-nav"> <a href="/architecture-design/" title="Architecture &amp; Design" class="nav__category">Architecture &amp; Design</a> <div class="nav__subnav subnav"> <ul class="subnav__categories no-style"> <li><a href="/architecture/" title="Architecture">Architecture</a></li> <li><a href="/enterprise-architecture/" title="Enterprise Architecture">Enterprise Architecture</a></li> <li><a href="/performance-scalability/" title="Scalability/Performance">Scalability/Performance</a></li> <li><a href="/design/" title="Design">Design</a></li> <li><a href="/Case_Study/" title="Case Studies">Case Studies</a></li> <li><a href="/microservices/" title="Microservices">Microservices</a></li> <li><a href="/servicemesh/" title="Service Mesh">Service Mesh</a></li> <li><a href="/DesignPattern/" title="Patterns">Patterns</a></li> <li><a href="/Security/" title="Security">Security</a></li> </ul> <div class="subnav__content" data-id="6816"> <div class="heading__container actions"> <div class="actions__left"> <h3 class="heading section__heading">Featured in Architecture &amp; Design</h3> </div> </div> <ul data-size="large" data-horizontal="true" data-tax="" taxonomy="articles" class="cards no-style"> <li> <div class="card__content"> <div class="card__data"> <h4 class="card__title"> <a href="/articles/architectural-experimentation-insurance">If Architectural Experimentation Is So Great, Why Aren&rsquo;t You Doing It?</a> </h4> <p class="card__excerpt">Architectural experimentation sounds like a great idea, yet it does not seem to be used very frequently. In this article, we will explore some of the reasons why teams don’t use this powerful tool more often, and what they can do about leveraging that tool for successful outcomes.</p> <div class="card__footer"></div> </div> <a href="/articles/architectural-experimentation-insurance" class="card__header"> <img loading="lazy" alt="If Architectural Experimentation Is So Great, Why Aren&rsquo;t You Doing It?" src="https://imgopt.infoq.com/fit-in/100x100/filters:quality(80)/articles/architectural-experimentation-insurance/en/smallimage/architectural-experimentation-thumbnail-1740472356165.jpg" class="card__image"/> </a> </div> </li> </ul> <a href="/architecture-design/" class="button__more button button__large button__arrow arrow__right">All in architecture-design</a> </div> </div> </div> <div class="has--subnav li-nav"> <a href="/ai-ml-data-eng/" title="AI Infrastructure" class="nav__category">AI Infrastructure</a> <div class="nav__subnav subnav"> <ul class="subnav__categories no-style"> <li><a href="/bigdata/" title="Big Data">Big Data</a></li> <li><a href="/machinelearning/" title="Machine Learning">Machine Learning</a></li> <li><a href="/nosql/" title="NoSQL">NoSQL</a></li> <li><a href="/database/" title="Database">Database</a></li> <li><a href="/data-analytics/" title="Data Analytics">Data Analytics</a></li> <li><a href="/streaming/" title="Streaming">Streaming</a></li> </ul> <div class="subnav__content" data-id="16690"> <div class="heading__container actions"> <div class="actions__left"> <h3 class="heading section__heading">Featured in AI, ML &amp; Data Engineering</h3> </div> </div> <ul data-size="large" data-horizontal="true" data-tax="" taxonomy="articles" class="cards no-style"> <li> <div class="card__content"> <div class="card__data"> <h4 class="card__title"> <a href="/articles/secure-ai-powered-early-detection-system">Secure AI-Powered Early Detection System for Medical Data Analysis &amp; Diagnosis</a> </h4> <p class="card__excerpt">In this article, author discusses the techniques for securing AI applications in healthcare with an use case of early detection system for medical data analysis &amp; diagnosis. The proposed layered architecture includes application components to support secure computation, ai modeling, governance and compliance, and monitoring and auditing.</p> <div class="card__footer"></div> </div> <a href="/articles/secure-ai-powered-early-detection-system" class="card__header"> <img loading="lazy" alt="Secure AI-Powered Early Detection System for Medical Data Analysis &amp; Diagnosis" src="https://imgopt.infoq.com/fit-in/100x100/filters:quality(80)/articles/secure-ai-powered-early-detection-system/en/smallimage/designing-architecture-ai-models-thumbnail-1740475990469.jpg" class="card__image"/> </a> </div> </li> </ul> <a href="/ai-ml-data-eng/" class="button__more button button__large button__arrow arrow__right">All in ai-ml-data-eng</a> </div> </div> </div> <div class="has--subnav li-nav"> <a href="/culture-methods/" title="Culture &amp; Methods" class="nav__category">Culture &amp; Methods</a> <div class="nav__subnav subnav"> <ul class="subnav__categories no-style"> <li><a href="/agile/" title="Agile">Agile</a></li> <li><a href="/diversity/" title="Diversity">Diversity</a></li> <li><a href="/leadership/" title="Leadership">Leadership</a></li> <li><a href="/lean/" title="Lean/Kanban">Lean/Kanban</a></li> <li><a href="/personal-growth/" title="Personal Growth">Personal Growth</a></li> <li><a href="/scrum/" title="Scrum">Scrum</a></li> <li><a href="/sociocracy/" title="Sociocracy">Sociocracy</a></li> <li><a href="/software_craftsmanship/" title="Software Craftmanship">Software Craftmanship</a></li> <li><a href="/team-collaboration/" title="Team Collaboration">Team Collaboration</a></li> <li><a href="/testing/" title="Testing">Testing</a></li> <li><a href="/ux/" title="UX">UX</a></li> </ul> <div class="subnav__content" data-id="6817"> <div class="heading__container actions"> <div class="actions__left"> <h3 class="heading section__heading">Featured in Culture &amp; Methods</h3> </div> </div> <ul data-size="large" data-horizontal="true" data-tax="" taxonomy="articles" class="cards no-style"> <li> <div class="card__content"> <div class="card__data"> <h4 class="card__title"> <a href="/podcasts/resilience-observability-automation">Resilience, Observability and Unintended Consequences of Automation</a> </h4> <p class="card__excerpt">In this podcast, Shane Hastie, the Lead Editor for Culture &amp; Methods, spoke to Courtney Nash about her research on the unintended consequences of automation in software systems, the importance of learning from incidents, and maintaining human expertise in complex systems.</p> <div class="card__footer"></div> </div> <a href="/podcasts/resilience-observability-automation" class="card__header"> <img loading="lazy" alt="Resilience, Observability and Unintended Consequences of Automation" src="https://imgopt.infoq.com/fit-in/100x100/filters:quality(80)/podcasts/resilience-observability-automation/en/smallimage/engineering-culture-podcast-thumbnail-1740403416752.jpg" class="card__image"/> </a> </div> </li> </ul> <a href="/culture-methods/" class="button__more button button__large button__arrow arrow__right">All in culture-methods</a> </div> </div> </div> <div class="has--subnav li-nav"> <a href="/devops/" class="nav__category">DevOps</a> <div class="nav__subnav subnav"> <ul class="subnav__categories no-style"> <li><a href="/infrastructure/" title="Infrastructure">Infrastructure</a></li> <li><a href="/continuous_delivery/" title="Continuous Delivery">Continuous Delivery</a></li> <li><a href="/automation/" title="Automation">Automation</a></li> <li><a href="/containers/" title="Containers">Containers</a></li> <li><a href="/cloud-computing/" title="Cloud">Cloud</a></li> <li><a href="/observability/" title="Observability">Observability</a></li> </ul> <div class="subnav__content" data-id="6043"> <div class="heading__container actions"> <div class="actions__left"> <h3 class="heading section__heading">Featured in DevOps</h3> </div> </div> <ul data-size="large" data-horizontal="true" data-tax="" taxonomy="articles" class="cards no-style"> <li> <div class="card__content"> <div class="card__data"> <h4 class="card__title"> <a href="/presentations/devsecops-ai">Efficient DevSecOps Workflows with a Little Help from AI</a> </h4> <p class="card__excerpt">Michael Friedrich tells a story about experienced pain points, wasted hours debugging and solving, and learning how a little help from AI makes DevSecOps workflows efficient again.</p> <div class="card__footer"></div> </div> <a href="/presentations/devsecops-ai" class="card__header"> <img loading="lazy" alt="Efficient DevSecOps Workflows with a Little Help from AI" src="https://imgopt.infoq.com/fit-in/100x100/filters:quality(80)/presentations/devsecops-ai/en/smallimage/MichaelFriedrich-small-1734515745316.jpg" class="card__image"/> </a> </div> </li> </ul> <a href="/devops/" class="button__more button button__large button__arrow arrow__right">All in devops</a> </div> </div> </div> <div class="li-nav"> <a rel="noreferrer noopener" href="https://events.infoq.com/" class="nav__category" title="Events" target="_blank">Events</a> </div> </nav> </div> <div> <h3 class="widget__heading">Helpful links</h3> <ul class="no-style header__nav"> <li> <a href="/about-infoq" title="About InfoQ"> About InfoQ </a> </li> <li> <a href="/infoq-editors" title="InfoQ Editors"> InfoQ Editors </a> </li> <li> <a href="/write-for-infoq" title="Write for InfoQ"> Write for InfoQ </a> </li> <li> <a href="/about-c4media" title="About C4Media"> About C4Media </a> </li> <li> <a rel="noreferrer noopener" href="https://c4media.com/diversity" title="Diversity" target="_blank">Diversity</a> </li> </ul> </div> <div> <h3 class="widget__heading">Choose your language</h3> <ul class="language__switcher no-style"> <li class="active"><a href="#" onclick="return false;" title="InfoQ English">En</a></li> <li><a href="https://www.infoq.cn">中文</a></li> <li><a href="/jp/">日本</a></li> <li><a href="/fr/">Fr</a></li> </ul> </div> </div> </div> <div data-nosnippet class="actions header__bottom header__bottom__events"> <div class="actions__left"> <div class="header__events-all"> <a href="https://qconlondon.com/?utm_source=infoq&utm_medium=referral&utm_campaign=homepageheader_qlondon25" rel="nofollow" target="_blank" class="header__event-slot"> <picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvbG9uZG9uLXRvcC11cGRhdGVkMi5qcGciLCJlZGl0cyI6IHsid2VicCI6IHsgInF1YWxpdHkiOjgwfX19" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvbG9uZG9uLXRvcC11cGRhdGVkMi5qcGciLCJlZGl0cyI6IHsianBlZyI6IHsgInF1YWxpdHkiOjgwfX19" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvbG9uZG9uLXRvcC11cGRhdGVkMi5qcGciLCJlZGl0cyI6IHsianBlZyI6IHsgInF1YWxpdHkiOjgwfX19" loading="lazy" width="40px" height="40px" alt="QCon London - image"></picture> <div> <span>QCon London</span> <p>Discover emerging trends, insights, and real-world best practices in software development &amp; tech leadership. Join now.</p> </div> </a> <a href="https://devsummit.infoq.com/conference/boston2025?utm_source=infoq&utm_medium=referral&utm_campaign=homepageheader_idsboston25" rel="nofollow" target="_blank" class="header__event-slot"> <picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvSW5mb1FEZXZTdW1taXQtdG9wLmpwZyIsImVkaXRzIjogeyJ3ZWJwIjogeyAicXVhbGl0eSI6ODB9fX0=" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvSW5mb1FEZXZTdW1taXQtdG9wLmpwZyIsImVkaXRzIjogeyJqcGVnIjogeyAicXVhbGl0eSI6ODB9fX0=" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvSW5mb1FEZXZTdW1taXQtdG9wLmpwZyIsImVkaXRzIjogeyJqcGVnIjogeyAicXVhbGl0eSI6ODB9fX0=" loading="lazy" width="40px" height="40px" alt="InfoQ Dev Summit Boston - image"></picture> <div> <span>InfoQ Dev Summit Boston</span> <p>Learn how senior software developers are solving the challenges you face. Register now with early bird tickets.</p> </div> </a> <a href="https://devsummit.infoq.com/conference/munich2025?utm_source=infoq&utm_medium=referral&utm_campaign=homepageheader_idsmunich25" rel="nofollow" target="_blank" class="header__event-slot"> <picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvSURTLU11bmljaC10b3AuanBnIiwiZWRpdHMiOiB7IndlYnAiOiB7ICJxdWFsaXR5Ijo4MH19fQ==" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvSURTLU11bmljaC10b3AuanBnIiwiZWRpdHMiOiB7ImpwZWciOiB7ICJxdWFsaXR5Ijo4MH19fQ==" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvSURTLU11bmljaC10b3AuanBnIiwiZWRpdHMiOiB7ImpwZWciOiB7ICJxdWFsaXR5Ijo4MH19fQ==" loading="lazy" width="40px" height="40px" alt="InfoQ Dev Summit Munich - image"></picture> <div> <span>InfoQ Dev Summit Munich</span> <p>Learn practical solutions to today's most pressing software challenges. Register now with early bird tickets.</p> </div> </a> <a href="https://qconsf.com/?utm_source=infoq&utm_medium=referral&utm_campaign=homepageheader_qsf25" rel="nofollow" target="_blank" class="header__event-slot"> <picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvU0YtdG9wLmpwZyIsImVkaXRzIjogeyJ3ZWJwIjogeyAicXVhbGl0eSI6ODB9fX0=" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvU0YtdG9wLmpwZyIsImVkaXRzIjogeyJqcGVnIjogeyAicXVhbGl0eSI6ODB9fX0=" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvaGVhZGVyL2NvbmZlcmVuY2VzLzIwMjUvU0YtdG9wLmpwZyIsImVkaXRzIjogeyJqcGVnIjogeyAicXVhbGl0eSI6ODB9fX0=" loading="lazy" width="40px" height="40px" alt="QCon San Francisco - image"></picture> <div> <span>QCon San Francisco</span> <p>Explore insights, real-world best practices and solutions in software development & leadership. Register now.</p> </div> </a> </div> </div> <!----> </div> </div> </div> </header> <!-- ####### CONTENT START ######### --> <main> <div> <section class="container section white"> <div class="container__inner"> <article data-type="presentation" class="article grid transcript rightbar"> <p class="crumbs"> <span data-nosnippet><a href="/" title="InfoQ Homepage">InfoQ Homepage</a></span> <span data-nosnippet><a href="/presentations" title="Presentations">Presentations</a></span> <span data-nosnippet class="active">0 → 1, Shipping Threads in 5 Months</span> </p> <div class="article__category architecture-design"> <a href="/architecture-design/" class="article__tag box--info" title="Architecture &amp; Design"> Architecture &amp; Design </a> </div> <div data-nosnippet class="notice"> <div class="box--warning"> <a target="_blank" rel="nofollow" href="https://qconlondon.com/?utm_source=infoq&amp;utm_medium=referral&amp;utm_campaign=infoqyellowbox_qlondon25 ">QCon London (April 7-10, 2025): Learn the emerging trends. Implement best practices. </a> </div> </div> <h1>0 → 1, Shipping Threads in 5 Months</h1> <div class="article__actions"> <div class="actions__left actions__sidebar article__actions"> <button id="toggleLikeContent" class="icon button button__icon like button__gray icon__like" aria-label="Like">Like</button> <div class="bookmarkReading"> <button id="bookmarkBtn" data-ref="bookmarkPage" aria-label="Read later" class="login button__gray button button__icon icon icon__bookmark icon--only"> </button> <!-- new dropdown rading list --> <div class="my-0 button__dropdown dropdown reading_list dropdown__center" id="showBookmarks"> <button aria-label="Reading list" class="button button__unstyled button__small"></button> <div class="dropdown__holder"> <div class="dropdown__content"> <ul class="no-style dropdown__nav"> <li class="active"><a href="/showbookmarks.action">Reading list</a></li> </ul> </div> </div> </div> <div id="toastContainer" class="toast-none toast-hide"> <div class="toast"><span></span></div> </div> </div> <script type="text/javascript"> if(loggedIn){ $('#showBookmarks').css('display', 'flex'); } function performBookmark() { Bookmarks.toggleBookmark('presentations', 'threads-meta'); } infoq.event.on('bookmarkRequested', function(e) { Bookmarks.toggleBookmark('presentations', 'threads-meta'); }); infoq.event.on("loaded", function(){ if(loggedIn){ var href = window.location.href; if(href.indexOf("#bookmarkPage") != -1){ $('#bookmarkBtn').click(); } } }); $(document).ready(function() { if(Bookmarks.isContentBookmarked == 'true'){ $('#bookmarkBtn').addClass('button__green'); $('#bookmarkBtn').removeClass('button__gray'); }else{ $('#bookmarkBtn').removeClass('button__green'); $('#bookmarkBtn').addClass('button__gray'); } }); </script> </div> </div> <div class="presentation__switch"> <label class="label">View Presentation</label> <ul class="no-style"> <li><button class="button button__unstyled button__tooltip tooltip__top button__icon icon icon__pres-2-cols icon--only active" aria-label="Vertical" data-tip="Vertical" data-tip-placement="top" data-key="pres-2-cols">Vertical</button></li> <li><button class="button button__unstyled button__tooltip tooltip__top button__icon icon icon__pres-1-col icon--only" aria-label="Horizontal" data-tip="Horizontal" data-tip-placement="top" data-key="pres-1-col">Horizontal</button></li> <li><button class="button button__unstyled button__tooltip tooltip__top button__icon icon icon__pres-fs icon--only" aria-label="Full" data-tip="Full" data-tip-placement="top" data-key="pres-fs">Full</button></li> </ul> </div> <div class="speed"> <label class="label">Speed:</label> <ul id="presentation_speed" class="no-style presentation_speed"> <li><button class="button button__unstyled active" aria-label="1x" onclick="P.adjustSpeed(1.0, $(this));return false;">1x</button></li> <li><button class="button button__unstyled" aria-label="1.25x" onclick="P.adjustSpeed(1.25, $(this));return false;">1.25x</button></li> <li><button class="button button__unstyled" aria-label="1.5x" onclick="P.adjustSpeed(1.5, $(this));return false;">1.5x</button></li> <li><button class="button button__unstyled" aria-label="2x" onclick="P.adjustSpeed(2.0, $(this));return false;">2x</button></li> </ul> </div> <div class="player"> <div id="player"> <script type="text/javascript"> SlideSynchronizer.setTimes(TIMES); SlideSynchronizer.playerId="video"; </script> <video id="video" playsinline controls controlsList="nodownload" width="100%" height="100%" onplay="SlideSynchronizer.start();"></video> </div> <div class="actions player__actions"> <div class="actions__left"> </div> <div class="actions__right"><span>48:43</span></div> </div> </div> <div id="slideContainer" class="intro slides"> <div id="slide"></div> </div> <div class="summary"> <h2 class="heading">Summary</h2> <p>Zahan Malkani shares how they built a microblogging service to compete with Twitter with a small team that shipped a new social network in a few months.</p> </div> <div data-nosnippet class="bio"> <h2 class="heading">Bio</h2> <p>Zahan Malkani was trained as a physicist, but fell into making software almost by accident. In his 11 years as a software engineer at Meta, he’s worked on a range of things including the Facebook product, internet.org, dev tools, a hardware product, to Instagram and two generations of Threads apps.</p> </div> <div data-nosnippet class="about-conference"> <h2 class="heading">About the conference</h2> <p>Software is changing the world. QCon London empowers software development by facilitating the spread of knowledge and innovation in the developer community. A practitioner-driven conference, QCon is designed for technical team leads, architects, engineering directors, and project managers who influence innovation in their teams.</p> </div> <div data-nosnippet class="event__list-box box__border"> <h3>INFOQ EVENTS</h3> <ul class="cards no-style webinarEvents"> <li data-col="1/1" data-type="webinar" hoverables=""><img alt="" data-src="sponsorship/eventsnotice/fb4b0b81-12dc-4d49-9596-5ff174c0dcd1/resources/1BoomiWebinarApril8-Transcript-1741000290392.png" style="width: 288px; height: 145px;" src="https://imgopt.infoq.com/fit-in/3000x4000/filters:quality(85)/filters:no_upscale()/sponsorship/eventsnotice/fb4b0b81-12dc-4d49-9596-5ff174c0dcd1/resources/1BoomiWebinarApril8-Transcript-1741000290392.png" rel="share"> <span class="date">Apr 8th, 2025, 12 PM EDT</span> <h4 class="title"><a href="https://www.infoq.com/url/t/6790dd40-fe63-477d-9f70-91f9b9659333/?label=Boomi-Transcripts" rel="nofollow" target="_blank">Architecting Scalable, Secure Multi-Agent Systems</a></h4> <p class="card__excerpt"><a href="https://www.infoq.com/url/t/6790dd40-fe63-477d-9f70-91f9b9659333/?label=Boomi-Transcripts" rel="nofollow" target="_blank">Presented by: Michael Bachman - Head of Architecture and AI Strategy at Boomi</a></p> <footer> <div class="authors"><span><a data-id="author-SPONSORED BY SPONSOR" href="https://www.infoq.com/url/t/6790dd40-fe63-477d-9f70-91f9b9659333/?label=Boomi-Transcripts" rel="nofollow" target="_blank">SPONSORED BY BOOMI</a></span></div> </footer> </li> </ul> </div> <div class="article__content"> <div class="article__data"> <div id="presentationNotes"> <h2 class="expanded">Transcript</h2> <p>Malkani: I&#39;m Zahan. I&#39;ve been an engineer at Meta for over a decade. I&#39;m here to tell you about how we launched the Threads app last year. Let&#39;s start by talking about the opportunity that presented itself. It was January last year, and I&#39;d just returned to work after a couple of months on leave. I was looking for something to work on and the tech scene was buzzing about Elon&#39;s business decision since he took Twitter private in November. We were talking about it at Meta as well. For reference, back in 2019, Mark had made the call that public conversations were not the focus, and pivoted both Facebook and Instagram to focus on private communication between friends instead. The analogies were the public town square and the living room.</p> <p>Mark&#39;s view was that communication in the living room was going to grow more over the next decade. That left Twitter as the de facto forum to debate ideas in public, a function so important, I think we all can agree, to society. Since Elon took over at Twitter, he made a number of controversial decisions, pretty lightly. Popular opinion was that it was just a matter of time before the site had an extended outage depriving millions of their favorite place online. It was increasingly obvious that there was an opportunity opening up here.</p> <p>The world clearly valued a service like Twitter, and the primary value in a social network is the people in it not the product. As many people abandoned Twitter, they were looking for somewhere else to hang out. At first, we thought that maybe the differentiating feature here is the text format, so we made it easier to make text posts on our existing products. In Instagram, some double-digit percentage of posts have some form of text on them, so we figured, what if it were easy to make posts that had nothing but text in it? How would that fare? It didn&#39;t get much usage.</p> <p>Few used the format, because while Instagram and Twitter share mechanical similarities, like a directed follow graph, and a feed that&#39;s based on interest, each product has its own culture, its own raison d&#39;etre that&#39;s set early in the product lifecycle. While Twitter was the public town square, Instagram was where you caught up with your friends&#39; lives, or where you are entertained by short-form videos. We realized that to build a competing product, we really would have to build a new product with a new set of norms.</p> <p>The main concern we had starting from scratch was how long this could potentially take. We were acutely aware that we had a fleeting window of opportunity to capitalize on here, that could disappear as quickly as it appeared. People still love Twitter as a brand, though little did I know of his plans for the brand. Still, in our view, time to market was all that mattered, and we enshrined that in everything we did. Every shortcut was on the table, every bit of scope up for debate, every complication a source of concern. The ask was that we needed to be prepared to ship at very short notice.</p> <h2 class="expanded">Part 2 - The Product</h2> <p>Let&#39;s focus on exactly what we wanted to build. We started by laying out the basic values of this product, we had four. First, the format here was text. Every post needed to start with text. Instagram put media front and center but not here. Two, we wanted to carry over the design language and ethos of Instagram. The simplicity, the feel of the product that so many love around the world. We felt like that was a good foundation. Three, we knew that one of the values that helped early Twitter establish itself was its openness. By this I mean that the community was free to craft their own experience with an API.</p> <p>Public content was widely available on the web through embeds. People generally used these tools to share their Twitter feed all over the place. While this is a new world, with GenAI coming up, we felt like a new walled garden product just wouldn&#39;t fly. We were paying attention to Mastodon, the fediverse, the interoperable social networks. I&#39;ll talk more about that later. Lastly, we felt like we needed to prioritize the needs of creators. Every social network has a class of folks who produce the majority of the content that others consume. This usually follows the Zipfian exponential distribution. On text-based networks this is exaggerated, and it&#39;s a smaller proportion of the user base who produce most of the content. It&#39;s hard to be interesting and funny in 500 characters. We knew that keeping the needs of this community in mind was critical for long term success.</p> <p>With these values in mind, we sketched out what the absolute bare minimum product was and got to work building. To give ourselves goalposts, we outlined four milestones we&#39;d like to get to. An important objective was that we wanted to have a product ready to ship as soon as possible to give us options. Each milestone was designed to be a possible end state itself, where we could ship if needed, each one gradually layered on the next most essential bit of functionality. Milestone one was just about standing up the app. You can see how bare bones that is.</p> <p>Being able to log in, to make a text post that gets associated with your account. Really just the basics. Milestone two was our essentials bucket. Giving the app its familiar look with tabs for feed, notifications, and profile. Getting the basics of integrity working, being able to block another profile, to report it. Milestone three was what we called the lean launch candidate. Here we fleshed out services that had been neglected before, like a basic people search, a full screen media viewer to view photos and videos. Starting to figure out what to do with conversations, the lifeblood of the app. How do you rank them as a unit? Copying your follow graph from IG so that you can bootstrap your profile, and the ability to mute other profiles.</p> <p>That&#39;s a long laundry list. Milestone four was where we enabled interoperability with the fediverse, and was a final ship candidate. For anyone who knows the product, you might be laughing at the ambitiousness because we are far from full fediverse interop even today. In one of my weaker moments, I promised we could have this ready within the month. This was going to be the last thing we tackled in May. We took this very seriously. As each milestone neared, we&#39;d shifted from a building features mindset to a polish for launch mindset. This was honestly exhausting as an engineer, as the context switching between building mods is taxing.</p> <p>In some ways, we shipped three products in those six months. Each time we&#39;d call a war room, burn the midnight oil, and push through to get a complete app. Then we decide whether we were ready or not to ship. With the benefit of hindsight, I now see there was a big upside to the strategy. It served as a strong forcing function to simplify the product. If all you get is three weeks to pick what features you will add, and which will add the most incremental value, you really have to boil it down to just the basics. The actual product we shipped was something like M3.5. We never got anywhere near M4, but we did get a much-needed iteration on top of M3.</p> <h2 class="expanded">Part 3 - Shortcut</h2> <p>All of this would be extremely ambitious to build from scratch in five months. We started in earnest in Feb, and we were promising our leadership that we&#39;d have it ready by the summer. We had a trick up our sleeves, and that was that we had no intention of building this from scratch. When you take a wide-angle view, broadcast sharing on Instagram is fairly straightforward. You can follow profiles, access a feed of their posts, plus some recommendations. You can respond to one another, building up communities around interests. Coincidentally, this is exactly the set of features we wanted for Threads on day one, so we did it.</p> <p>We took the biggest shortcut ever and reused Instagram wholesale. For the backend, it literally just is the Instagram backend with some custom functionality for Threads. For the apps, we forked the Instagram app code base on each platform. Starting from Instagram, and that we started with a fully featured product and had to strip it down to just the functionality needed. The screen recording shows what I mean. Our first prototype added a mod to the Instagram feed that surfaced text-only posts. We reused the ranking. For the post, the inside joke is that we just reordered the layout. We put the caption on top and the media on the bottom, everything else is just the same. This drastically reduced technical scope.</p> <p>We&#39;ve now taken the intractable problem of how do you build a new text-based social network and turn it into a very specific one? How do I customize Instagram feed to display a new text post format? As engineers, you will undoubtedly note that this approach has major downsides. You&#39;re accumulating massive tech debt using a code base for something new that it wasn&#39;t designed to serve. There&#39;s a whole series of paper cuts that you accumulate as a result. You also need to know said legacy code base inside and out. It&#39;s millions of lines of code, but you need to customize just a few so that you can effectively repurpose it.</p> <p>My favorite one-liner about this is that it&#39;s harder to read someone else&#39;s code than it is to write your own. With this, you&#39;re losing your one chance to start over clean. This approach help us stay focused on the product and keep this experience simple. A user could onboard by just logging in with Instagram. We borrowed Instagram&#39;s design language. Your Instagram identity bootstrapped your Threads one.</p> <p>We carried the spirit throughout, surgically reusing what we could and rebuilding only where necessary. It also means that the Threads team has much to be grateful for, the existence of Threads itself owes itself to the foundation laid by Instagram infra and product teams over the years. We&#39;d be nowhere without it. I like to think that this focus on simplicity paid off. Much of the praise we received at launch was for the sparkling simplicity of the app without it feeling like it lacked essential features.</p> <h2 class="expanded">Part 4 - The Details</h2> <p>Now to dive into a couple of areas with interesting implications. One technique we use to tune the experience quickly was to make iteration in the product itself very easy. We did this using server driven UI. In a traditional client-server model, the client is responsible for everything about how the data is laid out on-screen. The server is just middleware pulling data out from stores. What we did was for the core interfaces which showed a list of posts, we instead sent down a full view model, which told the client exactly how to render it. This meant that when we were experimenting on the call to action and the reply bar, or when and how we show different reply face files, we could do that with just a code change on the server, which only takes a couple of hours to roll out and takes effect on all platforms.</p> <p>This let us iterate on the core Threading UI very quickly in the early days. Another big focus was making the space feel safe and welcoming for all. We&#39;d seen public social networks before and many turn into angry spaces where people just don&#39;t hear each other out. Of course, the jury is still out on what degree Threads can live up to this aspiration, but I think there&#39;s a few factors that are important. First is the product culture, set from the early days by those who are the seed of your network. A lot of our early users were experienced in this and so you saw a lot of callouts like, block early and often. Don&#39;t engage with rage bait. Don&#39;t use quote posts to dunk on people.</p> <p>Then there&#39;s the tooling that helps people maintain control over their experience. For instance, it starts with the ability to block, of course. There&#39;s variations on this for different circumstances, like restrict, which ensures that the other party doesn&#39;t know you took action, and mute which hides their content from your feed.</p> <p>There&#39;s the popular hide reply functionality, which gives you some small control over the conversation that your post generates. Lastly, there&#39;s moderation. It&#39;s tricky to get right. There&#39;s no doubt in my mind that robust moderation is essential. To make a space acceptable to a mainstream audience, you need to do something about the extremes of speech. There&#39;s just too much breadth in what one can find on the open internet. I&#39;ll go as far as to say that for a new social network today, that is the unique value you&#39;re providing. In many ways, moderation is the product people are subscribing to. Luckily, we brought a decade of experience with this from Facebook and Instagram here. While I&#39;m sure it needs further tuning to feel right, at least we started from a good starting point. Combined with features and culture, all these helped set healthy new norms.</p> <p>The last focus I want to touch on is creating a buzz for the product before launch. An example of this is the golden ticket Easter egg, which we had made and hidden in Instagram. You might call this holographic effect overengineered, but it looked beautiful and felt playful, which sparked interest. We had little hidden entry points, specific keyword searches, hashtags, and long presses, to let people know that something was launching soon and let them sign up for a reminder. Moreover, we had a small early access launch for journalists and creators who had shown an interest. It ended up being just a day or so, but it gave them a chance to learn and see what this new platform was like. It didn&#39;t hurt that when they shared their impressions with their audience, the curiosity grew.</p> <h2 class="expanded">Part 5 - The Launch</h2> <p>If you&#39;re tired of fuzzy stories, this is when we get to the more technical part of the talk. To understand the launch, I need to give you a quick technical overview of the Threads stack. Meta in general is big into monolithic binaries and its monorepo. There&#39;s a number of reasons for this. The upshot is that much of Instagram&#39;s business logic lives in a Python binary called Distillery, which talks to Meta&#39;s bigger monolith, a massive PHP binary or Hack binary called WWW. Distillery is probably the largest Django deployment in the world, something I don&#39;t know if we&#39;re proud of, even if we run a pretty custom version of it.</p> <p>The data for our users is stored in a variety of systems. The most important ones are TAO, a write-through cache that operates on a graph data model, and UDB, so a sharded MySQL deployment that stores almost all our data. By graph data model, I mean that TAO is natively familiar with links between nodes and has optimized operations to query details of those. There&#39;s indexing systems on top that let you annotate particular links with how you want to query them. They build in memory indexes to help. The whole model has evolved over many years of building social products as Meta, and this has served us well.</p> <p>There&#39;s also other systems involved, and I can&#39;t do them all justice. There&#39;s a big Haskell service that fronts a lot of the rules that go into our decision making around restrictions, like looking for inauthentic behavior in user actions. There&#39;s a key-value store called ZippyDB that&#39;s used to stash lots of transient data that&#39;s written too often for MySQL to handle the load. There&#39;s a serverless compute platform, async, which was critical, and I&#39;ll cover it later. Then there&#39;s a Kubernetes-like system for managing, deploying, and scaling all these services. All of these need to work in concert.</p> <p>That&#39;s the background into which you insert our little product going live in July of last year. The story is that we were planning for a mid-July launch when news started doing the rounds that Twitter planned to restrict consumption of tweets for free users. This started a significant new cycle and we saw an opportunity, so we decided to launch a week early, even though it meant forgoing some load testing and final prep work. The launch was set for July 6th, and we opened up the Easter eggs I mentioned to generate buzz, and we started our early access program. On July 5th, anyone who wasn&#39;t an engineer was happily hanging out on the product with the celebs who had come on for early access. This was probably the closest anyone was going to get to a personal chat with Shakira. For engineers, it was an all hands on deck preparation for launch the next day, upsizing systems, sketching out the runup show, and the like. I&#39;ve never forgiven my product manager for that.</p> <p>Then in the middle of the day, our data engineer popped up in the chat and mentioned something odd. He was seeing tens of thousands of failed login attempts on our app. This was odd, because no one, certainly not tens of thousands of people should have access to the app yet. We pivoted quickly and ruled out a data issue. Then we noticed that all of these were coming from East Asian countries. Maybe you figured it out, it would take us another beat to realize that this was time zones. Specifically, we were using the App Store&#39;s preorder feature where people can sign up to download your app once it&#39;s available, and you specify a date. Since we said July 6th, once it was past midnight in these countries, the app became available, and they couldn&#39;t log in because of another gate on our end.</p> <p>This was an oh-shit moment. The warm fuzzy feeling of being safely ensconced in an internal only limited testing was gone. We pulled together a war room and a Zoom call with close to 100 experts from around the company and all the various systems I mentioned. Given that this was the middle of the night in those countries, it was evident that demand was going to far exceed our estimations once this all went live. We had a healthy preorder backlog built up and they were all going to get the app once the clock struck midnight in their local time.</p> <p>We chose a new target launch time, specifically midnight UK time, which gave us a couple of hours to prepare. We spent that time upsizing all the systems the Threads touched. I fondly remember a particular ZippyDB cache that is essential for feed to function at all, that needed to be resharded. It had to be resharded to handle 100x the capacity it was provisioned for. That job ended minutes before Mark posted that Threads was open for signups. I don&#39;t think I&#39;ll ever forget the stress of those final moments.</p> <p>The user growth in those first couple of days has been well covered elsewhere. Broadly, a million people downloaded our app and onboarded to try it out in the first hour from when it went live. Ten million in the first day. Seventy million in the first two days, and about 100 million in the first five days. After that, the novelty effect started to wear off and the buzziness subsided, but surviving those first five days was quite the feat. While people would later opine that it was great that Threads had a relatively smooth ride with no major visible downtime, it certainly didn&#39;t feel that way to me.</p> <p>We had a number of fires going at all times, and I didn&#39;t sleep much that week. What kept us up was all the experts in the room, certainly not me, who had the experience of dealing with larger user bases if not facing this kind of explosive growth. We tweaked the network enough to stay afloat, and we furiously fought the fires to keep things from spiraling. To pick a couple of interesting fires. The first is that we were consuming more capacity than one should. We were serving just as relatively small pool of posts to a smallish user base.</p> <p>This was most evident on our boss&#39;s timeline. We started getting reports it was actually failing to load. The thing is that Mark had an order of magnitude more interactions with his posts than anyone else in that early network. More likes, replies, reposts, quote posts, you name it, Mark was at five digits when everyone else was at four. We finally root caused this to a particular database query that we needed to render every post, but the runtimes scaled with the number of repos. It needed an index. With a couple of tries, we nailed the problematic query, and the site got healthier.</p> <p>Another fire revolved around copying the follower graph from Instagram to Threads. When someone signed up for Threads, we gave them the option to follow everyone that they already follow on Instagram, on Threads. That might sound daunting, but it&#39;s actually a limited operation. You have a maximum number of people you can follow, in the single digit thousands. That works fine. It&#39;s a limited operation. Our serverless compute platform soaked up the load. I think at one point, we had a backlog in the tens of millions in the job queue, but with some handholding, it worked just fine.</p> <p>Again, a testament to the wonderful engineering that&#39;s gone into these systems. The issue with graph copying was that you could also say that you wanted to follow people who hadn&#39;t signed up for Threads yet. Maybe you can see the issue now, because handling that person signing up is an unbounded operation. When big celebrities, say former President Barack Obama signed up for Threads, they had a backlog in the millions of people who were waiting to follow them. The system that we had originally designed simply couldn&#39;t handle that scale. We raced to redesign that system to horizontally scale and orchestrate a bunch of workers, so it could eat through these humongous queues for these sorts of accounts. We also tried to manually get through the backlog since this was a sensitive time for the product.</p> <p>We didn&#39;t want to leave potential engagement on the table. It was a hair-raising couple of days, but I loved the design of the system we finally made, and it&#39;s worked smoothly ever since. All told, I doubt I&#39;ll ever experience a product launch quite like that again. I learned a bunch from others about staying graceful in stressful situations. I&#39;ll carry that wherever I go.</p> <h2 class="expanded">Part 5 - After Launch</h2> <p>Past the launch, we needed to quickly pivot to address features that users were asking for. It had now been nine months. In that time, we finally opened to Europe in this last December. We shipped a following feed, a feed you have full control over with content from people you follow, sorted chronologically. We got our web client out there which caters to our power users. We have a limited release of an API that allows you to read and write posts. We polished content search and started showing what conversations are trending on the network.</p> <p>We also have big questions that loom over us. What should play a more important role in ranking? The follow graph that people choose, or understanding content and matching it with people&#39;s reveal preferences? How do we cater to the needs of power users who&#39;ve come over from Twitter who have very clear ideas about what to expect from the product, while also serving all the people who are new to a text-based public conversation app? One of the developments you might find more interesting is about the adoption of ActivityPub. This is an open protocol for interoperating between microblogging networks. The accumulation of those networks is called the fediverse. Keen-eyed listeners will note that I had promised fediverse interop on an insanely ambitious timeline pre-launch, but thankfully that wasn&#39;t put to the test.</p> <p>Today we&#39;re approaching fediverse interop, piece by piece, and we want to build it right instead of building it quickly. The reason is that we cannot integrate it into the legacy Instagram broadcast sharing stack. It has too many integration points with the rest of Meta, and we want to make strong guarantees about how we process this important data. We essentially need to rewrite our business logic and backend stack, which is ongoing.</p> <h2 class="expanded">Takeaways</h2> <p>In conclusion, getting this off the ground was a unique experience for me. My biggest takeaway is the power of keeping things simple. It&#39;s certainly not easy. The aphorism about it taking longer to write a shorter letter applies to anything creative. If you&#39;re clear about the value you want to provide, it can guide all your hard decisions on where you want to cut scope. The other learning is that cleaner, newer code isn&#39;t necessarily always better. All the little learnings encoded into an old battle tested code base add up. If you can help it, don&#39;t throw it away. The compliment to this is us saying that code wins arguments.</p> <p>This is to say that building a product often answers questions better than an abstract analysis. We got through a lot of thorny questions quicker with prototypes instead of slide decks. Of course, nothing can be entirely generalized, because we need to acknowledge how lucky we are for the opportunity and the reception once this product came out. None of that was guaranteed. I feel very grateful for the community that embraced the product. We have a saying that goes back to the early days of Facebook that this journey is just 1% finished. It indeed feels that way to me, especially with Threads.</p> <h2 class="expanded">Questions and Answers</h2> <p>Participant 1: What was the size and maturity of the engineering team put on this task?</p> <p>Malkani: I think, as we started building, it was like a rolling stone. We started with maybe 5 to 10 engineers, in Jan. By the middle of it, we were up to 25, 30 engineers. By launch, we were up to maybe 30, 40 engineers on the core product team. Again, standing on the shoulders of giants. This doesn&#39;t count all the pieces that we were able to reuse, and platform teams we could lean on for different pieces. In the end, maybe it was more like 100 engineers who contributed in some way. Of course, we got to reuse all those bits of infra and stuff. The core product team stayed under 50.</p> <p>Participant 2: Can you talk a little bit about the testing? How did you ensure that it worked, and you don&#39;t kill yourself, Instagram and everything?</p> <p>Malkani: We didn&#39;t get to test much because of the timeline. We lived on the product, of course. From the time that it was a standalone app, and we could download it on our phones, we published all the time, we shared. Instagram itself is a fairly big organization. They&#39;re like a couple of thousand people. For at least a couple of months, a couple of thousand people were using the app. It was all internal only content, and we wiped it all before we went public.</p> <p>We got a fair amount of ad hoc testing that way. We were not prepared for the scale. That&#39;s again what a lot of this talk is about, is about handling that. Then we were able to react quickly and rely on these systems that have been built for the scale. On the backend, we do have a pretty good test-driven development culture where we write a lot of integration tests for APIs, as we make them and stuff. There&#39;s no religiousness about it.</p> <p>Participant 3: You mentioned earlier that you were onboarding tech debt with your code, one year later, what happened to that?</p> <p>Malkani: We&#39;re paying down that debt. Reusing the code base meant that you&#39;re reusing it with all its edge case handling and all its warts. Sometimes it&#39;s difficult to know which context you&#39;re operating in. Are you serving an Instagram function or are you serving a Threads function? We have a big project underway to disentangle that. This is where being opportunistic was important. That opportunity was only going to last for that time. I think Ranbir mentioned like, everything in architecture is a tradeoff. Here the right tradeoff definitely was to take on that tech debt and enable launching the product sooner. Now we have this like changing the engine of the plane while it&#39;s in flight sort of project, to rewrite it and tease things apart and stuff, but we&#39;re doing it.</p> <p>Participant 4: If I understood you correctly, you said you started out by forking the Instagram code. Are you planning on reunifying that or do you want to split it further apart?</p> <p>Malkani: It&#39;s drifting apart over time. It was a convenient starting point. With us embedding more deeply with this interoperable like ActivityPub support and things, and just leaning into more of the uniqueness of what makes Threads, Threads, and what makes Instagram, Instagram, they&#39;re drifting apart over time and we have to tease that apart.</p> <p>Participant 5: You mentioned reusing the backend of Instagram. How does it say the data model and the APIs look for Threads versus Instagram? Are you reusing the same data model with some fields, or a new API for each operation?</p> <p>Malkani: They&#39;re similar, but we&#39;re starting to tease them apart. Instagram had a custom REST API, which is how the clients and servers spoke to each other. We started by reusing that, but we&#39;re moving towards adopting GraphQL more. GraphQL is used by Facebook extensively. With GraphQL, you get to do a lot more granular specification of what data the client needs, and also like how you define that on the server.</p> <p>Moving to that more field-oriented model, and it&#39;s this whole inverting the data model idea. Instead of business logic living on the server, for compositing data together, the client just requests specific pieces of data. We can label those things as being either Threads only or Instagram only, and tease it apart that way. We started with Instagram, and now we&#39;re teasing it apart.</p> <p>Participant 6: One of the differentiators you mentioned was that you could iterate quickly on the UI from the mobile applications. At Uber we specify a generic card format, that the backend then was returning with text first then for the other stuff. Is there something similar in place here?</p> <p>Malkani: It was a little more product specific than that. We have frameworks to do that very generic stuff. Like, specify a shadow DOM, and that&#39;s your API. There&#39;s server-side rendering stuff. That was not what we were doing over here. This is more like product specific. This is the post you should put here, but stuff that usually you would do on the client, whether it&#39;s figuring out what reply CTA to use, how to render the line. Like, is there a loop here, or stuff like that? It was like a custom data model, but it did let us iterate. We had variations on how we ran the self Threads, where you reply to yourself in a chain.</p> <p>How do we show that? We tried a number of ideas, and we were able to do this with our dogfooding community of a few thousand people, on the fly, quickly, thanks to this. No, we were not doing a generic server-side rendering thing. We do use that in other places for some of the onboarding things, or like the fediverse onboarding uses that sort of a server driven rendering thing, but that&#39;s not what this was.</p> <p>Participant 7: If you have to do it again, what would you do differently?</p> <p>Malkani: This reusing to move quicker was what saved our bacon. I would do that. I would take a few architectural decisions differently where like, specific data models that we reused, I would choose to spend a little time detangling them. Maybe it would push us back a month or something, but it would have been worth it because untangling it now is very complicated. No, the overall ethos of like, reuse what you can, yes, I wouldn&#39;t change that.</p> <p>Participant 8: Coming back on the question relating to technical debt, how are you unfolding that? How do you address that thing on a day-to-day basis? What does that look in the team planning and backlog?</p> <p>Malkani: We have pretty mature frameworks for doing data migrations on this scale, because we&#39;ve had to split things out before in Meta. When you think of like splitting Messenger from Facebook, or splitting Marketplace out from Facebook. There are a couple of examples of this. We have frameworks, for instance, that tail all mutations that happen, so that UDB that I talked about, that&#39;s our main datastore in MySQL. There are systems that tail those bin logs and let you do things with that, so they&#39;re observers. I&#39;m sure there are open source equivalents of this, like tailing a Kafka. You can write an observer that tails that and says, ok, double write this, and so now we have two versions of this particular data model, say, the user model, that we need to keep up to date.</p> <p>Then we start migrating the product logic over to start reading from both of those places. Depending on whether it&#39;s an Instagram context, or a Threads context, you now start reading from the new data model. Then you start doing the double reading and comparing consistency and stuff. There&#39;s a number of techniques like that. Part of the problem is, it&#39;s quite a deep data model. When you think about the post itself, the post itself can have a lot of things linked to it, and all of those things recursively need to now either be Threads data, or Instagram data. We need to go in deep and do those annotations and stuff, some of which can be done statically, some of which need to be done dynamically at runtime, because it depends on who created it. It&#39;s complicated, but still the right tradeoff.</p> <p>Participant 9: When reusing the code, you&#39;re also potentially reusing the technical debt which was originally in that code, and then you&#39;re ending up with multiple places using the same mistakes or problems. How do you see that?</p> <p>Malkani: It&#39;s part of the tech debt you take on. Again, it was a tradeoff. We could either take on that tech debt and build a product in six months, or we could start from scratch and probably take a year or something to have a fully-fledged product. We knew that we needed to take advantage of this window. Yes, we were ok with taking that on and paying for it later. You&#39;re taking out a loan, and you&#39;re saying, I&#39;m going to pay interest later.</p> <p>Participant 10: When you say that you first inherited the code from Instagram, and now you are decoupling this code, so in terms of coding and backlog and storage that are being done by the developers, do you have a certain allocation for this decoupling? For example, a certain team is working on removing the unneeded parts and just keeping what is needed in terms of code, so that in the future the code is more maintainable and easier to read and everything that is needed is there without extra stuff?</p> <p>Malkani: Absolutely. We have to balance needs now. On the one hand, we need to evolve the product because we haven&#39;t found product market fit at all. We&#39;re a brand-new product. On the other hand, we need to make this code base more maintainable and pay down some of the tech debt and remove footguns, remove things that can catch developers unaware and lead to big outages. We need to balance that. Right now, we&#39;re balancing that by having a separate team focus on this particular migration. At some point, it impacts all product developers and you can&#39;t get away from that. That will temporarily slow down progress in building the product. We know that we&#39;re going to have to pay that at some point. It&#39;s a tricky thing of how to organizationally set this up. So far, it&#39;s been with a separate team.</p> <p>Participant 11: Are there any development decisions you&#39;ve made in the development of Threads that have then influenced things that have gone back into the code bases and applications at Meta?</p> <p>Malkani: I hope the ActivityPub stuff makes it at some point. That has not happened yet. I think that has a lot of promise. Or generally interoperating with other networks. Certainly, the lean nature of this has been lauded within Meta. The fact that we were able to do this with a small team. Meta has a playbook of building large teams around important goals. This was a counterpoint example. That organizational lesson has definitely been taken to heart. I think on the technical side, there&#39;s a lot of interesting stuff we&#39;re doing with ranking, that&#39;s new to Meta.</p> <p>Other networks, with their ranking, the most important thing they&#39;re predicting, obviously with checks and balances, is how engaging is this post going to be? I&#39;m going to go look back and find the most interesting post and then sequence it by the next most interesting post. That&#39;s how you build up your feed. With Threads, you need to pay attention to the real-time nature of this product to a much greater degree.</p> <p>Some of the luxury and slack you have in your ranking stack, from the time a post is made to the time it&#39;s eligible for ranking and the time it starts actively getting picked up, that latency window can be much bigger for something like Instagram than it needs to be. For Threads, like from the moment you post, it needs to be eligible near real time, because this is how news breaks. If there&#39;s an earthquake, you want to know right now. If there&#39;s a helicopter flying overhead, you want to know why. That novelty in the ranking stack is something we&#39;ve had to push on. It&#39;s something Twitter does very well, for instance.</p> <p>On the subject of technical debt, are we working with the Instagram teams that we inherited this from and potentially have a similar solution to?</p> <p>Organizationally, Threads and Instagram team is still a subsidiary. We do work with those teams. In many cases, it was not like a straight fork as much as we&#39;re reusing the same code. If we had a shared solution, it improves in both places. Meta has this system called better engineering, it&#39;s almost like a 20% time thing, which is similar to what Google used to have, where we incentivize people to work on tech debt type problems in their spare time. We&#39;re falling in into that. We&#39;re working with these teams. The main short-term focus now is making the data models clear between these apps.</p> <p>Participant 12: Thinking about the products of Meta, was there a specific reason to use the Instagram architecture rather than Facebook&#39;s, maybe something else?</p> <p>Malkani: I think it started from the fact that Instagram is a directed follow graph, as opposed to Facebook, which is bidirectional friends. That one decision has a lot of technical implications. We probably could have started from somewhere else, but I think that, plus the fact that there&#39;s a bit of Conway&#39;s Law. The team who was building this was familiar with the Instagram tech stack, and so it made sense to repurpose that. Our options were Facebook and Instagram, and Instagram seemed like a better fit.</p> <p>Participant 13: How many people were involved initially in the project, boiled down to how many teams? How did you structure that based on the fact that you were just starting on a huge code base?</p> <p>Malkani: It was small. It started out with 10-ish engineers, snowballed into maybe 50-ish by the end. The fact that we could lean on these platform teams made a lot of difference. In the end, maybe 100 engineers or so, touched something that made it into the Threads app. We kept it small deliberately. A, we wanted to stay a nimble team, and we wanted to pivot the product itself that we were making. We wanted to keep the product simple. B, we were certainly worried about leak risks and stuff.</p> <p>Participant 14: You said you did some ranking stuff. I&#39;m curious if you had issues with bots, and if you&#39;re taking steps in the security area?</p> <p>Malkani: Yes, bots are a problem. Again, very lucky that we can rely on a long history of teams fighting bots on Instagram and Facebook as well. They do show up in unique ways on Threads. We have had problems where it&#39;s gotten out to users. Sometimes you get spammy replies and stuff like that, which we&#39;re fighting hard. Integrity is very much like a firefighting domain. These are adversaries who continually evolve their patterns. You learn one pattern, you put in a mitigation against it, and then they shift to a different abuse pattern. It&#39;s taxing, but it is something that we know how to do and we have teams who do this well.</p> <p>Among the more interesting novel challenges we have here is, Threads to a much greater degree than Instagram or Facebook, is about linking out to the web. Facebook and Instagram can be more internally referenced, but not as much outbound links. We have a number of challenges there we have to figure out about awareness of what&#39;s going on in the web, redirects and link crawlers, and that fun stuff. Yes, it&#39;s hard.</p> <p>&nbsp;</p> <script> $(function() { jQuery(function() { jQuery.scrollDepth(); }); }); </script> <p><big><strong>See more <a href="https://www.infoq.com/transcripts/presentations/">presentations with transcripts</a></strong></big></p> <p>&nbsp;</p> </div> </div> </div> <div class="aside"> <div class="recorded"> <p class="meta recorded__meta">Recorded at:</p> <a href="https://qconlondon.com"> <img loading="lazy" alt="" src="https://res.infoq.com/presentations/threads-meta/en/promoimage/logo-ln-small-1728560783548.jpg"> </a> </div> <p class="date">Oct 10, 2024</p> <div class="article__authors authors"> <div> <p class="meta">by</p> <ul class="no-style authors"> <li data-id="author-Zahan-Malkani"> <p class="meta author__bio"> <a href="/profile/Zahan-Malkani/" class="avatar author__avatar" aria-label="Zahan Malkani"></a> <span class="author__name"> <a href="/profile/Zahan-Malkani/" class="author__link">Zahan Malkani</a> </span> </p> </li> </ul> </div> </div> <div class="ads__area"> <script type="text/javascript"> var uriMapping = "presentations"; var showVcr = "false"; var fillWithVcr = "true"; var sponsorshipsJson = "{&quot;links&quot;:[{&quot;styleName&quot;:&quot;pdf&quot;,&quot;style&quot;:&quot;PDF&quot;,&quot;text&quot;:&quot;9 Principles for Improving Cloud Resilience - Download Free Report (By Gartner)&quot;,&quot;id&quot;:&quot;1f39a4cc-fbe5-4394-9476-b700e6a80909&quot;,&quot;target&quot;:&quot;https://www.infoq.com/vendorcontent/show.action?vcr=c394113e-92a5-4785-a3db-326a4ca4684b&amp;utm_source=infoq&amp;utm_medium=RSC&amp;utm_campaign=vcr_fixed_link&quot;,&quot;active&quot;:true}]}"; var sponsoredLinks = $.parseJSON($("<div/>").html(sponsorshipsJson).text()).links; var numberOfSponsoredVcrIds = sponsoredLinks != null ? sponsoredLinks.length : 0; var maxItems = 5 - numberOfSponsoredVcrIds; var intervalVcrSponsorship = setInterval(function() { if (window.vcrsLoaded) { clearInterval(intervalVcrSponsorship); if(showVcr || fillWithVcr) { if(fillWithVcr) { for(var index in window.vcrList) { if(VCR.isVcrSponsored(sponsoredLinks, window.vcrList[index])) { VCR.addToExcludedList(window.vcrList[index]); } } } var vcrs = VCR.getByTopicsAndCommunities(window.vcrList, topicIds, communityIds, maxItems, false, null); if (vcrs != null && vcrs.length > 0 || (sponsoredLinks != null && sponsoredLinks.length > 0)) { VCR.addToExcludedList(vcrs); var $widget = jQuery('.relatedVendor'); getCommonElementsForPresentationsWithTranscripts(vcrs, uriMapping, "RIGHT_BAR_RVC"); $widget.css("display", "block"); } else { var $widget = jQuery('.relatedVendor'); $widget.removeClass("f_rvcbox"); } } window.contentVcrFinished = true; // search for infoq.event.on("contentVcrFinished",... to see how/where it is used infoq.event.trigger("contentVcrFinished"); } }, 200); </script> <input type="hidden" name="" value="2498" id="cont_item_primary_topic"/> <div class="widget relatedVendor" style="display: block" > <h4 class="widget__heading">Related Sponsored Content</h4> <ul data-tax="prsp" data-horizontal="true" data-size="small" class="prsp__items no-style cards showImageFirst"> <div class="f_rvcList"></div> <li class="book"> <div class="book__info"> <h4 class="book__title"> <a href="/url/f/1f39a4cc-fbe5-4394-9476-b700e6a80909/" rel="nofollow"> 9 Principles for Improving Cloud Resilience - Download Free Report (By Gartner) </a> </h4> </div> </li> </ul> <ul class="related-prsp" jsh="{&quot;topic&quot;:&quot;Architecture &amp; Design&quot;,&quot;id&quot;:&quot;999b3bed-b010-4184-aa98-7cb5ba75aae2&quot;,&quot;title&quot;:&quot;Akka TS Core 01/01/2025 - 06/30/2025&quot;}"> <h4 class="widget__heading">Related Sponsor</h4> <a href="/url/f/2e430140-3e64-4fdd-ac3a-289efe39aef4/" target="_blank" rel="nofollow"> <img loading="lazy" src="https://imgopt.infoq.com//fit-in/250x380/filters:quality(100)/filters:no_upscale()/sponsorship/topic/999b3bed-b010-4184-aa98-7cb5ba75aae2/AkkaLogoRSB2-1734601591399.png"/> </a> <p style="clear: both; padding: 10px 0 0 0;"><b>Build and run apps that react to change.</b> Responsive by design, Akka apps are elastic, agile, and resilient. <b><a href="/url/f/e0c0f27d-3857-4002-bcb6-d7ea65263534/" target="_blank" rel="nofollow">Learn more</a>.</b></p> </ul> </div> <script type="text/javascript"> window.finishedRightbarVcr = false; var whitepaperVcrsJson = null; var topicSponsorshipJson = "{&quot;iconLink&quot;:&quot;/url/f/2e430140-3e64-4fdd-ac3a-289efe39aef4/&quot;,&quot;iconHref&quot;:&quot;https://imgopt.infoq.com//fit-in/275x500/filters:quality(100)/filters:no_upscale()/sponsorship/topic/999b3bed-b010-4184-aa98-7cb5ba75aae2/AkkaLogoRSB2-1734601591399.png&quot;,&quot;id&quot;:&quot;97696208-a16a-402d-9dc7-a5fa39c8cd56&quot;}"; var vcrOptionalListJson = null; /* do not delete these two, as they are used further in the code */ var contentDatetimeFormat='MMM dd, yyyy'; var contentUriMapping="presentations"; JSi18n.relatedRightbar_relatedContent='Related Content'; JSi18n.relatedRightbar_sponsoredContent='Related Sponsored Content'; JSi18n.relatedRightbar_sponsoredBy='Sponsored by'; var topicIds = "922,7029,137,6218,593,2210,2843,131"; var communityIds = "2498"; var company = "Akka"; // this event is fired by frontend once all the necessary things have been done(mobile display, moving vcr boxes around when needed...) var canStartTrackingCustomRightbar = false; infoq.event.on('loaded', function(e) { canStartTrackingCustomRightbar = true; }); var intervalRightbar = setInterval(function() { if (window.vcrsLoaded) { clearInterval(intervalRightbar); if(company != null && company != "") { whitepaperVcrsJson = VCR.filterByCompany(company, window.vcrList); } vcrOptionalListJson = VCR.getByTopicsAndCommunities(window.vcrList, topicIds, communityIds, 20, true, null); var adsArea = $('.ads__area'); // 1. display whitepaperVcrs var topicSponsorship = $.parseJSON($("<div/>").html(topicSponsorshipJson).text()); var whitepaperVcrItems = $.parseJSON($("<div/>").html(JSON.stringify(whitepaperVcrsJson)).text()); var index = 0; var hasWhitepaper = whitepaperVcrItems !== null && whitepaperVcrItems.length > 0; if (hasWhitepaper) { index++; var whitepaperDiv = getRightbarCustomVcrWidget(whitepaperVcrItems, index, topicSponsorship, "transcriptsright", 1); $(whitepaperDiv).addClass('prspContent_side'); $(whitepaperDiv).removeClass('box'); $(whitepaperDiv).find('a.book__image img').addClass("book__cover"); adsArea.append(whitepaperDiv); } // 2. repeat the "VCR OPTIONAL box as many times as possible, but not more than 5 times" var items = $.parseJSON($("<div/>").html(JSON.stringify(vcrOptionalListJson)).text()); var minimumBoxHeight = 2000; var availableSpace = $('.aside').height() - $('.relatedVendor').height(); var numberOfBoxes = Math.floor(availableSpace / minimumBoxHeight); if (numberOfBoxes > 5) { numberOfBoxes = 5; } for (var i = 0; i<numberOfBoxes; i++) { index++; var relatedVcrDiv = getRightbarCustomVcrWidget(items, index, null, "transcriptsright", 1); $(relatedVcrDiv).addClass('prspContent_side'); $(relatedVcrDiv).removeClass('box'); $(relatedVcrDiv).find('a.book__image img').addClass("book__cover"); adsArea.append(relatedVcrDiv); } window.finishedRightbarVcr = true; } }, 200); // these two events can happen one before another async(no precedence any can be first or second). Make sure tracking starts when both happened var intervalTrackingRightbar = setInterval(function() { if(canStartTrackingCustomRightbar && window.finishedRightbarVcr){ clearInterval(intervalTrackingRightbar); VCR.doTrackingCustomRightbarForPresentations(); } }, 200); </script> </div> </div> <div class="widget article__fromTopic topics"> <div class="widget__head related__for-topic" data-id="597" data-trk-ref="content_primary_topic"> <h4 class="heading related__heading"> This content is in the <a href='/qcon/'>QCon Software Development Conference</a> topic </h4> </div> <h5 class="heading related__inline">Related Topics:</h5> <ul class="no-style topics related__topics topics__small" data-trk-ref="content_related_topic"> <li data-id="6816"> <a href="/architecture-design/" class="button related__topic button__small button__black">Architecture &amp; Design</a> </li> <li data-id="3535"> <a href="/Facebook/" class="button related__topic button__small button__black">Facebook</a> </li> <li data-id="18549"> <a href="/qcon-london-2024/" class="button related__topic button__small button__black">QCon London 2024</a> </li> <li data-id="140"> <a href="/socialNetworking/" class="button related__topic button__small button__black">Social Networking</a> </li> <li data-id="17662"> <a href="/transcripts/" class="button related__topic button__small button__black">Transcripts</a> </li> <li data-id="597"> <a href="/qcon/" class="button related__topic button__small button__black">QCon Software Development Conference</a> </li> <li data-id="6428"> <a href="/thread/" class="button related__topic button__small button__black">Thread</a> </li> <li data-id="7313"> <a href="/Case_Study/" class="button related__topic button__small button__black">Case Study</a> </li> <li data-id="134"> <a href="/InfoQ/" class="button related__topic button__small button__black">InfoQ</a> </li> </ul> </div> <input type="hidden" name="" value="2498" id="cont_item_primary_topic"/> <script type="text/javascript"> $(document).ready(function() { $.ajax({ url: "/api/recommendationlinks.action", contentType: "application/x-www-form-urlencoded; charset=utf-8", type: 'POST', data: { "primaryTopicAlias": "architecture-design", "topicIds": "2843,922,7029,6218,2210", "title": "0 → 1, Shipping Threads in 5 Months", "contentPath": "/presentations/threads-meta", "language": "en" }, success: displayRelatedEditorial, async: false }); }); function displayRelatedEditorial(data) { $('.related__editorial h4').text("Related Editorial"); if (data && data.length > 0) { if(data[0].fromEs) { //change title and tracking params var box_title="Architecture &amp; Design"; //replace html entity since it conflicts with style box_title=box_title.replace("&amp;","&"); $('.related__editorial h4').text("Popular in " + box_title); } for (var i = 0; i < data.length; i++) { if (i === 5) { break; } if (data[i].url.indexOf("/presentations/threads-meta") !== -1) { console.log("Removing the current item from list..."); continue; } var theLinkURL = data[i].url; if(!theLinkURL.endsWith("/")) { theLinkURL = theLinkURL + "/"; } var link = $('<li><h5 class="rvc__title"><a title="" href="' + theLinkURL + '/">' + data[i].title + '</a></h5></li>'); $('.related__editorial ul').append(link); } $('.related__editorial').show(); displayWidget = true; }else{ $('.related__editorial').parent("li").remove(); } if(displayWidget==true){ $('.related__group').attr("data-cols", $('.related__group').find(">li").length); $('.related__group').css("display", "flex"); } } </script> <ul class="no-style related__group nocontent cards"> <li> <div class="related__editorial"> <h4 class="heading">Related Editorial</h4> <ul></ul> </div> </li> <li class="bg-gray"> <div class="related__prsp"> <h4 class="heading">Popular across InfoQ</h4> <ul> <li> <h5 class="rvc__title"> <a href="/news/2025/02/microsoft-majorana-quantum-chip/" class="rvc__link"> Microsoft Unveils the First Topological Quantum Chip Majorana 1 </a> </h5> </li> <li> <h5 class="rvc__title"> <a href="/news/2025/02/docker-bake-ga/" class="rvc__link"> Farewell to Build Scripts as Docker Bake Goes GA </a> </h5> </li> <li> <h5 class="rvc__title"> <a href="/news/2025/02/kube-resource-orchestrator/" class="rvc__link"> Cloud Giants Collaborate on New Kubernetes Resource Management Tool </a> </h5> </li> <li> <h5 class="rvc__title"> <a href="/podcasts/facilitating-software-architecture/" class="rvc__link"> Facilitating Software Architecture with Andrew Harmel-Law </a> </h5> </li> <li> <h5 class="rvc__title"> <a href="/news/2025/02/monzo-stand-in/" class="rvc__link"> How Monzo Bank Built a Cost-Effective, Unorthodox Backup System to Ensure Resilient Banking </a> </h5> </li> <li> <h5 class="rvc__title"> <a href="/news/2025/02/valkey-glide-az-affinity-routing/" class="rvc__link"> AWS Reduces Latency and Costs for Key/Value Datastores with AZ Affinity Routing and GLIDE Valkey </a> </h5> </li> </ul> </div> </li> </ul> </article> </div> </section> </div> <div id="imgPreload"></div> <script type="text/javascript"> // global vars that can be used for this page, use this section to add more. var contentTitle = "0 → 1, Shipping Threads in 5 Months", contentPath = "/presentations/threads-meta", contentUUID = "a42ab4bc-73ac-4f44-a620-f3b041d27e8f", authorUserCSVIds = "126658110"; </script> <script type="text/javascript"> // needed for starting download after IDP login, processing starts after frontend modules are loaded infoq.event.on("loaded", function(){ if(loggedIn){ var href = window.location.href; if(href.indexOf("#downloadPdf") != -1){ //window.location.href = href.substring(0, href.indexOf('#')); $('#slides').click(); } else if(href.indexOf("#downloadPresentationMp3") != -1){ //window.location.href = href.substring(0, href.indexOf('#')); $('#mp3').click(); } } }); P.c(false, 'p', isWideScreen, 'https://cdn.infoq.com/statics_s2_20250228123450/styles/static/images/logo/logo_scrubber_16_9.jpg', 'https://cdn.infoq.com/statics_s2_20250228123450/styles/static/images/logo/logo_scrubber_4_3.jpg'); //wait for the player to be ready document.getElementById("video").addEventListener('loadeddata', function() { //check if we are requested to jump to a specific time in the video var t = CommonUtils.getQueryParameterByName("t"); if(t !== null && t.length <= 9) { SlideSynchronizer.start(); P.seekPlayerTime(t, true); } }, false); </script> </main> <footer class="footer "> <section data-nosnippet class="section container"> <div class="container__inner"> <ul data-cols="5" class="no-style columns boxes topic__boxes"> <li class="development"> <div class="box__header"> <a class="t_all_footer_more-boxes-header" href="/development/">Development</a> </div> <div class="box__content"> <ul class="no-style box__list small"> <li> <h5><a class="t_all_footer_more-boxes-item" href="/presentations/zero-trust-devsecops/" title="A Zero Trust Future for Applications: Practical Implementation and Pitfalls">A Zero Trust Future for Applications: Practical Implementation and Pitfalls</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/02/go-1-24-generic-aliases/" title="Go 1.24 Brings Generic Type Aliases, Weak Pointers, Improved Finalizers, and More">Go 1.24 Brings Generic Type Aliases, Weak Pointers, Improved Finalizers, and More</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/02/apple-cpu-side-channel-slap-flop/" title="Recent Generations of Apple CPUs Affected by New Side-Channel Vulnerabilities">Recent Generations of Apple CPUs Affected by New Side-Channel Vulnerabilities</a></h5> </li> </ul> </div> </li> <li class="architecture-design"> <div class="box__header"> <a class="t_all_footer_more-boxes-header" href="/architecture-design/">Architecture &amp; Design</a> </div> <div class="box__content"> <ul class="no-style box__list small"> <li> <h5><a class="t_all_footer_more-boxes-item" href="/articles/architectural-experimentation-insurance/" title="If Architectural Experimentation Is So Great, Why Aren&amp;rsquo;t You Doing It?">If Architectural Experimentation Is So Great, Why Aren&rsquo;t You Doing It?</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/02/monzo-stand-in/" title="How Monzo Bank Built a Cost-Effective, Unorthodox Backup System to Ensure Resilient Banking">How Monzo Bank Built a Cost-Effective, Unorthodox Backup System to Ensure Resilient Banking</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/podcasts/facilitating-software-architecture/" title="Facilitating Software Architecture with Andrew Harmel-Law">Facilitating Software Architecture with Andrew Harmel-Law</a></h5> </li> </ul> </div> </li> <li class="culture-methods"> <div class="box__header"> <a class="t_all_footer_more-boxes-header" href="/culture-methods/">Culture &amp; Methods</a> </div> <div class="box__content"> <ul class="no-style box__list small"> <li> <h5><a class="t_all_footer_more-boxes-item" href="/podcasts/resilience-observability-automation/" title="Resilience, Observability and Unintended Consequences of Automation">Resilience, Observability and Unintended Consequences of Automation</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/02/security-software-development/" title="Ensuring Security without Harming Software Development Productivity">Ensuring Security without Harming Software Development Productivity</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/presentations/navigators/" title="Navigators: Decentralizing Decisions and Empowering ICs at Carta">Navigators: Decentralizing Decisions and Empowering ICs at Carta</a></h5> </li> </ul> </div> </li> <li class="ai-ml-data-eng"> <div class="box__header"> <a class="t_all_footer_more-boxes-header" href="/ai-ml-data-eng/">AI, ML &amp; Data Engineering</a> </div> <div class="box__content"> <ul class="no-style box__list small"> <li> <h5><a class="t_all_footer_more-boxes-item" href="/articles/secure-ai-powered-early-detection-system/" title="Secure AI-Powered Early Detection System for Medical Data Analysis &amp;amp; Diagnosis">Secure AI-Powered Early Detection System for Medical Data Analysis &amp; Diagnosis</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/03/ibm-granite-3-2/" title="IBM Granite 3.2 Brings New Vision Language Model, Chain of Thought Reasoning, Improved TimeSeries">IBM Granite 3.2 Brings New Vision Language Model, Chain of Thought Reasoning, Improved TimeSeries</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/02/microsoft-bioemu-1/" title="Microsoft Releases BioEmu-1: a Deep Learning Model for Protein Structure Prediction">Microsoft Releases BioEmu-1: a Deep Learning Model for Protein Structure Prediction</a></h5> </li> </ul> </div> </li> <li class="devops"> <div class="box__header"> <a class="t_all_footer_more-boxes-header" href="/devops/">DevOps</a> </div> <div class="box__content"> <ul class="no-style box__list small"> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/03/aws-cdk-garbage-collection/" title="AWS CDK Introduces Garbage Collection to Remove Outdated Assets">AWS CDK Introduces Garbage Collection to Remove Outdated Assets</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/03/flux-gitops-release/" title="Flux v2.5 Release: Expanding GitOps Capabilities with CEL Integration and GitHub App Auth">Flux v2.5 Release: Expanding GitOps Capabilities with CEL Integration and GitHub App Auth</a></h5> </li> <li> <h5><a class="t_all_footer_more-boxes-item" href="/news/2025/03/meta-suports-data-logs/" title="Meta Enhances Download Your Information Tool with Data Logs">Meta Enhances Download Your Information Tool with Data Logs</a></h5> </li> </ul> </div> </li> </ul> </div> </section> <section data-nosnippet class="container section section__newsletter"> <div class="columns container__inner"> <div class="newsletter" data-col="1/2" id="infoq-nl" > <h2 class="heading"> <strong>The InfoQ</strong> Newsletter </h2> <p class="intro">A round-up of last week&#x2019;s content on InfoQ sent out every Tuesday. Join a community of over 250,000 senior developers. <a target="_blank" href="https://assets.infoq.com/newsletter/regular/en/newsletter_sample/newsletter_sample.html">View an example</a> </p> <ul class="newsletter__features"> <li>Get a quick overview of content published on a variety of innovator and early adopter technologies</li> <li>Learn what you don&#x2019;t know that you don&#x2019;t know</li> <li>Stay up to date with the latest information from the topics you are interested in</li> </ul> <div class="newsletter__subscribe"> <form class="form gdpr" name="footerNewsletterForm" id="footerNewsletterForm" action="#" onsubmit="footerNewsletter.saveSubscription(); return false;"> <div class="field newsletter__mail input__text input__no-label input__medium email"> <label for="email-newsletter-infoq" class="label field__label">Enter your e-mail address</label> <input id="email-newsletter-infoq" name="footerNewsletterEmail" placeholder="Enter your e-mail address" class="input field__input" type="email"/> <input type="text" name="emailH" id="input_email_h" aria-required="false" style="display:none !important" tabindex="-1" autocomplete="off"/> <input type="hidden" id="fnt" name="fnt" value="FaHUbNSfqo0L4vv3"/> <input type="hidden" id="footerNewsletterType" name="footerNewsletterType" value="regular"/> <input type="hidden" id="cmpi" name="cmpi" value="1"/> </div> <div class="hidden"> <span class="input__select field country"> <label for="input-simple-newsletter-country" class="label field__label">Select your country</label> <select id="input-simple-newsletter-country" class="select field__input"> <option value="" class="select__option">Select a country</option> </select> <p class="input__message field__desc"></p> </span> <span class="input__checkbox field hidden"> <input type="checkbox" id="gdpr-consent-simple-nl"> <label for="gdpr-consent-simple-nl" class="label"><span>I consent to InfoQ.com handling my data as explained in this <a href="https://www.infoq.com/privacy-notice">Privacy Notice</a>.</span></label> </span> </div> <input type="submit" role="button" value="Subscribe" class="button button__medium button__red" onclick="return footerNewsletter.validateEmail('Invalid email address');"/> </form> <p class="meta"> <a href="/privacy-notice/" target="_blank">We protect your privacy.</a> </p> <span class="success" style="display:none;" id="footerNewsletterMessage"></span> </div> <script type="text/javascript"> var footerNewsletter = new Newsletter('Enter your e-mail address', 'email-newsletter-infoq', 'footerNewsletterType','footerNewsletterMessage', 'fnt', 'input_email_h', 'input-simple-newsletter-country', 'cmpi','footer_except_homepage'); </script> </div> <div data-col="1/2" data-bg="qconLondon" class="event__container"> <a href="https://qconlondon.com/?utm_source=infoq&utm_medium=referral&utm_campaign=largefooterad_qlondon25" target="_blank" class="qconplus__events-slider"> <div> <div class="logo-london"></div> <br> </div> <p class="intro"><ul><li><strong>Conference: April 7-9, 2025</strong></li><li><strong>Certification workshop: April 10, 2025</strong></li></ul> QCon London International Software Development Conference returns on April 7-10, 2025. Level-up on 15 major software and leadership topics including; The Tech of FinTech, AI & ML in Software Engineering, Modern Data Architectures, Engineering Productivity, The Path to Senior Engineering Leadership, Supply Chain Security, and more.</p> <p class="intro">Learn the emerging trends. Explore the use cases. Implement the best practices.<br><strong class="button button__green cta__button">Register Now</strong></p> </a> </div> </div> </section> <section data-nosnippet class="section container footer__subfooter align__left"> <div class="container__inner columns"> <div data-col="1/4" class="columns footer__links-wrap"> <div class="footer__links"> <a href="/" class="nuxt-link-exact-active active" title="Home">Home</a> <a href="/reginit.action" class="emphasis" title="Create account">Create account</a> <button aria-label="Login" class="login" data-ref="mainLogin">Login</button> <a rel="noreferrer noopener" href="http://qconferences.com/" target="_blank" title="QCon Conferences">QCon Conferences</a> <a rel="noreferrer noopener" href="https://events.infoq.com/" target="_blank">Events</a> <a href="/write-for-infoq/" title="Write for InfoQ">Write for InfoQ</a> <a href="/infoq-editors/" title="InfoQ Editors">InfoQ Editors</a> <a href="/about-infoq/" title="About InfoQ">About InfoQ</a> <a href="/about-c4media/" title="About C4Media">About C4Media</a> <a rel="noreferrer noopener" href="https://get.infoq.com/infoq-mediakit/" title="Media Kit" target="_blank"> Media Kit </a> <a href="https://devmarketing.c4media.com/?utm_source=infoq" title="InfoQ Developer Marketing Blog" target="_blank">InfoQ Developer Marketing Blog</a> <a rel="noreferrer noopener" href="https://c4media.com/diversity" title="Diversity" target="_blank">Diversity</a> </div> </div> <div data-col="1/4" class="events__list"> <h4 class="heading footer__heading">Events</h4> <ul class="qcons__list no-style"> <li><span class="icon event__type conference"></span> <div class="qcon__detail"> <h5 class="heading"> <a rel="noreferrer noopener" href="https://qconlondon.com/?utm_source=infoq&utm_medium=referral&utm_campaign=footer_qlondon25" target="_blank">QCon London</a> </h5> <span class="meta date">APRIL 7-10, 2025</span> </div> </li> <li><span class="icon event__type conference"></span> <div class="qcon__detail"> <h5 class="heading"> <a rel="noreferrer noopener" href="https://devsummit.infoq.com/conference/boston2025?utm_source=infoq&utm_medium=referral&utm_campaign=footer_idsboston25" target="_blank">InfoQ Dev Summit Boston</a> </h5> <span class="meta date">June 9-10, 2025</span> </div> </li> <li><span class="icon event__type conference"></span> <div class="qcon__detail"> <h5 class="heading"> <a rel="noreferrer noopener" href="https://devsummit.infoq.com/conference/munich2025?utm_source=infoq&utm_medium=referral&utm_campaign=footer_idsmunich25" target="_blank">InfoQ Dev Summit Munich</a> </h5> <span class="meta date">October 15-16, 2025</span> </div> </li> <li><span class="icon event__type conference"></span> <div class="qcon__detail"> <h5 class="heading"> <a rel="noreferrer noopener" href="https://qconsf.com/?utm_source=infoq&utm_medium=referral&utm_campaign=footer_qsf25" target="_blank">QCon San Francisco</a> </h5> <span class="meta date">November 17-21, 2025 / In-person</span> </div> </li> <li><span class="icon event__type conference"></span> <div class="qcon__detail"> <h5 class="heading"> <a rel="noreferrer noopener" href="#" target="_self" onclick="return false;">InfoQ Dev Summit New York</a> </h5> <span class="meta date">December, 2025 / In-person</span> </div> </li> </ul> </div> <div data-col="1/4" class="footer__social-wrap"> <h4 class="heading text-left footer__heading">Follow us on </h4> <div class="social__links columns social__links__row"> <a href="https://www.youtube.com/infoq"><span class="icon icon__large icon__social icon__youtube"></span><div><span class="social__count">Youtube</span><span class="social__followers">223K Followers</span></div></a> <a href="http://www.linkedin.com/company/infoq"><span class="icon icon__large icon__social icon__linkedin"></span><div><span class="social__count">Linkedin</span><span class="social__followers">21K Followers</span></div></a> <a href="#" id="footerNewsletterRssLink"><span class="icon icon__large icon__social icon__rss"></span><div><span class="social__count">RSS</span><span class="social__followers">19K Readers</span></div></a> <a rel="noreferrer noopener" href="http://twitter.com/infoq" target="_blank"><span class="icon icon__large icon__social icon__twitter"></span><div><span class="social__count">X</span><span class="social__followers">53.4k Followers</span></div></a> <a rel="noreferrer noopener" href="https://www.facebook.com/InfoQ-75911537320" target="_blank"><span class="icon icon__large icon__social icon__fb"></span><div><span class="social__count">Facebook</span><span class="social__followers">21K Likes</span></div></a> <a rel="noreferrer noopener" href="https://bsky.app/profile/infoq.com" target="_blank"><span class="icon icon__large icon__social icon__bluesky"></span><div><span class="social__count">Bluesky</span><span class="social__followers">New</span></div></a> <a rel="noreferrer noopener" href="https://www.amazon.com/dp/B07KMWGNNL" target="_blank"><span class="icon icon__large icon__social icon__alexa"></span><div><span class="social__count">Alexa</span><span class="social__followers">New</span></div></a> </div> </div> <div data-col="1/4" class="footer__stayin-wrap"> <h4 class="heading text-left footer__heading">Stay in the know</h4> <div class="stayIn_panel_container"> <a href="/podcasts/" class="stayIn_panel" target="_blank" rel="noreferrer noopener"><span>The InfoQ Podcast</span><picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLXBvZGNhc3QuanBnIiwiZWRpdHMiOiB7IndlYnAiOiB7ICJxdWFsaXR5Ijo4MH19fQ==" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLXBvZGNhc3QuanBnIiwiZWRpdHMiOiB7ImpwZWciOiB7ICJxdWFsaXR5Ijo4MH19fQ==" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLXBvZGNhc3QuanBnIiwiZWRpdHMiOiB7ImpwZWciOiB7ICJxdWFsaXR5Ijo4MH19fQ==" loading="lazy" width="65px" height="64px" alt="The InfoQ Podcast Logo - Stay in the know"></picture></a> <a href="/podcasts/#engineering_culture" class="stayIn_panel" target="_blank" rel="noreferrer noopener"><span>Engineering Culture Podcast</span><picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLXBvZGNhc3QtZW5naW5lZXJpbmctY3VsdHVyZS5qcGciLCJlZGl0cyI6IHsid2VicCI6IHsgInF1YWxpdHkiOjgwfX19" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLXBvZGNhc3QtZW5naW5lZXJpbmctY3VsdHVyZS5qcGciLCJlZGl0cyI6IHsianBlZyI6IHsgInF1YWxpdHkiOjgwfX19" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLXBvZGNhc3QtZW5naW5lZXJpbmctY3VsdHVyZS5qcGciLCJlZGl0cyI6IHsianBlZyI6IHsgInF1YWxpdHkiOjgwfX19" loading="lazy" width="65px" height="64px" alt="Engineering Culture Podcast Logo - Stay in the knoww"></picture></a> <a href="/software-architects-newsletter/" class="stayIn_panel" target="_blank" rel="noreferrer noopener"><span>The Software Architects' Newsletter</span><picture><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLWFyY2hpdGVjdC1uZXdzbGV0dGVyLmpwZyIsImVkaXRzIjogeyJ3ZWJwIjogeyAicXVhbGl0eSI6ODB9fX0=" type="image/webp"><source srcset="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLWFyY2hpdGVjdC1uZXdzbGV0dGVyLmpwZyIsImVkaXRzIjogeyJqcGVnIjogeyAicXVhbGl0eSI6ODB9fX0=" type="image/webp"><img src="https://imgopt.infoq.com/eyJidWNrZXQiOiAiYXNzZXRzLmluZm9xLmNvbSIsImtleSI6ICJ3ZWIvZm9vdGVyL2luZm9xLWFyY2hpdGVjdC1uZXdzbGV0dGVyLmpwZyIsImVkaXRzIjogeyJqcGVnIjogeyAicXVhbGl0eSI6ODB9fX0=" loading="lazy" width="65px" height="64px" alt="The Software Architects' Newsletter Logo - Stay in the know"></picture></a> </div> </div> </div> </section> <section data-nosnippet class="container footer__bottom section white align__left"> <div class="container__inner columns"> <div data-col="2/3" class="column"> <div class="footer__contact contact columns"> <span data-col="1/6"> General Feedback <a href="mailto:feedback@infoq.com">feedback@infoq.com</a> </span> <span data-col="1/6"> Advertising <a href="mailto:sales@infoq.com">sales@infoq.com</a> </span> <span data-col="1/6"> Editorial <a href="mailto:editors@infoq.com">editors@infoq.com</a> </span> <span data-col="1/6"> Marketing <a href="mailto:marketing@infoq.com">marketing@infoq.com</a> </span> </div> </div> <div class="column" data-col="1/3"> <p class="footer__more"> InfoQ.com and all content copyright &#169; 2006-2025 C4Media Inc.<br/> <a href="/privacy-notice" target="_blank">Privacy Notice</a>, <a href="/terms-and-conditions " target="_blank">Terms And Conditions</a>, <a href="/cookie-policy " target="_blank">Cookie Policy</a> </p> </div> </div> </section> </footer> <!-- ####### SITE END ######### --> </div> <div class="intbt"> <a href="/int/bt/" title="bt">BT</a> </div> <script type="text/javascript"> $.when(humanDetectionAsync()).then( function(status) { $.getScript("/scripts/__hd.ifq?hdt=FaHUbNSfqo0L4vv3&ha=" + status); } ); </script> <script type="text/javascript"> var pageFullyLoaded = false; // this event is fired by frontend once all the necessary things have been done(mobile display, moving vcr boxes around when needed...) infoq.event.on('loaded', function(e) { pageFullyLoaded = true; }); infoq.event.on('pageWidthChanged', function(e) { // re-execute tracking vcr impressions when this event happens (it only happens when elements are added/removed from page) // doTrackVcrImpressions takes into account the data-trk-impr="true" if =false the element was already tracked. // this is needed when switching from mobile to desktop or when layout on mobile changes and desktop version is displayed. New elements become visible. Tracker.safeExec(Tracker.doTrackVcrImpressions); // these 2 need to be called also because we might be on a content page. In case we are not nothing happens VCR.doTrackingCustomRightbar(); VCR.doTrackingCustomRightbarForPresentations() }); //check to see if error page if(window.device !== undefined) { var intervalImpressions = setInterval(function() { var shouldTrack = false; // no vcr widgets on index pages if(window.isIndexPage) { if(window.sponsoredPodcastDone === undefined || window.sponsoredPodcastDone) { shouldTrack = true; } } else //on homepage, bottom widget + 2 native widgets if(InfoQConstants.pageType == "HOMEPAGE" && window.finishedVcrOptional1 && window.finishedRelatedVcr && (window.finishedVcrOptional2 === undefined || window.finishedVcrOptional2)) { shouldTrack = true; } else // rightbar widgets + native widgets + content vcr widgets if((InfoQConstants.pageType == "NEWS_PAGE" || InfoQConstants.pageType == "ARTICLE_PAGE") && ((window.finishedRightbarVcr || window.finishedRightbarVcr === undefined) && window.contentVcrFinished)) { shouldTrack = true; } else if ((InfoQConstants.pageType == "PRESENTATION_PAGE") && (window.contentVcrFinished || window.contentVcrFinished === undefined) && (window.finishedRightbarVcr || window.finishedRightbarVcr === undefined) ) { shouldTrack = true; } else // native widgets + content widgets if(window.contentVcrFinished && (window.finishedVcrOptional1 || window.finishedVcrOptional1 === undefined) && (window.finishedVcrOptional2 || window.finishedVcrOptional2 === undefined)) { shouldTrack = true; } // we start tracking only after the page is fully loaded, frontend signals that they finished everything related to page display. if(shouldTrack && pageFullyLoaded) { clearInterval(intervalImpressions); Tracker.safeExec(Tracker.doTrackVcrImpressions); // start tracking viewable impressions also only after everything is ready function callbackRouter(entries, observer) { var targets = new Array(); entries.forEach(function (entry) { var target = entry.target; if (target.dataset.trkView === 'false') return; if (entry.intersectionRatio > 0) { target.dataset.trkView = false; targets.push(target); } }); Tracker.doTrackViewableImpressions(targets); } var elementsForTrackingViewableImpressions = document.querySelectorAll('[data-trk-view="true"]') var observer = new IntersectionObserver(callbackRouter, { threshold: 0.3 }); elementsForTrackingViewableImpressions.forEach(observer.observe.bind(observer)); } }, 500); } $(document).ready(function () { // desktop notifications widget Tracker.encodeNotificationLinks($(".f_notificationWidget")); // mobile notifications widget Tracker.encodeNotificationLinks($(".h_notifications")); // desktop notifications page Tracker.encodeNotificationLinks($(".notification-page")); // mobile notifications page Tracker.encodeNotificationLinks($(".notifications_page")); }); </script> <script type="text/javascript"> if(window.location.hash){ var hash = window.location.hash.substring(1); if(hash == 'subscribe'){ $('html,body').animate({scrollTop: $('.ftxt3 > .newsletter').offset().top}, 'slow'); } } </script> <script type="text/javascript"> var newsletterSubscriptionURL ='/newsletter/subscribe.action'; DynamicLinks.updateRssLinks('XnLuCjIf6z9BHCGZ6Nd4R76O32258ENr'); ContentSummary.setSelectedTab('en'); //when user enters the main content area show default topics in the topics bar $("#content-wrapper").mouseenter(function() { showDefaultTopics(); }); Bookmarks.contentTitle = "0 → 1, Shipping Threads in 5 Months"; Bookmarks.apiUrl = '/widgets/bookmark.action'; Bookmarks.isContentBookmarked = "false"; </script> <script type="text/javascript"> var $buoop = {vs:{i:6,f:1,o:10.1,s:1}} $buoop.ol = window.onload; $(document).ready(function() { try {if ($buoop.ol) $buoop.ol();}catch (e) {} var e = document.createElement("script"); e.setAttribute("type", "text/javascript"); e.setAttribute("src", "https://cdn.infoq.com/statics_s2_20250228123450/scripts/lib/browser-update-org/update.js"); document.body.appendChild(e); }); </script> <script> !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window,document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '842388869148196'); fbq('track', 'PageView'); </script> <noscript> <img height="1" width="1" src="https://www.facebook.com/tr?id=842388869148196&ev=PageView&noscript=1"/> </noscript> <script type='text/javascript'> try { mixpanel.track('page viewed', { 'page name' : document.title, 'url' : window.location.pathname }); } catch(err) { } </script> <!-- Latest Version --> <script src="https://cc.cdn.civiccomputing.com/9/cookieControl-9.x.min.js" type="text/javascript"></script> <script> const config = { apiKey: '8910ea974a96ffb6f927952b4ae9b9b0cc3e5973', product: 'PRO_MULTISITE', // general settings consentCookieExpiry: 90, encodeCookie: true, sameSiteCookie: true, // if false, cookie set as SameSite=None;secure; sameSiteValue: ';secure', // either 'Strict', 'Lax', or 'None' subDomains: true, initialState: 'notify', // 'notify','top','box' require pro licence notifyOnce: false, setInnerHTML: true, //layout settings layout: 'slideout', position: 'left', theme: 'light', acceptButton: true, rejectButton: true, closeOnGlobalChange: true, closeStyle: 'icon', toggleType: 'slider', notifyDismissButton: true, settingsStyle: 'link', excludedCountries: ['US'], /*accessibility: { disableSiteScrolling: true, },*/ statement: { description: 'For more detailed information about the cookies we use, see our', name: 'Cookie Policy', url: 'https://www.infoq.com/cookie-policy', updated: '01/01/2024', }, // cookies starting from 'cookie_expire' are from live.infoq.com but since we use the same tool on the same domain we need to specify those too so // that infoq.com cookieControl does not delete live.infoq.com cookies(also infoq.com cookies have been specified in live.infoq.com cookieControl configs) necessaryCookies: ['RegUserCookie', 'UserCookie', 'IdpCookie', 'ConversionTrackingV2_','PSAdialog','*P13NWN*','topbarSurvey','__bkm','JSESSIONID','mp_','_mixpanel','CloudFront-Key-Pair-Id','CloudFront-Policy','CloudFront-Signature','cookie_expire','discount_promo_closed','discount_promo_code','discount_promo_submitted','exit_survey_popup','referrer_popup','voting_popup_*','AWSALB','AWSALBCORS','aws-waf-token'], optionalCookies: [ { name: 'analytics', label: 'Analytics', description: 'Analytical cookies help us to improve our website by collecting and reporting information on its usage.', cookies: ['_ga', '_ga*', '_gid', '_gat', '__utma', '__utmt', '__utmb', '__utmc', '__utmz', '__utmv'], onAccept: function(){ gtag('consent', 'update', {'analytics_storage': 'granted'}); }, onRevoke: function(){ gtag('consent', 'update', {'analytics_storage': 'denied'}); } }, { name: 'marketing', label: 'Advertising', description: 'We use advertising cookies to display advertisements to you for our products.', onAccept: function(){ gtag('consent', 'update', {'ad_storage': 'granted', 'ad_personalization': 'granted', 'ad_user_data': 'granted'}); }, onRevoke: function(){ gtag('consent', 'update', {'ad_storage': 'denied', 'ad_personalization': 'denied', 'ad_user_data': 'denied'}); } } ], text : { // main preference panels title: '<h3>Our use of cookies</h3>', intro: 'We use necessary cookies to make our site work. Functional cookies help enhance the performance and functionality of the site. '+ 'We\'d also like to set analytics cookies to help us improve your experience by measuring how you use the site. '+ 'These will be set only if you accept. ', acceptSettings: 'I Accept', rejectSettings: 'I Do Not Accept', necessaryTitle : '<h3>Necessary Cookies</h3>', necessaryDescription : 'Necessary cookies enable core functionality ' + 'such as page navigation and access to secure areas. '+ 'The website cannot function properly without '+ 'these cookies, and can only be disabled by changing '+ 'your browser preferences.', closeLabel: 'Close Cookie Control', cornerButton: 'Set cookie preferences', // main preference panel controls on: 'On', off : 'Off', thirdPartyTitle : 'Some cookies require your attention', thirdPartyDescription : 'Consent for the following cookies could not be '+ 'automatically revoked. Please follow the link(s) '+ 'below to opt out manually.', // notification panels (only accessible for pro licences) notifyTitle : 'Your choice regarding cookies on this site', notifyDescription : 'We use cookies to optimise site functionality and '+ 'give you the best possible experience.', accept : 'I Accept', reject: 'I Do Not Accept', settings : 'Settings', }, branding : { removeAbout: true, }, }; // do not load this for local envs only. for testing on local envs remove/modify this condition if(InfoQConstants.pageUrl.indexOf('local')===-1){ CookieControl.load( config ); } </script> </body> </html> <!-- s2 -->

Pages: 1 2 3 4 5 6 7 8 9 10