<?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[Experiments: ML and Data Engineering]]></title><description><![CDATA[Machine learning and Data Engineering posts, thoughts and tutorials.]]></description><link>https://blog.ismail.bio/s/ml-and-data-engineering</link><image><url>https://substackcdn.com/image/fetch/$s_!EF-d!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6df693b6-9478-43c4-91ab-762d4d455088_906x906.png</url><title>Experiments: ML and Data Engineering</title><link>https://blog.ismail.bio/s/ml-and-data-engineering</link></image><generator>Substack</generator><lastBuildDate>Tue, 21 Apr 2026 10:37:47 GMT</lastBuildDate><atom:link href="https://blog.ismail.bio/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Ismail Elouafiq]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[ismail@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[ismail@substack.com]]></itunes:email><itunes:name><![CDATA[Ismail Elouafiq]]></itunes:name></itunes:owner><itunes:author><![CDATA[Ismail Elouafiq]]></itunes:author><googleplay:owner><![CDATA[ismail@substack.com]]></googleplay:owner><googleplay:email><![CDATA[ismail@substack.com]]></googleplay:email><googleplay:author><![CDATA[Ismail Elouafiq]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Make your data pipeline less chaotic by one versioned definition of data]]></title><description><![CDATA[Data collection at Sweden&#8217;s Television]]></description><link>https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic</link><guid isPermaLink="false">https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic</guid><dc:creator><![CDATA[Ismail Elouafiq]]></dc:creator><pubDate>Tue, 06 Jan 2026 13:56:09 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!TG2c!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TG2c!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TG2c!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 424w, https://substackcdn.com/image/fetch/$s_!TG2c!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 848w, https://substackcdn.com/image/fetch/$s_!TG2c!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 1272w, https://substackcdn.com/image/fetch/$s_!TG2c!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TG2c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png" width="1024" height="502" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:502,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!TG2c!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 424w, https://substackcdn.com/image/fetch/$s_!TG2c!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 848w, https://substackcdn.com/image/fetch/$s_!TG2c!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.png 1272w, https://substackcdn.com/image/fetch/$s_!TG2c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fad887d66-8128-40fd-b5f3-cb7f39146739_1024x502.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></figure></div><h4>How we use a central protobuf schema to make our data pipeline less&nbsp;chaotic</h4><p>If I told you one of the most popular TV Shows in Sweden is about following the moose as they travel, for 21 days, you might say:<br>&#8202;&#8212;<em>&#8202;Stop it with the stereotypes! <br></em>or&nbsp;:<br>&#8212; <em>Ismail, go home and stop experimenting with psychedelics</em></p><p>I promise, this TV show is the real deal and it&#8217;s only 21 days&nbsp;long.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1gDF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1gDF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 424w, https://substackcdn.com/image/fetch/$s_!1gDF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 848w, https://substackcdn.com/image/fetch/$s_!1gDF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 1272w, https://substackcdn.com/image/fetch/$s_!1gDF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1gDF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png" width="1024" height="359" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:359,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!1gDF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 424w, https://substackcdn.com/image/fetch/$s_!1gDF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 848w, https://substackcdn.com/image/fetch/$s_!1gDF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 1272w, https://substackcdn.com/image/fetch/$s_!1gDF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddecc4e9-485d-484e-8ce6-f4703386b596_1024x359.png 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">Day 5 of the moose walk (&#8220;den stora &#228;lg vandringen&#8221;) and the moose are indeed&nbsp;walking</figcaption></figure></div><p>The TV Show &#8220;<em>den stora &#228;lg vandringen&#8221; </em>(which translates to<em> &#8220;the great moose walk&#8221;</em>)<em> </em>is a type of TV Show known as <em>slow TV. </em>This trend started in the neighboring lovely country of Norway (at&nbsp;NRK).</p><p>This TV show is 21 days long and it was streamed live on SVTs (Swedish Television&#8217;s) streaming service SVT&nbsp;Play.</p><p><em><strong>So why collect data then?<br></strong></em> It turns out filming the moose is not the only thing that SVT does and <em>SVT Play</em> is just one of the services at SVT. These services range from streaming to delivering news in addition to games and services for children and more. The point is, those apps make different types of content available (news articles, movies, TV series etc.) on different platforms including web, iOS, Android and smart&nbsp;TVs.</p><p>So a little more than two years ago, a project for data collection at SVT got started. This was an effort to aid decision making in the multiple products of SVT (that used to rely on third-party services such as google analytics).</p><p>Of course, the data is not what makes or breaks the products, nor the shows, movies or news articles. It is there to verify assumptions, to understand the users better and to support the decision&nbsp;making.</p><p>As one can see, the diversity of SVTs services and the platforms on which they run adds multiple challenges to the collection of&nbsp;data.</p><h3><strong>Too long; didn&#8217;t&nbsp;read?</strong></h3><p><em><a href="https://www.youtube.com/watch?v=ZouUbWt5tug">If you prefer watching this as a video feel free to head over&nbsp;here</a></em><a href="https://www.youtube.com/watch?v=ZouUbWt5tug">.</a></p><blockquote><p>While there are many things to talk about when it comes to the collection and analysis of data, this post will focus on: <br>&#8212; A very brief <strong>intro to how we collect data</strong> at SVT.<br>&#8212; The chaos that can result from the changes in the business rules.<br>&#8212;How we use a <strong>central schema</strong> (with Protobuf) <strong>to define the data we collect and propagate this definition</strong> in the whole pipeline (from collection to storage).<br>&#8202;&#8212;&#8202;Some of <strong>the issues we encountered</strong> with that&nbsp;choice.</p></blockquote><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.ismail.bio/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>Experiments</em> is a reader-supported publication. To receive new posts and support my work, consider becoming a subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3><strong>A Brief on how we collect data at&nbsp;SVT</strong></h3><p>Let&#8217;s say you&#8217;re a news editor, and you want to see how your articles perform. How can we collect data about&nbsp;that?</p><p>For example, you would want to know: <em>how many users read an article?</em> We cannot know for sure if a user actually reads the article, but what we can do is estimate it from what we can collect such as: a <em>mouse click</em> on the article or a <em>mouse scroll</em> inside the&nbsp;article.</p><p>These things that we can collect are what we call &#8220;<em><strong>Events&#8221;</strong>.</em> Other example events for other products can&nbsp;be:</p><ul><li><p>A <em>video start</em> or a <em>video pause </em>in the video&nbsp;player.</p></li><li><p>A <em>search query </em>in a search&nbsp;bar.</p></li><li><p>Or other events for collecting video player telemetry information.</p></li></ul><blockquote><p>An <strong>event </strong>is an action that happened on the client application side, for which the corresponding information can be collected (for example: a click or a video&nbsp;start)</p></blockquote><p>These events are just observations, and from them we should be able to either calculate or approximate our metrics (an example of a metric that cannot be calculated exactly is the <em>percentage watched of a video</em> because we simply do not know if the user is actually watching)</p><p>So we send those events. We ingest them into our pipeline (more details later). We store them in a table. We process and analyze them and then we present them to the users of our solution.</p><p>So the event will go&nbsp;through:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dM_e!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dM_e!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 424w, https://substackcdn.com/image/fetch/$s_!dM_e!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 848w, https://substackcdn.com/image/fetch/$s_!dM_e!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 1272w, https://substackcdn.com/image/fetch/$s_!dM_e!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!dM_e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png" width="1024" height="280" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:280,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!dM_e!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 424w, https://substackcdn.com/image/fetch/$s_!dM_e!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 848w, https://substackcdn.com/image/fetch/$s_!dM_e!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.png 1272w, https://substackcdn.com/image/fetch/$s_!dM_e!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2063015-e9e6-480e-8ab7-5abcaf3b20b5_1024x280.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></figure></div><ul><li><p><em><strong>collection:</strong></em> on the user-facing application side. For this part, in our case, we built SDKs (mainly for iOS, Android, Web and smart TVs) that will collect events such as clicks and send them to an API, which brings us to the next&nbsp;part.</p></li><li><p><em><strong>ingestion:</strong></em> when the API gets the previous event it publishes it to a message queue. In our case, we are currently using <a href="https://cloud.google.com/pubsub/docs/overview">Pub/Sub on the google cloud platform</a> (GCP). We have creatively named the previous API: the <em><strong>event&nbsp;API</strong></em>.</p></li><li><p><em><strong>storage:</strong></em> a service gets the previous event from Pub/Sub, checks the validity of its content, then stores it in a table (a BigQuery table in our case). We have called this service <em><strong>judge-judi</strong></em>.</p></li><li><p><em><strong>analysis:</strong></em> mostly just a bunch of&nbsp;ETL</p></li><li><p><em><strong>presentation:</strong></em> at this stage, we can show a dashboard to the right person with the right&nbsp;metric.</p></li></ul><p>For the purpose of this post, we will only focus on the <em>collect&#8202;&#8212;&#8202;ingest&#8202;&#8212;&#8202;store</em> parts of the previous pipeline.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!26Fs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!26Fs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 424w, https://substackcdn.com/image/fetch/$s_!26Fs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 848w, https://substackcdn.com/image/fetch/$s_!26Fs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 1272w, https://substackcdn.com/image/fetch/$s_!26Fs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!26Fs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png" width="1024" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!26Fs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 424w, https://substackcdn.com/image/fetch/$s_!26Fs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 848w, https://substackcdn.com/image/fetch/$s_!26Fs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.png 1272w, https://substackcdn.com/image/fetch/$s_!26Fs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F343a5f89-0b34-42f3-90d1-a8e9c89a12c4_1024x374.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></figure></div><p>To keep things simple, we can assume that we send one event at a time from the client application (In reality, those events are gathered by the client application and sent together in a sequence of&nbsp;events)</p><p>So, with all this in mind, where can problems&nbsp;happen?</p><h3>The need for ONE (versioned) definition of the event&nbsp;data</h3><p>From what we&#8217;ve talked about in the previous section, here&#8217;s what the life of an event looks like from collection to storage:<br>&#8202;&#8212;&#8202;First, we send the event from an app (through our SDK) to the Event API.<br>&#8202;&#8212;&#8202;The Event API then adds it to the queue for it to be processed later.<br>&#8202;&#8212;&#8202;And then on the right, is an accurate picture of <em>judge-judi</em> (the service described in the ingestion part above) performing its duty of pulling and storing valid events in the&nbsp;table.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vgah!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vgah!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 424w, https://substackcdn.com/image/fetch/$s_!Vgah!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 848w, https://substackcdn.com/image/fetch/$s_!Vgah!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 1272w, https://substackcdn.com/image/fetch/$s_!Vgah!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vgah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png" width="1024" height="437" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:437,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Vgah!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 424w, https://substackcdn.com/image/fetch/$s_!Vgah!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 848w, https://substackcdn.com/image/fetch/$s_!Vgah!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.png 1272w, https://substackcdn.com/image/fetch/$s_!Vgah!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd82f508f-26bd-4015-9dc5-f18cc6295ccd_1024x437.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">on the right an accurate picture of <strong>judge-judi </strong>performing its&nbsp;duty</figcaption></figure></div><p>The first problem is that all parts of the pipeline, from collection to storage, have to agree on what the definition of an event&nbsp;is.</p><h4><strong>The first problem: consistency</strong></h4><p>Let&#8217;s assume that the event looks something like:</p><pre><code>{
    'user_id':   '00000000',
    'content_type': 'video',
    'event_type': 'video_start',    
}</code></pre><p>Given the event above. What if one of our products ends up sending an event by naming the type <em>eventType </em>instead of <em>event_type?</em></p><pre><code>{
    'user_id':   '00000000',
    'content_type': 'video',
    'eventType': 'video_start',    
}</code></pre><p>When this event reaches the validation stage at <em>judge-judi. </em>The service<em> </em>is expecting a field <em>event_type </em>it will just conclude that the field is not&nbsp;there.</p><p>So the first problem is <em><strong>having all parts of the pipeline agree on the definition of the&nbsp;data</strong></em>.</p><p>We also have a multitude of products in SVT (svtplay, news etc.) and different platforms (web, iOS, Android etc.) it would be hard to make sure that the SDKs are always consistent.</p><h4><strong>The second problem: Murphy&#8217;s law of data engineering</strong></h4><p>Which states that: &#8220;<em>If the data schema can change, the data schema will change</em>.&#8221; Now, Murphy did not necessarily say that. <br>Well, he never actually did, but I&#8217;m sure he would&nbsp;agree.</p><p>The business rules and goals change more often than teenagers&#8217; relationships. We should expect, as a result, that the definition of the event will change. And it will change often. New fields will be added, old fields will be removed, others merged together, and the list goes on and&nbsp;on.</p><p>These modifications put schemas, and therefore the definition of an event, in a state of perpetual change. Each change will require adjustment to the pipeline. <em><strong>We do not want these recurring changes in the definition of the data to break the whole (or part of) the pipeline</strong></em>. Ideally, we would want to preserve backward and forward compatibility whenever possible.</p><h4>And then problems specific to&nbsp;JSON</h4><ul><li><p>The type of a field in JSON is unclear and errors can happen. It would be preferable if we can provide guarantees of what the event structure to be expected&nbsp;is.</p></li><li><p>Because we have different platforms, we are using different programming languages. This means that the JSON body can differ depending on the programming language and libraries used.</p></li><li><p>Long serialization overhead on the Event API&#8217;s side with the use of JSON. Although I currently do not have the &#8220;data&#8221; to prove it, it is easy to see that the schema is sent with every&nbsp;event.</p></li></ul><p>But since we have control over the applications and have control over the schema definition how can we make use of&nbsp;that?</p><h3>The solution: centralizing the definition of an event with&nbsp;Protobuf</h3><p>One way of tackling the issues above is to do the following:</p><ul><li><p>One repository where the definition of an event, which we will call the <em><strong>Event Model</strong></em>, is kept (we just keep it in a repository on&nbsp;Gitlab).</p></li><li><p>This <em>event model </em>is versioned.</p></li><li><p>Every version of the <em>event model</em> is then propagated across all the elements of the pipeline. For example, the web SDK will have access to an event model library and every new version in the event model repository will correspond to a new version in the library. This version should be the same for all platforms.</p></li><li><p>We will preferably use a language-neutral definition for the <em>event model</em>&#8217;s definition that can enable us to serialize an event on the SDKs and then deserialize it on the side of <em>judge-judi</em>.</p></li><li><p>Preferably adding or removing fields from the <em>event model </em>should not break backward/forward compatibility.</p></li></ul><p>To make a choice we tried both Avro and Protobuf. While there are many choices when it comes to defining the schema, to have a definition that supports all of the languages and provides a &#8220;good enough&#8221; serialization: Protobuf was the tool of&nbsp;choice.</p><h4><em><strong>What is protobuf and how does it&nbsp;work?</strong></em></h4><p>Protocol buffers are a language-neutral, platform-neutral, extensible way of serializing structured data. At least that&#8217;s what they&#8217;re supposed to&nbsp;be.</p><p>We will not go too deeply in how protocol buffers work but here are the&nbsp;basics.</p><p>Let&#8217;s say Alice wants to send a letter message to Bob that would look like this in&nbsp;JSON:</p><pre><code>{
  'firstName': 'Alice',
  'lastName': 'Alice',
  'email': 'alice@alice.alice',
  'content': 'Hi Bob, it's Alice'
}</code></pre><p>To do so, in protobuf, Alice and Bob would have to agree on a message schema. This schema can look something like&nbsp;this:</p><pre><code>message Letter{
  required string firstName = 1;
  required string lastName = 2;
  optional string email = 3;
  required string content = 4;
}</code></pre><p>This letter schema will be stored in a&nbsp;<em>.proto</em>&nbsp;file.</p><p>Alice and Bob can then convert this message to C++ or Javascript code or whatever language they&#8217;re into using the proto compiler.</p><p>Using the generated code Alice will serialize the message. For example, if Alice is using C++ her code might look something like&nbsp;this:</p><pre><code>Letter letter;
letter.set_first_name("Alice");</code></pre><p>Alice can now send the letter to Bob. A series of bytes are sent over the network. Bob knows the Letter schema, Bob can deserialize the letter&nbsp;message.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cv-K!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cv-K!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 424w, https://substackcdn.com/image/fetch/$s_!cv-K!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 848w, https://substackcdn.com/image/fetch/$s_!cv-K!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 1272w, https://substackcdn.com/image/fetch/$s_!cv-K!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cv-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png" width="1024" height="296" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:296,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!cv-K!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 424w, https://substackcdn.com/image/fetch/$s_!cv-K!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 848w, https://substackcdn.com/image/fetch/$s_!cv-K!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.png 1272w, https://substackcdn.com/image/fetch/$s_!cv-K!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2773bc1-760d-49ee-a213-38dd90577bdc_1024x296.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></figure></div><h4>So how can we use it for the solution&nbsp;above?</h4><p>Step 1&#8202;&#8212;&#8202;In our case, the <em>event model</em> repository hosts the&nbsp;.<em>proto</em>&nbsp;file.</p><p>Step 2&#8202;&#8212;&#8202;This repository propagates code with the same for the rest of the pipeline through pushing libraries. This repository also creates the table on BigQuery (as we will mention in the next section, this part has changed).</p><p>Step 3&#8202;&#8212;&#8202;The service <em>judge-judi</em> will also fetch the latest Go version of the <em>event model </em>because it will need it later. And, just like Alice, through the SDKs we can fetch the latest version of this <em>event model </em>on the client apps to serialize the events that we will send. The app will serialize the event and send it to the&nbsp;API.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SCOs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SCOs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 424w, https://substackcdn.com/image/fetch/$s_!SCOs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 848w, https://substackcdn.com/image/fetch/$s_!SCOs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 1272w, https://substackcdn.com/image/fetch/$s_!SCOs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SCOs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png" width="1024" height="270" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:270,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!SCOs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 424w, https://substackcdn.com/image/fetch/$s_!SCOs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 848w, https://substackcdn.com/image/fetch/$s_!SCOs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.png 1272w, https://substackcdn.com/image/fetch/$s_!SCOs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6b766e3-aa49-4707-9af0-62dbd74278e0_1024x270.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></figure></div><p>Step 4&#8202;&#8212;&#8202;We collect this event as it is, without deserializing it, and we publish it to the queue on&nbsp;Pub/Sub.</p><p>Step 5&#8202;&#8212;&#8202;The service <em>judge-judi </em>pulls the events and deserializes them.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4kjA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4kjA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 424w, https://substackcdn.com/image/fetch/$s_!4kjA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 848w, https://substackcdn.com/image/fetch/$s_!4kjA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 1272w, https://substackcdn.com/image/fetch/$s_!4kjA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4kjA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png" width="1024" height="223" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:223,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!4kjA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 424w, https://substackcdn.com/image/fetch/$s_!4kjA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 848w, https://substackcdn.com/image/fetch/$s_!4kjA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 1272w, https://substackcdn.com/image/fetch/$s_!4kjA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0e56d587-31e7-4c94-9bee-8f3877851acc_1024x223.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!evtv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!evtv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 424w, https://substackcdn.com/image/fetch/$s_!evtv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 848w, https://substackcdn.com/image/fetch/$s_!evtv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 1272w, https://substackcdn.com/image/fetch/$s_!evtv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!evtv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png" width="1024" height="374" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:374,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!evtv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 424w, https://substackcdn.com/image/fetch/$s_!evtv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 848w, https://substackcdn.com/image/fetch/$s_!evtv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.png 1272w, https://substackcdn.com/image/fetch/$s_!evtv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4c73939-48f1-43f1-b3ef-074d9822d3f8_1024x374.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></figure></div><blockquote><p>It&#8217;s all good now, you drop the mic, walk out of the room, head high&#8230;until&#8230;stuff happens. You realize that the reality is as far from your expectations as your tongue is from touching your nose&#8230; So close, and yet so far (don&#8217;t try that, you&#8217;ll look ridiculous)</p></blockquote><h3><strong>Expectations vs.&nbsp;reality</strong></h3><h4>The myth of language agnosticism</h4><p>When the mechanism of protocol buffers is supposed to be language-agnostic and platform agnostic. In practice, this does not seem to be the&nbsp;case.</p><p>For example, some platforms had encoding that was not consistent with the deserializer. We use <a href="https://github.com/gogo/protobuf">the gogofaster</a> compiler for Go which is a third party implementation that leverages type-specific marshaling code for extra performance. But we use it mainly to provide more canonical Go structures, less typing and to not end up with the<a href="https://github.com/golang/protobuf/issues/276"> infamous </a><em><a href="https://github.com/golang/protobuf/issues/276">xxx</a></em><a href="https://github.com/golang/protobuf/issues/276">&nbsp;fields</a>.</p><h4>The myth of backward and forward compatibility</h4><p>Let&#8217;s say a field gets added, and a field gets removed from the schema. If the service <em>judge-judi</em> is using the latest version of the <em>event model</em>, it will still be able to deserialize the data with no problem even if the client application does not update to the latest version. But this is only true for simple changes. For example, this would not hold if we change the nesting of some&nbsp;fields.</p><p>Moreover, although we avoided talking about the analysis that comes after the storage part earlier, a new event model would mean that all the jobs and tables that depend on it will change. For this reason, we separated the version of the event model from the version of the event table on BigQuery so that the table would change less often. We then provide a mapping on <em>judge-judi </em>from the event model to the table schema before storing the&nbsp;events.</p><p>Thus, we identify mainly three types of changes in the <em>event model</em>&#8217;s<em> </em>schema and act accordingly:<br>&#8202;&#8212;&#8202;<em>Non-breaking changes</em>: that happen regularly. These are the changes that do not break backward compatibility. This can be the deletion or addition of fields in the protobuf schema. <br>&#8202;&#8212;&#8202;<em>Breaking changes that do not require a change of the BigQuery table</em>: that rarely happen, and should be minimized. When these happen judge-<em>judi</em> just changes the mapping between the event and the table.<em><br>&#8202;&#8212;&#8202;Breaking changes that require a change of the BigQuery table</em>: very rare and have yet to happen but they could (thus they will). Since those are rare and we cannot know what these will be like we&#8217;ll tackle them on a case by case&nbsp;basis.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">If you found this useful please give it a heart and share it. This is very easy and means a lot to me.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><h3>Conclusion</h3><p>The reality of data collection and analysis is very different from the mathematical fantasies of well-defined axioms and controllable assertions.</p><p>Coming from a scientific background, we have a tendency to want to keep the pipeline clean. And that&#8217;s good. However, chaos in data engineering is not just real but probably unavoidable. And it is one of the reasons why we should try to iterate slowly, and add tests and data quality checks when possible. It is also why keeping a central definition of the data in one place can be very&nbsp;helpful.</p><p>Protocol buffers are one way of defining a data model that seems to improve serialization overhead and be almost language agnostic. If you already know what the data schema should look like, protobuf is good at managing additions and deletions of fields, although one has to be careful as always. More complex changes will require more thoughtfulness.</p><p><strong>Hope you found something useful reading this&#8230; Have a beautiful day!</strong></p><p>If you have any comments or suggestions would love to hear from&nbsp;you.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic/comments&quot;,&quot;text&quot;:&quot;Leave a comment&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.ismail.bio/p/make-your-data-pipeline-less-chaotic/comments"><span>Leave a comment</span></a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.ismail.bio/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>Experiments</em> is a reader-supported publication. To receive new posts and support my work, consider becoming a free or paid subscriber.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p><a href="https://medium.com/the-svt-tech-blog/make-your-data-pipeline-less-chaotic-by-one-versioned-definition-of-data-5ddb92c0c6f6">Make your data pipeline less chaotic by one versioned definition of data</a> was originally published in <a href="https://medium.com/the-svt-tech-blog">The SVT Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded></item></channel></rss>