<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Good Tech Things: Forrest Discovers Google Cloud]]></title><description><![CDATA[An AWS Hero turned Google Cloud employee, I explore the technical and philosophical differences between the two platforms. My biases are obvious, but opinions are my own.]]></description><link>https://newsletter.goodtechthings.com/s/forrest-discovers-google-cloud</link><image><url>https://substackcdn.com/image/fetch/$s_!pt3-!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F53dec02b-d276-41ae-98ec-b34b1e686c78_120x120.png</url><title>Good Tech Things: Forrest Discovers Google Cloud</title><link>https://newsletter.goodtechthings.com/s/forrest-discovers-google-cloud</link></image><generator>Substack</generator><lastBuildDate>Sat, 09 May 2026 04:22:04 GMT</lastBuildDate><atom:link href="https://newsletter.goodtechthings.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Forrest Brazeal]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[hello@goodtechthings.com]]></webMaster><itunes:owner><itunes:email><![CDATA[hello@goodtechthings.com]]></itunes:email><itunes:name><![CDATA[Forrest Brazeal]]></itunes:name></itunes:owner><itunes:author><![CDATA[Forrest Brazeal]]></itunes:author><googleplay:owner><![CDATA[hello@goodtechthings.com]]></googleplay:owner><googleplay:email><![CDATA[hello@goodtechthings.com]]></googleplay:email><googleplay:author><![CDATA[Forrest Brazeal]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Leaving Google Cloud]]></title><description><![CDATA[The hardest choice I've ever made]]></description><link>https://newsletter.goodtechthings.com/p/leaving-google-cloud</link><guid isPermaLink="false">https://newsletter.goodtechthings.com/p/leaving-google-cloud</guid><dc:creator><![CDATA[Forrest Brazeal]]></dc:creator><pubDate>Wed, 03 Jan 2024 19:16:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Quick thing up top so you see it: I&#8217;m taking a few requests for <a href="https://www.goodtechthings.com/speaking/">musical speaking engagements</a> this year. Book me for your team offsite or whatever!</em></p><p>I&#8217;m leaving Google Cloud at the end of this week.</p><p>Working at Google was a dream come true for me, something I&#8217;d imagined doing since I was a teenager. I met many interesting people in my 2.5 years there and got a taste of the complexity and impact of solving enormous hyperscaler-sized problems. </p><p>(I also once had to demo Vertex AI for Questlove and the Roots, and&#8212;in a semi-related incident&#8212;got a case full of video gear confiscated by the Albanian secret police. Don&#8217;t ask.)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rz_C!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rz_C!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 424w, https://substackcdn.com/image/fetch/$s_!Rz_C!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 848w, https://substackcdn.com/image/fetch/$s_!Rz_C!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 1272w, https://substackcdn.com/image/fetch/$s_!Rz_C!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rz_C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6ba50e2-869b-4219-99e2-970ed8957768.heic&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1216918,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/heic&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Rz_C!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 424w, https://substackcdn.com/image/fetch/$s_!Rz_C!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 848w, https://substackcdn.com/image/fetch/$s_!Rz_C!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 1272w, https://substackcdn.com/image/fetch/$s_!Rz_C!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6ba50e2-869b-4219-99e2-970ed8957768.heic 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Me and Questlove at Google Cloud Next. You&#8217;re just gonna have to deal with me sharing this picture in every newsletter from now on.</figcaption></figure></div><p>Sometimes Google even let me make complete nonsense like this Schoolhouse Rock-style ode to S3C, which is now used as the intro to some of their cloud security workshops:</p><div id="youtube2-NaR8WlLtPw0" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;NaR8WlLtPw0&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/NaR8WlLtPw0?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div><p>As people began to congregate again in person after the pandemic, I also began doing something completely new: I started doing talks for tech audiences that incorporated live performances of my songs. There&#8217;s something therapeutic about gathering a bunch of IT people in a room and singing about the vagaries of <a href="https://youtu.be/yDcaRklX7q4?feature=shared">re-orgs</a> or &#8220;<a href="https://youtu.be/VVc5QiMedno?feature=shared">digital transformations</a>&#8221; or <a href="https://www.youtube.com/watch?v=268jdNwH6AM">legacy code</a>. In a weird way, it helped me rediscover the joy I had found working with technology in the first place. Other people seemed to enjoy it too.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ciMt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ciMt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ciMt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ciMt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ciMt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ciMt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg" width="1456" height="971" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:17478723,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ciMt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 424w, https://substackcdn.com/image/fetch/$s_!ciMt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 848w, https://substackcdn.com/image/fetch/$s_!ciMt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!ciMt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8428f829-346a-496d-a9d9-5c2bf60a14f7_6240x4160.jpeg 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Giving the closing &#8220;key&#8221;-note at DevOps Enterprise Summit in Amsterdam</figcaption></figure></div><p>Google was incredibly supportive of me doing this, but eventually I realized something alarming: my job was no longer the right shape for what I wanted to do. Actually, it didn&#8217;t seem likely that any job was.</p><p>I&#8217;m used to the next right thing feeling certain and obvious. That&#8217;s probably because I&#8217;m used to being young. When you&#8217;re young, there are a lot of people out there whose examples you can imitate, and relatively low risk in trying things you&#8217;re not sure will work out. You also have an unearned confidence that comes from not having failed much yet.</p><p>But even the most conventionally successful of us, young or not, may reach a place in our careers where THERE IS NO OBVIOUS NEXT STEP. The things you&#8217;ve discovered you&#8217;re good at may not exactly line up with a standard corporate career path. There may no longer be an existing, ready-made challenge that&#8217;s the right size for you to step into.</p><p>There will just be a you-shaped hole in the world&#8212;its boundaries defined by your unique connections, the extreme limit of your skills, the scope of your ambitions&#8212;and trial and error is the only way you can figure out how to fill it.</p><p>So I handed in my resignation before Christmas, walking away from what was (to me, anyway) a significant amount of money. I&#8217;m still not sure this was a <em>smart</em> thing to do, but it was certainly exhilarating.</p><p>What&#8217;s next for me after Google?</p><p>For the first time in my working life, I&#8217;m allowing myself a little time to discover that. I&#8217;m not closing the door on returning to full-time employment if the shape is right. And I will be doing some consulting to keep my technical skills sharp.</p><p>What I&#8217;m most certain of is that <strong>I want to make things that bring joy to people</strong>, and I have a few ideas about what that might look like that I&#8217;m excited to try. (Watch this space!)</p><p>I can tell you that while I&#8217;m exploring and experimenting, I plan to spend time on a couple of familiar things:</p><ul><li><p>Breathing some new life into the <a href="https://cloudresumechallenge.dev/">Cloud Resume Challenge</a> (more on that soon).  </p></li><li><p>Doing more writing, speaking, and singing. Yes, I suspect my <a href="https://www.goodtechthings.com/">cartoons</a> and <a href="https://www.youtube.com/playlist?list=PLPUSFL3ut4ibHYoBes2tku_XUOHbpTFJZ">songs</a> are going to get even more ridiculous now that I&#8217;m self-employed. I&#8217;ve updated <a href="https://www.goodtechthings.com/speaking/">my speaker page</a>, and my piano and I would be happy to regale your conference or corporate offsite.</p></li></ul><p>I am grateful for what Google taught me about myself. I am happy for those who find joy and peace there. I am really excited about what I&#8217;m going to learn and build next.</p><p>If you have been wanting to collaborate with me on something, now would be a great time to <a href="mailto:hello@goodtechthings.com">get in touch</a>!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PFjQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PFjQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 424w, https://substackcdn.com/image/fetch/$s_!PFjQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 848w, https://substackcdn.com/image/fetch/$s_!PFjQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 1272w, https://substackcdn.com/image/fetch/$s_!PFjQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PFjQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png" width="1140" height="810" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:810,&quot;width&quot;:1140,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Calendars&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Calendars" title="Calendars" srcset="https://substackcdn.com/image/fetch/$s_!PFjQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 424w, https://substackcdn.com/image/fetch/$s_!PFjQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 848w, https://substackcdn.com/image/fetch/$s_!PFjQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 1272w, https://substackcdn.com/image/fetch/$s_!PFjQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7329d852-f752-4c4f-a5f4-72c4ac6f6c3f_1140x810.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">I&#8217;m gonna try to take it easy on meetings for a while, though.</figcaption></figure></div><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Calm down about Service Weaver]]></title><description><![CDATA[It isn't a silver bullet, and it's not claiming to be]]></description><link>https://newsletter.goodtechthings.com/p/calm-down-about-service-weaver</link><guid isPermaLink="false">https://newsletter.goodtechthings.com/p/calm-down-about-service-weaver</guid><dc:creator><![CDATA[Forrest Brazeal]]></dc:creator><pubDate>Fri, 03 Mar 2023 19:20:25 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!HZDv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In 1991, the standards consortium OMG published the first version of something called CORBA, a standard that promised to bring distributed programming to the masses. No more weird homegrown RPC implementations that didn&#8217;t interoperate! Developers wouldn&#8217;t need to know the hardware, operating system, or even the languages used by remote machines. Through the power of its fancy new interface definition language, CORBA was going to be the beginning and the end of all middleware. OMG, indeed!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HZDv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HZDv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 424w, https://substackcdn.com/image/fetch/$s_!HZDv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 848w, https://substackcdn.com/image/fetch/$s_!HZDv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 1272w, https://substackcdn.com/image/fetch/$s_!HZDv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!HZDv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png" width="401" height="402" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:402,&quot;width&quot;:401,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Illustration of the autogeneration of the infrastructure code from an interface defined using the CORBA IDL&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Illustration of the autogeneration of the infrastructure code from an interface defined using the CORBA IDL" title="Illustration of the autogeneration of the infrastructure code from an interface defined using the CORBA IDL" srcset="https://substackcdn.com/image/fetch/$s_!HZDv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 424w, https://substackcdn.com/image/fetch/$s_!HZDv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 848w, https://substackcdn.com/image/fetch/$s_!HZDv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 1272w, https://substackcdn.com/image/fetch/$s_!HZDv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F38e5c755-8e80-4ba8-9718-e56c60aefbc4_401x402.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><a href="https://en.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture">How CORBA worked at a high level</a>. (It only worked at a high level.)</figcaption></figure></div><p>CORBA never took over the world for <a href="https://queue.acm.org/detail.cfm?id=1142044">a variety of reasons</a>&#8212;not all of them technical&#8212;but the <em>funniest </em>excuse appears on <a href="https://en.wikipedia.org/wiki/Common_Object_Request_Broker_Architecture">its Wikipedia page</a>:</p><div class="pullquote"><p>Much of the criticism of CORBA stems from poor implementations of the standard and not deficiencies of the standard itself.</p></div><p>See, the <em>spec </em>was great, it was just those silly programmers who couldn&#8217;t figure out how to apply it. The pesky <a href="https://particular.net/blog/topics/fallacies">fallacies of distributed computing</a> kept getting in the way.</p><p>But software keeps needing to talk to other software over the network, and so people keep trying to design protocols and component models and service-oriented architectures to make it easier.</p><p>Microsoft tried it with DCOM (and, more recently, with <a href="https://learn.microsoft.com/en-us/dotnet/orleans/">Orleans</a><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>). Enterprise JavaBeans apps have been doing RPC stuff forever. The worst person you know won&#8217;t shut up about the Erlang actor model. </p><p>These solutions have made their way into lots of production systems over the years, so it would be wrong to say they &#8220;don&#8217;t work&#8221;, but nobody who&#8217;s had to support them seems very happy about it. A big reason is that distributed programming models often make a seductive promise that is impossible to fulfill: they gloss over the realities of time and space by pretending that a bunch of remote machines are the same thing as one local machine, or vice versa. (See <a href="https://news.ycombinator.com/item?id=35007615">this glorious rant about what that meant for unsuspecting DCOM developers</a>). </p><p>In a nutshell: Distributed systems are irreducibly tricky, <a href="https://scholar.harvard.edu/files/waldo/files/waldo-94.pdf">we&#8217;ve known this for decades</a>, and it&#8217;s probably best that everyone stays mentally prepared for it&#8212;particularly in the cloud.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UPL_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UPL_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 424w, https://substackcdn.com/image/fetch/$s_!UPL_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 848w, https://substackcdn.com/image/fetch/$s_!UPL_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 1272w, https://substackcdn.com/image/fetch/$s_!UPL_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UPL_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png" width="1280" height="1280" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1280,&quot;width&quot;:1280,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Distributed Architecture&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Distributed Architecture" title="Distributed Architecture" srcset="https://substackcdn.com/image/fetch/$s_!UPL_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 424w, https://substackcdn.com/image/fetch/$s_!UPL_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 848w, https://substackcdn.com/image/fetch/$s_!UPL_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 1272w, https://substackcdn.com/image/fetch/$s_!UPL_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b07644-3d1d-4c77-8bfa-ce7107f9e69b_1280x1280.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Pretty much <a href="https://www.goodtechthings.com/distributed-architecture/">this</a></figcaption></figure></div><p>So you can see why when this week Google open-sourced <a href="https://opensource.googleblog.com/2023/03/introducing-service-weaver-framework-for-writing-distributed-applications.html">a &#8220;framework for writing distributed applications&#8221; called Service Weaver</a>, the overwhelming reaction was deja vu.</p><p>Martin Kleppmann, the patron saint of your distributed systems book club, is skeptical:</p><div class="twitter-embed" data-attrs="{&quot;url&quot;:&quot;https://twitter.com/martinkl/status/1631602767524495363&quot;,&quot;full_text&quot;:&quot;Google's Service Weaver claims that it can hide the difference between RPC and local method calls. Just like CORBA claimed in 1991. Is it different this time? The docs say barely a word about handing failures, such as RPCs timing out &quot;,&quot;username&quot;:&quot;martinkl&quot;,&quot;name&quot;:&quot;Martin Kleppmann @martin@nondeterministic.computer&quot;,&quot;profile_image_url&quot;:&quot;&quot;,&quot;date&quot;:&quot;Fri Mar 03 10:29:48 +0000 2023&quot;,&quot;photos&quot;:[],&quot;quoted_tweet&quot;:{},&quot;reply_count&quot;:0,&quot;retweet_count&quot;:34,&quot;like_count&quot;:266,&quot;impression_count&quot;:0,&quot;expanded_url&quot;:{&quot;url&quot;:&quot;https://serviceweaver.dev/&quot;,&quot;image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4836606-33db-4892-ace9-2a82cb90915a_1024x1024.svg&quot;,&quot;title&quot;:&quot;Service Weaver&quot;,&quot;description&quot;:null,&quot;domain&quot;:&quot;serviceweaver.dev&quot;},&quot;video_url&quot;:null,&quot;belowTheFold&quot;:true}" data-component-name="Twitter2ToDOM"></div><p>And skeptical also are <a href="https://twitter.com/kelseyhightower/status/1630995723956412420">hundreds of others in Kelsey Hightower&#8217;s mentions</a>. Kelsey and the core maintainers of the project have been working overtime to listen and respond to all the feedback; here&#8217;s <a href="https://twitter.com/kelseyhightower/status/1631352524157648896">a Twitter Space they did yesterday</a> that addresses a lot of common questions.</p><p>It does sound like the announcement blog and the docs could use some tweaking. In particular, I think the &#8220;write a monolith, deploy microservices&#8221; framing has gotten some people a bit off track. It seems to me that Service Weaver isn&#8217;t really a tool for creating self-contained microservices as they&#8217;re classically understood; it&#8217;s more about spreading a single service over multiple pieces of compute.</p><p>If you&#8217;re trying to figure out &#8220;why does Service Weaver need to exist&#8221;, here&#8217;s my understanding:</p><ol><li><p>It&#8217;s Golang-first right now, and the Go ecosystem didn&#8217;t previously have a tool like this;</p></li><li><p>It does seem to provide better tools for dealing with some real problems people are experiencing with big Kubernetes deployments, such as upgrade versioning and testing, by consolidating code maintenance into one place while allowing atomic deployments;</p></li><li><p>It provides some measurable performance gains for network calls via a custom serialization mechanism;</p></li><li><p>It gives you some observability hooks with OpenTelemetry out of the box so you can get more insight into the distributed calls you might be making.</p></li></ol><p>So I think for people who are deep into the services-on-Kubernetes world, Service Weaver has potential as a <em>deployment</em> tool&#8212;as long as we don&#8217;t attempt to paint it as a magic <em>development</em> framework that makes remote function calls behave just like local ones. That didn&#8217;t work for CORBA and it won&#8217;t work for you and me.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a></p><p>On the other hand, if you are building the kind of architectures that some of us like to call &#8220;<a href="https://www.forbes.com/sites/oracle/2017/10/12/the-trouble-with-promises-patrick-debois-explains-serverless-and-service-full-culture/?sh=2c54443a452d">service-full</a>&#8221; (that is, gluing cloud services together and representing the application control flow in the infrastructure diagram), then I&#8217;m more interested in something like <a href="https://www.winglang.io/">Wing</a>, a new programming language that interacts with cloud infrastructure the way .NET wraps Windows syscalls.</p><p>Either way, I&#8217;m cautiously encouraged that Service Weaver is a step up the abstraction ladder from &#8220;caring a lot about containers&#8221; by decoupling deployment topology from app code. And I think the widespread community interest very clearly marks it as a project to watch going forward.</p><p>In the meantime, well&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4NaI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4NaI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 424w, https://substackcdn.com/image/fetch/$s_!4NaI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 848w, https://substackcdn.com/image/fetch/$s_!4NaI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 1272w, https://substackcdn.com/image/fetch/$s_!4NaI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4NaI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png" width="1140" height="1140" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1140,&quot;width&quot;:1140,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Marco Polo&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Marco Polo" title="Marco Polo" srcset="https://substackcdn.com/image/fetch/$s_!4NaI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 424w, https://substackcdn.com/image/fetch/$s_!4NaI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 848w, https://substackcdn.com/image/fetch/$s_!4NaI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 1272w, https://substackcdn.com/image/fetch/$s_!4NaI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1faaf66b-5a91-41bf-879a-2ee1cf9c8c93_1140x1140.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"></figcaption></figure></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>There are a lot of tools out there that ship their org chart, but I can&#8217;t remember seeing anything quite so Conway&#8217;s-Law as Orleans calling their control primitive a &#8220;silo&#8221;.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Kelsey and others have suggested that the safest way to use Service Weaver is to write code as if any function you invoke could be a remote call. I admit being a little skeptical of this approach, as assuming &#8220;worst-case&#8221; complexity for every call is <a href="https://www.cc.gatech.edu/classes/AY2010/cs4210_fall/papers/smli_tr-94-29.pdf">one of the very antipatterns that sunk CORBA</a>.</p></div></div>]]></content:encoded></item><item><title><![CDATA[In pursuit of compute]]></title><description><![CDATA[What I learned about Google Cloud compute while figuring out how to host a Discord bot]]></description><link>https://newsletter.goodtechthings.com/p/in-pursuit-of-compute</link><guid isPermaLink="false">https://newsletter.goodtechthings.com/p/in-pursuit-of-compute</guid><dc:creator><![CDATA[Forrest Brazeal]]></dc:creator><pubDate>Thu, 23 Jun 2022 17:37:31 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/h_600,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey there! It&#8217;s been awhile.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> </p><p>I&#8217;ve been on parental leave for a few weeks, which has been amazing for lots of reasons. It&#8217;s the first time in my career I&#8217;ve taken several consecutive weeks off work, and while it would be wrong to call it a &#8220;break&#8221;, the change of pace has been transformative. Or do I mean informative? I&#8217;m not sure. I didn&#8217;t get much sleep last night.</p><p>Anyway, at the moment my daughter is sleeping on my lap and so I have a few minutes to write up a side project I&#8217;ve been playing with.</p><p>I&#8217;m working on some fun updates to the <a href="https://cloudresumechallenge.dev/">Cloud Resume Challenge</a> (more on that in a few weeks), and one thing I need to build is a bot to help manage <a href="https://discord.gg/2PTwAth">the 4,000-member CRC Discord server</a>. My requirements for the bot architecture:</p><ul><li><p>I want it to be as serverless/managed as possible, because I&#8217;m still that guy;</p></li><li><p>I want to run it on Google Cloud, because I&#8217;m still trying to get my head around Google Cloud;</p></li><li><p>I want to run it for free, because I want to understand the limits of the Google Cloud free tier and also because I like free things.</p></li></ul><p>If you don&#8217;t know much about Discord or Discord bots, there is <a href="https://discord.com/developers/docs/intro">endless documentation</a> out there, much of it either 1) contradictory, due to Discord&#8217;s habit of releasing vaguely similar new APIs at breakneck pace into a peculiar ecosystem of community-maintained language SDKs that are constantly winking in and out of existence like firefly lights, or 2) out-of-date, due to knock-on effects of 1). Bottom line: it&#8217;s a much more bewildering space than I expected, and I underestimated the complexity here.</p><p>So this post is going to feel a bit random, but what I&#8217;m going to try to do is talk you through my process of discovering the best way to host a Discord bot on Google Cloud and what I learned about Google Cloud&#8217;s compute options along the way.</p><h3>First idea: Cloud Run</h3><p>At first blush, this seems like a classic serverless use case. We want to write some Python<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> that will listen to events from Discord and maybe send some scheduled messages. In the AWS world, I&#8217;d have used Lambda and API Gateway to do this. In the Google Cloud world we could use Cloud Functions, but recent updates to Cloud Functions have made clear that it&#8217;s <a href="https://cloud.google.com/functions/docs/2nd-gen/overview">pretty much just a programming conceit on top of Cloud Run now</a>, so for the sake of keeping my mental models straight let&#8217;s consider Cloud Run to be Google Cloud&#8217;s default &#8220;serverless&#8221; offering.</p><p>I found Cloud Run interesting to work with, for reasons outlined in this Twitter thread:</p><div class="twitter-embed" data-attrs="{&quot;url&quot;:&quot;https://twitter.com/forrestbrazeal/status/1534538919856988161&quot;,&quot;full_text&quot;:&quot;Getting hands-on with Google Cloud Run for a little side project this week. Impressed so far. If there's a smoother way to go from idea -&amp;gt; container -&amp;gt; cloud, I haven't seen it.\n\nI'll try to thread a few observations here as I learn.&quot;,&quot;username&quot;:&quot;forrestbrazeal&quot;,&quot;name&quot;:&quot;Forrest Brazeal&quot;,&quot;profile_image_url&quot;:&quot;&quot;,&quot;date&quot;:&quot;Wed Jun 08 14:12:43 +0000 2022&quot;,&quot;photos&quot;:[],&quot;quoted_tweet&quot;:{},&quot;reply_count&quot;:0,&quot;retweet_count&quot;:5,&quot;like_count&quot;:72,&quot;impression_count&quot;:0,&quot;expanded_url&quot;:{},&quot;video_url&quot;:null,&quot;belowTheFold&quot;:true}" data-component-name="Twitter2ToDOM"></div><p>AWS people can think of Cloud Run as a more developer-friendly, slightly more &#8220;serverless&#8221; version of Fargate; the emulated development options are nice, and it has super smooth, flexible scaling and concurrency out of the box - all the way down to zero.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a></p><p>But there&#8217;s a problem. The problem is Discord&#8217;s classic way of interacting with bots, which is basically just to hold open a socket on a piece of long-running compute. (There is a newer way of talking to Discord bots that&#8217;s more event-driven - we&#8217;ll get to that in a minute; I&#8217;m sharing my learning in the order I figured it out.) That means we can&#8217;t host our bot using Cloud Run&#8217;s classic execution mode, which only spins up a CPU to process requests and scales to zero the rest of the time. Instead, we&#8217;d have to use the newer <a href="https://cloud.google.com/blog/products/serverless/cloud-run-gets-always-on-cpu-allocation">&#8220;always-on CPU allocation&#8221;</a> feature that keeps the container running indefinitely.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> And this runs afoul of both my serverless and cost management goals. Classic Cloud Run has a great free tier; you can crunch through millions of free requests per month, just like on Lambda. Switch over to Always-On and the cheapest CPU is going to cost something like $20/month. Ugh. Let&#8217;s keep looking.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><h3>GCE (the coward&#8217;s refuge)</h3><p>For the reasons I just explained, the traditional way of hosting a Discord bot has always been just to dump it on the cheapest VM you can find. This is in fact what Google Cloud suggests, by way of <a href="https://cloud.google.com/blog/topics/developers-practitioners/build-and-run-discord-bot-top-google-cloud">a DevRel-authored tutorial blog from a year or two ago</a>: just plop the thing on Google Compute Engine and have done with it. This has the advantage of being free: Google Cloud&#8217;s free tier lets you run <a href="https://cloud.google.com/free/docs/gcp-free-tier/#compute">one e2-micro instance</a> at any time. That tutorial doesn&#8217;t really give a serious example, though; it suggests just SSHing into the server and executing your bot script from the command line. I&#8217;m looking for quick and cheap, but I&#8217;m not a <em>barbarian. </em></p><p>It turns out that Google Cloud doesn&#8217;t have a standalone VPS product like AWS Lightsail or [insert your favorite &#8220;deploy a container to the cloud with 1 command&#8221; product here], but what they do have are <a href="https://cloud.google.com/container-optimized-os/docs/concepts/features-and-benefits">container-optimized VMs</a>. These are locked-down instances that run Docker and allow you to specify the entrypoint when you deploy the instance itself. If you want to run a single container on a single VM, for free, a container-optimized e2-micro GCE instance is the Google Cloud way to do it. And I did it.</p><p>(Pausing here to shout out the Google Cloud GitHub Actions developed by Google Cloud&#8217;s DevRel team, and specifically <a href="https://github.com/google-github-actions/setup-gcloud/tree/main/example-workflows/gce">the GCE example workflow</a>; they made it super easy for me to get my bot from repo to the cloud.)</p><div class="twitter-embed" data-attrs="{&quot;url&quot;:&quot;https://twitter.com/forrestbrazeal/status/1539637238010617862&quot;,&quot;full_text&quot;:&quot;Finally getting into GitHub Actions, and these Google Cloud actions developed by <span class=\&quot;tweet-fake-link\&quot;>@sethvargo</span>, <span class=\&quot;tweet-fake-link\&quot;>@sigje</span> and team have come in super handy. It's awesome to stumble on something that exactly anticipates your needs! &quot;,&quot;username&quot;:&quot;forrestbrazeal&quot;,&quot;name&quot;:&quot;Forrest Brazeal&quot;,&quot;profile_image_url&quot;:&quot;&quot;,&quot;date&quot;:&quot;Wed Jun 22 15:51:37 +0000 2022&quot;,&quot;photos&quot;:[],&quot;quoted_tweet&quot;:{},&quot;reply_count&quot;:0,&quot;retweet_count&quot;:6,&quot;like_count&quot;:32,&quot;impression_count&quot;:0,&quot;expanded_url&quot;:{&quot;url&quot;:&quot;https://github.com/google-github-actions&quot;,&quot;image&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/37e8b57a-6be4-4e11-bfa9-f781b7efb627_280x280.png&quot;,&quot;title&quot;:&quot;Google GitHub Actions&quot;,&quot;description&quot;:&quot;Google Cloud integrations for the GitHub Actions Marketplace - Google GitHub Actions&quot;,&quot;domain&quot;:&quot;github.com&quot;},&quot;video_url&quot;:null,&quot;belowTheFold&quot;:true}" data-component-name="Twitter2ToDOM"></div><p>So now I have a Discord bot running on Google Cloud, for free, but very much not serverless. This isn&#8217;t just a cosmetic complaint; my bot can&#8217;t scale beyond its single e2-micro instance, it&#8217;s not HA, and the long-polling architecture means all my control logic for scheduled tasks is wrapped up in my server instead of using <a href="https://cloud.google.com/scheduler">Google Cloud Scheduler</a>.</p><h3>To boldly go where no event has gone before</h3><p>Here&#8217;s where I started learning about newer Discord API modes like <a href="https://discord.com/developers/docs/interactions/application-commands">Interaction Events</a>, which allow you to leave the old long-polling clients behind and just respond to HTTP POST requests like a normal web app. It would seem this would allow us to go back to Cloud Run and build a true event-driven bot, right? </p><p>Well, sort of. I&#8217;m not aware of anyone who&#8217;s built this on Cloud Run, but <a href="https://gemisis.medium.com/building-a-serverless-discord-bot-on-aws-5dc7d972c9c6">Gerald McAlister tried it on Lambda</a>, and the problem he ran into was &#8230; wait for it&#8230; </p><p>(are you waiting?) </p><p>&#8230; cold starts. </p><p>Discord enforces a 3-second timeout on responses to its interaction events. Depending on your language, package size, etc, this can leave you with little time to process an I/O-bound command after a cold start. McAlister&#8217;s clever solution is <a href="https://github.com/GEMISIS/discord-bot-cdk-construct">a CDK construct that uses two chained Lambda functions</a> - one to respond to the initial request and send Discord back a provisional response, the other to do the bulk of the command processing and return the final output. This is, needless to say, a hack - and I think it still might not avoid cold start timeouts in the p&gt;99 case.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7tW3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7tW3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 424w, https://substackcdn.com/image/fetch/$s_!7tW3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 848w, https://substackcdn.com/image/fetch/$s_!7tW3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 1272w, https://substackcdn.com/image/fetch/$s_!7tW3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7tW3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png" width="700" height="432" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:432,&quot;width&quot;:700,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7tW3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 424w, https://substackcdn.com/image/fetch/$s_!7tW3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 848w, https://substackcdn.com/image/fetch/$s_!7tW3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 1272w, https://substackcdn.com/image/fetch/$s_!7tW3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F9c802062-abf5-4377-a6e1-c9c6ae411c1e_700x432.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">McAlister&#8217;s Hack (<a href="https://gemisis.medium.com/building-a-serverless-discord-bot-on-aws-5dc7d972c9c6">source</a>)</figcaption></figure></div><p>If I was building on AWS, I&#8217;d be tempted to borrow his CDK construct, but I kind of doubt this trick is worth porting over to Google Cloud. Come to think of it, most of what I need this bot to do can probably be implemented using <a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks">webhooks</a>, where the command is initiated by my app and not the Discord server. And THAT I can do - for free! - on Cloud Run.</p><h2>Links and events</h2><ul><li><p>The Cloud Resume Challenge has always been about helping people <a href="https://twitter.com/forrestbrazeal/status/1536107605390675970">build something real</a>. But beyond the OG challenge, there&#8217;s great need for more reality-informed cloud project ideas touching on security, observability, cloud automation, and more. So the Cloud Resume Challenge is now <a href="https://github.com/cloudresumechallenge/projects">an open-source project inviting community extensions</a>. Recent add-on projects have included <a href="https://github.com/cloudresumechallenge/projects/blob/main/projects/networking/traditional-web-hosting-on-aws.md">a classical networking jaunt</a> and <a href="https://github.com/cloudresumechallenge/projects/blob/main/projects/security/supply-chain.md">a secure software supply chain challenge</a>. If you have cloud knowledge and would like to propose a challenge, I hope you&#8217;ll contribute a project prompt or <a href="https://github.com/cloudresumechallenge/projects/issues">suggest one via issue</a>!</p></li><li><p>On a similar note, I <a href="https://www.youtube.com/watch?v=mZuZ697Z90A&amp;t=3836s">keynoted Pluralsight&#8217;s Tech Skills Day</a>, sharing my recommendations on how to build a great cloud side project.</p></li><li><p>I chatted with The Cloudcast about <a href="https://www.thecloudcast.net/2022/03/developing-multi-cloud-skills.html">building multi-cloud skills</a>. (Spoiler: I think you should, even if you&#8217;d never consider building a multicloud app.)</p></li></ul><h2>Just for fun</h2><p>I&#8217;ve guested on a few podcasts recently, but none more fun than <a href="https://changelog.com/podcast/477">this episode of The Changelog&#8217;s &#8220;Song Encoder&#8221;</a>, where we took a tour through a bunch of my tech songs and examined the key question: why would anyone do this?</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Reminder for those who are new here: in each issue of Cloud Irregular, I try to provide a piece of useful cloud commentary, round up links to things I&#8217;ve published elsewhere, and leave you with something silly and fun. While there is technically a paid version of this newsletter, I disabled payments several months ago and have no plans to turn them back on.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Well, <em>I </em>want to write some Python.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>&#8220;Serverless&#8221; compute services ranked from &#8220;most serverless to least serverless&#8221;, in my opinion: AWS Lambda, Google Cloud Run, AWS Fargate, <a href="https://azure.microsoft.com/en-us/blog/bringing-serverless-to-azure-kubernetes-service/">AKS virtual nodes</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>We&#8217;d also need to be careful about concurrency; a Cloud Run container can handle <a href="https://cloud.google.com/run/docs/about-concurrency">up to 80 concurrent requests</a> by default, but to keep from confusing the Discord client we&#8217;d need to lock it down to 1.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>I did end up using Cloud Run for an adjacent little web service, though. No complaints so far.</p></div></div>]]></content:encoded></item><item><title><![CDATA[Digging into that Pokémon GO architecture]]></title><description><![CDATA[Why did they build it on Google Cloud?]]></description><link>https://newsletter.goodtechthings.com/p/digging-into-that-pokemon-go-architecture</link><guid isPermaLink="false">https://newsletter.goodtechthings.com/p/digging-into-that-pokemon-go-architecture</guid><dc:creator><![CDATA[Forrest Brazeal]]></dc:creator><pubDate>Mon, 01 Nov 2021 13:06:16 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Gm5R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The other day, Google Cloud&#8217;s consistently excellent <a href="https://twitter.com/pvergadia">Priyanka Vergadia</a> released <a href="https://cloud.google.com/blog/topics/developers-practitioners/how-pok%C3%A9mon-go-scales-millions-requests">this interesting interview</a> with an engineering manager at Niantic Labs, the people behind Pok&#233;mon GO.</p><p>My favorite thing about that interview is that &#8230; well okay, my <em>favorite </em>thing is that it&#8217;s been transcribed for text, which I find much easier to consume than video. But my second favorite thing is that it gives you a peek into how you can run something in the cloud that requires simply stupid levels of global scale, while also keeping interactive latency down to a level approximating &#8220;real life&#8221;. There&#8217;s a reason that a lot of the historical innovations in computing have come out of gaming. This is a next-level problem and I recommend reading/watching the interview multiple times to pull out the nuances of what Niantic&#8217;s James Prompanya is explaining.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Gm5R!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Gm5R!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Gm5R!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Gm5R!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Gm5R!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Gm5R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg" width="1200" height="708" data-attrs="{&quot;src&quot;:&quot;https://bucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com/public/images/d2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:708,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Image&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Image" title="Image" srcset="https://substackcdn.com/image/fetch/$s_!Gm5R!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Gm5R!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Gm5R!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Gm5R!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2Fd2314870-8b34-4427-89c2-9dbe60708b97_1200x708.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">The (very high-level) view of Pok&#233;mon GO&#8217;s cloud infrastructure shared in the interview. We&#8217;ll break this down in a sec.</figcaption></figure></div><p>Hours after the interview came out, a reader of this newsletter reached out to me with the following question:</p><blockquote><p>&#8220;I'd love to see a tweet thread from you decrypting [the above design], mapping the various parts to equivalent AWS services. [To be honest,] I've never really taken Google Cloud very seriously because I've never seen the architecture of a major app like this running on GCP - they always seem to be leaning on AWS more. It would be instructive, if you have the time.&#8221;</p></blockquote><p>They do say adults learn primarily by analogy, and I&#8217;m right there with ya, reader - my background is all AWS, and when I see an architecture like this I immediately try to relate it to what I already know. </p><p>So why did Niantic choose to build this app on Google Cloud? Could you do it using equivalent services on AWS? What tradeoffs are they making here?</p><p>It&#8217;s hard to give too serious of an analysis based on the high level of the information available, but here are four things that jump out to me. Let&#8217;s see if we can use them to shed some new light on both clouds.</p><h3>Spanner</h3><p>Let&#8217;s start with Google Cloud Spanner, the boldest choice made in this design. Is there a comparable service to it on AWS?</p><p>We know that global low latency, ACID transactions, and relational semantics are important to Niantic. They&#8217;re pumping a brain-bleeding amount of traffic through this thing as well, so it has to stay fast at giant scale. What AWS database could do this? Prompanya says they evolved past Google Datastore, so DynamoDB is probably not going to work for them either.<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><p>The closest AWS-native service to GO&#8217;s requirements would probably be Aurora, but Aurora is not going to give you the same global write-anywhere/replicate-everywhere abilities as Spanner. (You can have multi-master clusters in Aurora now, but <a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-multi-master.html#aurora-multi-master-limitations">all the instances have to be in the same region</a>, and you can&#8217;t enable cross-region replication on them.) Think of Aurora as Postgres or MySQL on cloud steroids, but still fundamentally bound by the traditional database rules of clustering, failover, and replication. Whereas Spanner is this <a href="https://cloud.google.com/spanner/docs/replication">shapeshifting Paxos-based voodoo creature</a> that globally distributes your data at the row level.</p><p>The tradeoff with Spanner, one that Niantic apparently was okay with, is that you&#8217;re not going to get a familiar engine to build on - it speaks SQL, but it&#8217;s a bespoke system with its own libraries and drivers. It&#8217;s worth noting that <a href="https://cloud.google.com/blog/topics/developers-practitioners/postgresql-interface-adds-familiarity-and-portability-cloud-spanner">Spanner finally got Postgres compatibility</a> in preview about two weeks ago, though.</p><p>Bottom line: I don&#8217;t think you could reproduce this piece of the app one-to-one on AWS services. If you really want a Spanner-like experience on AWS, your best bet might be to pull in a third-party service: specifically <a href="https://www.cockroachlabs.com/">CockroachDB</a>, which <a href="https://www.cockroachlabs.com/blog/living-without-atomic-clocks/">approximates</a> Spanner&#8217;s &#8220;TrueTime&#8221; design in software to get around Google&#8217;s reliance on atomic clocks. </p><h3>GKE</h3><p>The Kubernetes cluster in that diagram is a bit of a black box as presented; we&#8217;re given tantalizing hints about caching and event-driven optimizations, but we don&#8217;t really know how all these services are talking to each other.</p><p>The part of my brain that used to be a Serverless Hero says &#8220;see, this is what&#8217;s so great about serverless! If you&#8217;d just built your thing out of functions, all the complexity would be forced onto the cloud infrastructure diagram, and we wouldn&#8217;t have to guess about it!&#8221;</p><p>But, of course, I&#8217;m not saying this architecture could or should have been built on functions. The near-real-time latency requirements alone might rule that out. Instead, per the interview, we get &#8220;thousands&#8221; of containers - and if you&#8217;re going to run that much Kubernetes, you probably want to let a cloud provider manage it for you. </p><p>My bias here is to say that, given the choice, GKE is a better all-around option than AWS EKS. It&#8217;s simply the most fully-featured and the most automated managed K8s service of the 3 major cloud providers, as you can see in this <a href="https://acloudguru.com/blog/engineering/aks-vs-eks-vs-gke-managed-kubernetes-services-compared">bake-off</a> I helped put together for ACG a few months ago<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>. I&#8217;d be curious to know what Niantic&#8217;s compute bill looks like, though.</p><h3>Cloud load balancing</h3><p>For fairness&#8217; sake, I should call out something here that&#8217;s been an <em>unpleasant </em>surprise for me when picking up Google Cloud: that even a simple static website <a href="https://cloud.google.com/storage/docs/hosting-static-website">requires you</a> to put an always-on Cloud Load Balancer in front of the storage bucket just to get HTTPS. I don&#8217;t want my static assets to charge me 24/7 for compute costs!</p><p>Obviously what&#8217;s going on here is more complex. But still, it appears the Cloud Load Balancer / CDN / Storage part of the architecture could be replaced by Cloudfront and S3 without much conceptual tweaking.</p><h3>Data and monitoring</h3><p>The one place where we actually get to see a bit of message passing happening in this architecture is the Pub/Sub notification (Google Cloud&#8217;s version of AWS SNS) that triggers the decoupled data warehousing / analytics stuff. An AWS equivalent of the Bigtable &#8594; Dataflow &#8594; BigQuery pipeline in the diagram would be a <a href="https://docs.aws.amazon.com/glue/latest/dg/add-job-streaming.html">streaming ETL job</a>, something like DynamoDB &#8594; Kinesis &#8594; Glue &#8594; RedShift. Your opinions of RedShift may vary, but I suspect Niantic is quite happy using BigQuery for their data lake needs.</p><p>One last thing. Did you notice that Prompanya keeps mentioning how happy they are with using Google Cloud Monitoring as their primary pane of glass to keep an eye on all this stuff? Coming from the AWS world, that really jumped out at me. When&#8217;s the last time you heard of someone monitoring a massive-scale app in AWS using nothing but CloudWatch - not to mention evidently being quite proud of that fact? </p><p>Now, to be fair, Prompanya never says that Google Cloud Monitoring is their <em>only </em>window into how the app behaves, and there could be some editorial bowdlerizing going on here. But still I&#8217;m getting the spidey-sense that, <a href="https://cloud.google.com/blog/products/identity-security/identity-and-environment-in-google-cloud">like with IAM and environments</a>, there may be some fundamental quality-of-life difference between monitoring on AWS and on Google Cloud.</p><p>Maybe in the next installment of this newsletter, I&#8217;ll have to do a deep dive into Google Cloud Monitoring and see what all the fuss is about.</p><p><em>Disclaimer, as always, that I&#8217;m new to Google Cloud and could be totally off on something here. If so, let me know and I&#8217;ll fix it.</em></p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Could DynamoDB <em>theoretically</em> fulfill the latency and data model requirements of Pok&#233;mon GO? I suspect <a href="https://twitter.com/houlihan_rick?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor">Rick Houlihan</a> would say yes. He also might be the only person who could pull it off.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Note: that article was released before the announcement of <a href="https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview">GKE Autopilot</a>, which abstracts away even more of the K8s management responsibilities.</p><p></p></div></div>]]></content:encoded></item></channel></rss>