<?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[BitNirmata]]></title><description><![CDATA[This substack covers topics related to the cloud environment, offering tips and tricks for optimizing its use, and also delves into some aspects of crypto and trading.]]></description><link>https://bitnirmata.com</link><image><url>https://substackcdn.com/image/fetch/$s_!y_lq!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd56313b2-18da-4be7-8162-563d73e60620_371x371.png</url><title>BitNirmata</title><link>https://bitnirmata.com</link></image><generator>Substack</generator><lastBuildDate>Mon, 06 Apr 2026 14:57:00 GMT</lastBuildDate><atom:link href="https://bitnirmata.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Alen Krmelj]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[bitnirmata@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[bitnirmata@substack.com]]></itunes:email><itunes:name><![CDATA[Alen Krmelj]]></itunes:name></itunes:owner><itunes:author><![CDATA[Alen Krmelj]]></itunes:author><googleplay:owner><![CDATA[bitnirmata@substack.com]]></googleplay:owner><googleplay:email><![CDATA[bitnirmata@substack.com]]></googleplay:email><googleplay:author><![CDATA[Alen Krmelj]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Overcoming impostor syndrome]]></title><description><![CDATA[A brief article exploring impostor syndrome, its meaning, and strategies that are effective for overcoming it, especially when starting a job at a large company filled with highly talented people.]]></description><link>https://bitnirmata.com/p/overcoming-impostor-syndrome</link><guid isPermaLink="false">https://bitnirmata.com/p/overcoming-impostor-syndrome</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Thu, 30 Jan 2025 08:00:43 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d21407c8-1d4d-44db-b657-78f451d6f92a_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Definition of impostor syndrome</h2><p>Impostor syndrome is a psychological pattern in which an individual doubts their skills, accomplishments, or knowledge and fears being exposed as a fraud, despite evidence of their competence. It&#8217;s common among high achievers, but anyone can experience it. Symptoms include feeling like you&#8217;ve &#8220;just been lucky,&#8221; downplaying your achievements and constantly comparing yourself to others.</p><h2>My observations in years of hiring</h2><p>As team lead I have interviewed hundreds of engineers. For junior and senior roles. Over time, I noticed that even when I hired top engineers, they often struggled right from the start. Why? Would you ask. Answer is simple. Many of high achievers come from smaller companies or teams that didn&#8217;t have a lot of high skilled talent. They begin to feel overwhelmed. These people used to be go-to people at their previous job and had everything under control. This changed now and their bubble burst a bit. The realization, that they are not the ones smartest can be tough. They tend to self doubt and struggle to find their place where they would feel they are adding value.</p><h2>Overcoming it effectively</h2><p>Let&#8217;s have a look at some of the ways to overcome this situation, since the longer it lasts, the longer you will be struggling with self doubt, bad self image and will in general be unhappy at work. Keep in mind these are guidelines and not exact answers to the issue. Main thing we want to achieve is, to get you to believe, that you actually are valuable part of the team and company. Unless you truly believe it, you can&#8217;t move forward from it.</p><ul><li><p><strong>Recognise it</strong><br>It&#8217;s important to acknowledge that it&#8217;s happening to you and understanding that this is just a temporary feeling. It is not long lived and as you become more comfortable in new environment, it will begin to fade. Understand you were hired because a senior hiring engineer or team lead saw a potential in you. Trust the process! It&#8217;s going to be all right.</p></li><li><p><strong>Finding your strength</strong><br>Focus on finding that thing that you are best at and can really shine if you are given opportunity to show your skills. It&#8217;s important to get rid of the feeling that you should know it all, and that you should be best at everything. In large companies it does not work. There is just too much code, infrastructure and technologies used, for you to be able to do that.</p></li><li><p><strong>Let your skills shine</strong></p><p>Take time for solving the task that you were given. Research, study, learn. Try to do absolutely best solution that you can think of and write reasoning why you chose something the way you did. This will give you confidence that it&#8217;s not a rash decision and that you put thought into it. It will also be ground for senior engineer to look at, read it, and understand your thought process. It will generally lead to much better responses than if you rush and prioritize speed over quality.</p></li><li><p><strong>Don&#8217;t fear asking for feedback</strong></p><p>Many times when you are in self doubt position, it&#8217;s best to ask others what do they think of your solution or code that you produced. Get constructive feedback and take it as an opportunity to learn. Choose senior people for such code reviews, or questions about correctness of your approach.</p></li><li><p><strong>Set realistic goals</strong></p><p>Perfectionism often fuels impostor syndrome. Strive for excellence but understand that mistakes and learning curves are normal. It will take time to get there and won&#8217;t happen over night.</p></li><li><p><strong>Learn, learn, learn</strong></p><p>If you notice that you are &#8220;behind&#8221; with knowledge, you can catch up faster, if you do a research on technologies that you think you are lacking knowledge of. Ask your team lead to suggest you good resources you can look up, to learn things in depth. It&#8217;s really a boost to self confidence if you get recognition by passing an official certification. So, try to do some certificate. Not because you need it for a job, but because of yourself and self confidence.</p></li></ul><h2>Final words</h2><p>In general, the more positive feedback you will get, the more comfortable you will feel. Sense of achievement most effectively helps with overcoming impostor syndrome. Most of overachievers are prone to downplaying their achievements and therefore it takes longer for them to really and truely believe they are valuable part of the team and company. </p><p>Keep that in mind and I hope this post helped you at least understand the situation. Good luck and don&#8217;t worry too much about it. In time things will get better!</p><p></p>]]></content:encoded></item><item><title><![CDATA[Pinpointing Exchange's Location]]></title><description><![CDATA[This article provides simple steps for non-engineers to identify the location of the exchange they are trading on. The methodology is written in a general way, making it adaptable for any exchange.]]></description><link>https://bitnirmata.com/p/pinpointing-your-exchanges-location</link><guid isPermaLink="false">https://bitnirmata.com/p/pinpointing-your-exchanges-location</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Wed, 04 Dec 2024 10:01:20 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/5ad3b19d-0265-4d81-ac9e-65ac71758c23_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><p>Traditional and crypto exchanges often times obscure the location of their infrastructure. They use Content Delivery Networks to mask their true locations. CDN also helps them protect against DDoS attacks, and mitigate other security threats. Keeping the details of their servers and IP addresses private is in their best interest, and such information is typically shared only with selected market makers that they work with. This basically means you, as a retail customer, can not get to this information.</p><p>However, there is a way to pinpoint the exact region of an exchange's infrastructure, if you know an exchange&#8217;s cloud provider. (90% of crypto exchanges for example are hosted on them) In this article, we&#8217;ll explore one such crypto exchange and try to figure out region in which to deploy your trading or arbitrage bots, ensuring the lowest possible latency to the crypto exchange.</p><h2>Methodology</h2><p>First of all, before we begin, we have to think a little bit how to tackle this problem and here is how my train of thought went:</p><ul><li><p>Find out what cloud provider is crypto exchange using. Most of them post this publicly and it&#8217;s not really a secret.</p></li><li><p>We need to get response from non heavily cached endpoint in order to get initial latency to the exchange. It would be best to choose un-authed endpoint, so we can geo query it.</p></li><li><p>Geo query the endpoint, get lowest latency node and find a region on a cloud provider, that this node is closest to.</p></li><li><p>We can go further and benchmark from which availability zone we get lowest time on limit order endpoint response. Usually matching engine runs in one availability zone with hot standby in another. Unfortunately if exchange is doing loadbalancing that introduces additional network hops, knowing exact AZ of matching engine doesn&#8217;t matter anymore.</p></li></ul><blockquote><p>Cross AZ network hop in AWS usually adds 1ms and can vary up to 2ms of additional latency.</p></blockquote><h2>Tracing AWS region of an exchange</h2><h4>Step 1</h4><p>Looking at API reference of the exchange that we will try to pinpoint shows that server time endpoint is accessible here:</p><pre><code><code>GET /api/v3/time</code></code></pre><h4>Step 2</h4><p>Lets open up: <a href="https://www.site24x7.com/tools/check-website-availability.html">https://www.site24x7.com/tools/check-website-availability.html </a>or any similar website where you can check response times of a website from different parts of the world and fire it against our server time url:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a_Kt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a_Kt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 424w, https://substackcdn.com/image/fetch/$s_!a_Kt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 848w, https://substackcdn.com/image/fetch/$s_!a_Kt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 1272w, https://substackcdn.com/image/fetch/$s_!a_Kt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a_Kt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png" width="728" height="357.492252681764" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:412,&quot;width&quot;:839,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:23898,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!a_Kt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 424w, https://substackcdn.com/image/fetch/$s_!a_Kt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 848w, https://substackcdn.com/image/fetch/$s_!a_Kt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.png 1272w, https://substackcdn.com/image/fetch/$s_!a_Kt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf18fcef-cca5-4ebe-b8ba-c2b885221727_839x412.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><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XJ0J!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XJ0J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 424w, https://substackcdn.com/image/fetch/$s_!XJ0J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 848w, https://substackcdn.com/image/fetch/$s_!XJ0J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 1272w, https://substackcdn.com/image/fetch/$s_!XJ0J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XJ0J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png" width="1020" height="517" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:517,&quot;width&quot;:1020,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:80762,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!XJ0J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 424w, https://substackcdn.com/image/fetch/$s_!XJ0J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 848w, https://substackcdn.com/image/fetch/$s_!XJ0J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.png 1272w, https://substackcdn.com/image/fetch/$s_!XJ0J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f53e327-c4db-49c7-8f42-57b00e7d3629_1020x517.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>We can clearly see that the total response time seems to be fastest in <strong>Singapore</strong>, which coresponds to the AWS region <strong>ap-southeast-1</strong>.</p><div class="pullquote"><p>Ignore the failed regions, since that is called geofencing. This means, particularly crypto exchanges need to geofence and block access to their website from specific countries, usually due to regulatory reasons. </p></div><p><strong>Step 3</strong></p><p>Benchmark limit order endpoint and response times from each availability zone in that AWS region. Unfortunately particular exchange didn&#8217;t show much better performance from single AZ, but we could pinpoint that connection times from <strong>apse1-az2 </strong>are a little faster in average of ~1-2ms.</p><h2>Summary</h2><p>Knowing in what region exchange hosts its infrastructure is mostly important for automated trading. An example of those that are latency sensitive would be market makers. Beyond region, pinpointing actual AZ usually does not result in much better performance in speed of setting limit orders. Some exchanges do use smart routing on the ingress though and route requests directly to the matching engine, so testing limit order endpoint from each AZ still makes sense to at least try, maybe you get lucky.</p>]]></content:encoded></item><item><title><![CDATA[Sorry Server: What it is and why you should use it]]></title><description><![CDATA[A quick look at what Sorry Server is and some key lessons from using it in production that might change how you see it and hopefully convince you to implement it in your environment.]]></description><link>https://bitnirmata.com/p/sorry-server-what-it-is-and-why-you</link><guid isPermaLink="false">https://bitnirmata.com/p/sorry-server-what-it-is-and-why-you</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Wed, 20 Nov 2024 10:00:56 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/662663e3-95fd-4e36-aaa3-05607068871a_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>What is Sorry Server?</h2><p>"Sorry Server" is a term often used informally in web development. It typically refers to a server that serves a fallback page in order to handle errors gracefully and inform users when something goes wrong with the service. In most cases the content served is static in order to be as lightweight on the resources and fast to serve as possible.</p><h2>Common use cases</h2><ul><li><p><strong>Rate limiting</strong></p><p>In this case you would show your clients a sorry page when you are experiencing higher load or notice a larger queue in your service and would like to rate limit the intake of the requests.</p></li><li><p><strong>Maintenance Pages</strong></p><p>One of standard use cases is also using sorry server to inform clients that currently a maintenance is happening.</p></li><li><p><strong>Graceful Degradation:</strong></p><p>When your service is experiencing increased load and cannot keep up with the intake of the traffic, you would use sorry server to only be shown on certain parts of your system. Meaning, it would limit the functionality, but wouldn&#8217;t out right cut everyone out.</p></li><li><p><strong>Error handling</strong></p><p>When your servers detect an error, let there be code issue or another resource issue, they could instead of showing an error, rather forward the user to the sorry server.</p></li></ul><h2>Lessons from production</h2><p>There are takeaways from production where sorry server saved us:</p><ul><li><p><strong>SPOF service inplace upgrades</strong></p><p>Sometimes, you have to patch or upgrade a SPOF service, that doesn&#8217;t have additional server that you can fallback to, during upgrade. Running commands like<strong> apt</strong> <strong>upgrade</strong> or <strong>do-release-upgrade</strong> can lead to very unexpected behaviour of the server. For example, a PHP webserver for example could unload module for PHP in Apache during the upgrade and restart the httpd server. This leads to exposing raw PHP files of all of the clients hosting websites on that server for a period of time. This is something that happened lately with ubuntu server. Perfect example, where you should put sorry server up and make sure that for that period of time, nothing connects to the server being upgraded.</p></li><li><p><strong>Inplace updating your code</strong></p><p>Let&#8217;s say you are hosting your code on some webhosting server provider. Developer would usually just upload files via FTP or rsync. Unfortunately, that is not immutable deploy. Meaning, for the time in between when you start syncing your new files over the old ones and time they finish transferring, there can come to unprecedented errors, even wrong execution of code, because clients are all the time executing whatever is synced at the time. This is something we saw a lot, when I was working in advertising company and decided to go with immutable squashfs images of code, that would just be remounted (there was no Docker at the time). This kind of deployment of new code is also a case for a sorry server, to put it in front of your server while you are updating files and avoid the problems.</p></li><li><p><strong>Handling of all types of responses</strong></p><p>As most of crypto exchanges, we serve some html websites and on certain endpoints we also offer API access that is returned as JSON data. This means, putting a standard sorry server that just returns html output, does not cut it. We have to think about our clients. What happens with the code that connects to API service and tries to JSON load the input, but instead of JSON, gets html? That leads to awful errors. This is why we modify endpoints that we serve on our sorry serve, swapping from html output to JSON on appropriate paths and returning valid JSON with error message that explains that we are in maintenance mode.</p></li><li><p><strong>CDN implementation</strong></p><p>For actual exchange infrastructure, we have our own sorry servers of course, but for certain third party software that we are running, having CDN serve a maintenance page is just fine. That is also an option for all of you, that don&#8217;t actually have several servers and loadbalancers, to utilize.</p></li><li><p><strong>Serve static content</strong></p><p>A very tricky thing happened to us back in the day, when we were trying to be very smart about our maintenance sorry server page and actually served dynamic content on it. We tried to do it lightweight, but it was also connecting to database. The real problem happened, that we didn&#8217;t think about all edge cases. One of those would be, providing favicon.ico file on it, because certain browsers like FireFox require it. That led to awful spam to the database, trying to get that file and ended up executing dynamic content. This doubled the requests that we would have to handle, one for favicon and one for website and of course that led to certain degradation of the database performance. So, keep these maintenance pages static without any logic on it.</p></li></ul><h2>Footnote</h2><p>Incorporating a "Sorry Server" isn't just a safety net, it's a strategy to enhance resilience and user satisfaction in production environments. In case you are not using it, hopefully above examples from production convinced you to at least have a look at it and maybe it&#8217;s really easy to add it into your procedure when doing maintenance.</p>]]></content:encoded></item><item><title><![CDATA[Impact of Indexes on MySQL Write Performance]]></title><description><![CDATA[This article benchmarks MySQL to show how different index types impact write performance on various columns, highlighting the best and worst column types for indexing efficiency.]]></description><link>https://bitnirmata.com/p/impact-of-indexes-on-mysql-write</link><guid isPermaLink="false">https://bitnirmata.com/p/impact-of-indexes-on-mysql-write</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 11 Nov 2024 09:01:03 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/2894bffa-39f8-49a5-881f-6f9207f71d1e_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><p>In our fast pace environment of crypto exchange, write speed to database plays important role. For example, every trade, transaction or even non executed order needs to be written somewhere and for some of these, we use AWS Aurora. If you worked on the field for some time, you know, there is never ending issue with developers requesting an index to this or that column in some table. Adding an index in MySQL does not go without penalty to write performance. Reason is, that because for every database insert, an index needs to be updated too. This means there is more work to do and therefore this impacts write performance.</p><p>This is nothing new, but what you might be wondering is, <strong>how much </strong>does it actually impact performance and which types of columns in MySQL are worse than the other and for how much?</p><p>That is the real question.</p><h2>Battle plan</h2><p>In order to answer some of these questions, I prepared a small benchmark on db.c5.large Aurora cluster. Nothing special about it, everything default, so in short, ACID compliant database.</p><p>Main thing that we want to do is:</p><ol><li><p>Create a table with multiple different types of columns</p></li><li><p>Pre-fill few million rows of random data</p></li><li><p>Do a SysBench insert benchmark, to see how everything performs without indexes</p></li><li><p>Add an index on a column</p></li><li><p>Repeat benchmark, to see how much that impacted the write performance</p></li><li><p>Rinse-repeat step 4 and 5 until all of the columns have index</p></li></ol><p>Of course having index on every column makes absolutely no sense from practical standpoint, but we are not trying to benchmark reads. Writes are what we are interested in and how types of indexes impact them.</p><h2>Actual setup</h2><ol><li><p>Table</p><blockquote><p>Note, few other types exist in MySQL, but from perspective of adding an index, it makes no sense to put index on for example &#8220;TEXT&#8221; type or something similar&#8230;</p></blockquote></li></ol><pre><code>CREATE TABLE benchmark_table (
    id INT AUTO_INCREMENT PRIMARY KEY,  -- Integer
    name VARCHAR(255),                  -- Variable-length string
    birthdate DATE,                     -- Date
    salary DECIMAL(10, 2),              -- Decimal for financial values
    is_active BOOLEAN,                  -- Boolean (True/False)
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Timestamp with auto-update
    rating FLOAT,                       -- Floating-point number
    visit_count BIGINT                  -- Large integer for counters
);</code></pre><ol start="2"><li><p>SysBench parameters</p></li></ol><pre><code>sysbench \
  --db-driver=mysql \
  --mysql-host=xxx \
  --mysql-user=xxx \
  --mysql-password=xxx \
  --mysql-db=benchmark \
  --report-interval=3 \
  --time=120 \
  --threads=150 \
  ./insert.lua run</code></pre><ol start="3"><li><p>Insert Lua script</p></li></ol><pre><code>function get_conn()
   drv = sysbench.sql.driver()
   return drv:connect()
end

function thread_init(thread_id)
  con = get_conn()
end

function random_string(length)
   local chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
   local str = ""
   for i = 1, length do
      local rand_index = math.random(#chars)
      str = str .. chars:sub(rand_index, rand_index)
   end
   return str
end

function random_date(start_year, end_year)
   local year = math.random(start_year, end_year)
   local month = math.random(1, 12)
   local day = math.random(1, 28) -- To avoid invalid dates
   return string.format("%04d-%02d-%02d", year, month, day)
end

function event(thread_id)
   local name = random_string(8)  -- Generate a random 8-character name
   local birthdate = random_date(1970, 2000)  -- Generate a random birthdate between 1970 and 2000
   local salary = math.random(30000, 100000) + math.random()  -- Generate a random salary with decimals
   local is_active = (math.random() &gt; 0.5) and "TRUE" or "FALSE"
   local rating = string.format("%.1f", math.random(10, 50) / 10)  -- Random rating between 1.0 and 5.0
   local visit_count = math.random(1, 500)  -- Random visit count

   local query = string.format("INSERT INTO benchmark_table (name, birthdate, salary, is_active, created_at, rating, visit_count) VALUES ('%s', '%s', %.2f, %s, NOW(), %s, %d)",
                               name, birthdate, salary, is_active, rating, visit_count)

   con:query(query)
end

function thread_done(thread_id)
  con:disconnect()
end</code></pre><ol start="4"><li><p>Indexes were added in this order:</p></li></ol><pre><code><code>1. CREATE INDEX idx_name ON benchmark_table (name);
2. CREATE INDEX idx_birthdate ON benchmark_table (birthdate);
3. CREATE INDEX idx_salary ON benchmark_table (salary);
4. CREATE INDEX idx_is_active ON benchmark_table (is_active);
5. CREATE INDEX idx_created_at ON benchmark_table (created_at);
6. CREATE INDEX idx_rating ON benchmark_table (rating);
7. CREATE INDEX idx_visit_count ON benchmark_table (visit_count);</code></code></pre><h2>Results</h2><blockquote><p>Keep in mind indexes are compounded. So, Visit_count_qps for example consists of all other columns having index, plus a visit_count.</p></blockquote><p>Queries per second - higher is better</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Aoih!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Aoih!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 424w, https://substackcdn.com/image/fetch/$s_!Aoih!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 848w, https://substackcdn.com/image/fetch/$s_!Aoih!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 1272w, https://substackcdn.com/image/fetch/$s_!Aoih!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Aoih!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png" width="728" height="451.4331658291457" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:617,&quot;width&quot;:995,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:174439,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!Aoih!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 424w, https://substackcdn.com/image/fetch/$s_!Aoih!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 848w, https://substackcdn.com/image/fetch/$s_!Aoih!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.png 1272w, https://substackcdn.com/image/fetch/$s_!Aoih!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F903dda36-e7d4-4fc8-9107-db62e2a027d8_995x617.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>Latency (ms) - less is better:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IMLY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IMLY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 424w, https://substackcdn.com/image/fetch/$s_!IMLY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 848w, https://substackcdn.com/image/fetch/$s_!IMLY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 1272w, https://substackcdn.com/image/fetch/$s_!IMLY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!IMLY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png" width="728" height="451.86206896551727" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:594,&quot;width&quot;:957,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:199675,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!IMLY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 424w, https://substackcdn.com/image/fetch/$s_!IMLY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 848w, https://substackcdn.com/image/fetch/$s_!IMLY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.png 1272w, https://substackcdn.com/image/fetch/$s_!IMLY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf8a0b0b-558c-45c0-8a0e-7076b698abc3_957x594.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>Since above graphs might be a bit noisy and hard to read, I also prepared drill-down of degradation of performance per column type added:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VKNE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VKNE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 424w, https://substackcdn.com/image/fetch/$s_!VKNE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 848w, https://substackcdn.com/image/fetch/$s_!VKNE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 1272w, https://substackcdn.com/image/fetch/$s_!VKNE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VKNE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png" width="671" height="299" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:299,&quot;width&quot;:671,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39283,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!VKNE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 424w, https://substackcdn.com/image/fetch/$s_!VKNE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 848w, https://substackcdn.com/image/fetch/$s_!VKNE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.png 1272w, https://substackcdn.com/image/fetch/$s_!VKNE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a0e96e-6e47-4437-9b03-cb8aad8685cc_671x299.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>And visual graph of above 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_!Cqt9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Cqt9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 424w, https://substackcdn.com/image/fetch/$s_!Cqt9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 848w, https://substackcdn.com/image/fetch/$s_!Cqt9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 1272w, https://substackcdn.com/image/fetch/$s_!Cqt9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Cqt9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png" width="910" height="555" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:555,&quot;width&quot;:910,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29118,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!Cqt9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 424w, https://substackcdn.com/image/fetch/$s_!Cqt9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 848w, https://substackcdn.com/image/fetch/$s_!Cqt9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.png 1272w, https://substackcdn.com/image/fetch/$s_!Cqt9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F77bda3f6-9aba-4fb2-88c5-7fb9a82b0641_910x555.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><h2>Summary</h2><p>Here it is, magic answer to your questions on how much degradation in writes can you expect per index type. As we can see some types are a little worse than the others, but in general, they all add certain penalty. Boolean being one of the best indexes and varchar being one of the worst column types you could choose to add index on. Keep in mind that with MySQL, adding an index also increases table/disk size, and by the rule of thumb, if you have more than 30% of additional disk claimed by indexes, you are probably abusing indexes too much and should rethink your strategy.</p>]]></content:encoded></item><item><title><![CDATA[Open Source APMs]]></title><description><![CDATA[Running proprietary APMs like AppDynamics or NewRelic at scale can become quite expensive. Let's explore open-source alternatives and try to find suitable replacement for them.]]></description><link>https://bitnirmata.com/p/open-source-apms-1-introduction</link><guid isPermaLink="false">https://bitnirmata.com/p/open-source-apms-1-introduction</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Tue, 22 Oct 2024 07:01:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a4addda3-8c84-47bd-ba04-e06d742d9b8b_908x849.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Proprietary APMs</h2><p>Just like monitoring and logging, tracing and profiling are also important in general observability of your running applications. Here come Application Performance Monitoring, or in short APM. Some of the leaders in this field are certaily AppDynamics, New Relic and Dynatrace.</p><h2>Cost problems</h2><p>As time passed, these APMs became very popular and many companies turned to them, when they needed to optimize or otherwise debug their applications. These proprietary APMs actually make sense when you need to monitor few servers, but running them on thousands of servers, things become very expensive&#8230;</p><h2>Open Source Alternatives</h2><p>I recently found a few open source APMs that aren&#8217;t that known, so I decided to add them alongside some of the de-facto standard ones and I&#8217;ll let you decide if you want to try them out.</p><ol><li><p><strong>Jaeger Tracing</strong> - <a href="https://www.jaegertracing.io">https://www.jaegertracing.io</a></p><p>Jaeger is an open-source application performance monitoring (APM) tool originally developed by Uber and later contributed to the Cloud Native Computing Foundation (CNCF). Jaeger is a distributed tracing system designed to troubleshoot microservices-based distributed systems. As its fast adoption by many companies, Jaeger is a solid option to evaluate if you're looking for an APM solution to replace some proprietary one.</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mIpn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mIpn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 424w, https://substackcdn.com/image/fetch/$s_!mIpn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 848w, https://substackcdn.com/image/fetch/$s_!mIpn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 1272w, https://substackcdn.com/image/fetch/$s_!mIpn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mIpn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png" width="728" height="359.1993793638479" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;normal&quot;,&quot;height&quot;:636,&quot;width&quot;:1289,&quot;resizeWidth&quot;:728,&quot;bytes&quot;:39507,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&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_!mIpn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 424w, https://substackcdn.com/image/fetch/$s_!mIpn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 848w, https://substackcdn.com/image/fetch/$s_!mIpn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.png 1272w, https://substackcdn.com/image/fetch/$s_!mIpn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2b1ac30a-a473-4457-8091-e31e7d474fe5_1289x636.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><ol start="2"><li><p><strong>Coroot</strong> - <a href="https://github.com/coroot/coroot">https://github.com/coroot/coroot</a></p></li></ol><p>Coroot is a monitoring platform for tracking performance of microservices and distributed applications, particularly in cloud-native environments. It prioritizes service-level objectives (SLOs), enabling teams to monitor application health from a service-oriented perspective, focusing on user experience and reliability instead of just basic metrics. Using eBPF, Coroot automatically collects detailed telemetry data, including metrics, logs, and traces. Integration with kubernetes is especially awesome and I was pretty impressed by it.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!y1jy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!y1jy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 424w, https://substackcdn.com/image/fetch/$s_!y1jy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 848w, https://substackcdn.com/image/fetch/$s_!y1jy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 1272w, https://substackcdn.com/image/fetch/$s_!y1jy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!y1jy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png" width="1024" height="565" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:565,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:171242,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!y1jy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 424w, https://substackcdn.com/image/fetch/$s_!y1jy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 848w, https://substackcdn.com/image/fetch/$s_!y1jy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.png 1272w, https://substackcdn.com/image/fetch/$s_!y1jy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb96dc6-3ed4-4a03-9e5c-acdfaee8b039_1024x565.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><ol start="3"><li><p><strong>SkyWalking</strong> - <a href="https://skywalking.apache.org/">https://skywalking.apache.org</a></p></li></ol><p>Application performance monitor tool for distributed systems, especially designed for microservices, cloud native and container-based (Kubernetes) architectures. Leveraging eBPF technology, Kubernetes Network Monitoring delivers granular insights into network traffic, topology, and TCP/HTTP metrics.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!giGx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!giGx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 424w, https://substackcdn.com/image/fetch/$s_!giGx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 848w, https://substackcdn.com/image/fetch/$s_!giGx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 1272w, https://substackcdn.com/image/fetch/$s_!giGx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!giGx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp" width="1192" height="536" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:536,&quot;width&quot;:1192,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39976,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&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_!giGx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 424w, https://substackcdn.com/image/fetch/$s_!giGx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 848w, https://substackcdn.com/image/fetch/$s_!giGx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 1272w, https://substackcdn.com/image/fetch/$s_!giGx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d3191d9-2ae3-43d4-b30c-5353202219da_1192x536.webp 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><ol start="4"><li><p><strong>Uptrace</strong> - <a href="https://uptrace.dev/">https://uptrace.dev</a></p></li></ol><p>Uptrace is another open source APM that supports distributed tracing, metrics, and logs. You can use it to monitor applications and troubleshoot issues. Uptrace comes with an intuitive query builder, rich dashboards, alerting rules, notifications, and integrations for most languages and frameworks.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nIMO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nIMO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 424w, https://substackcdn.com/image/fetch/$s_!nIMO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 848w, https://substackcdn.com/image/fetch/$s_!nIMO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 1272w, https://substackcdn.com/image/fetch/$s_!nIMO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nIMO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png" width="1213" height="808" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:808,&quot;width&quot;:1213,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36672,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!nIMO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 424w, https://substackcdn.com/image/fetch/$s_!nIMO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 848w, https://substackcdn.com/image/fetch/$s_!nIMO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.png 1272w, https://substackcdn.com/image/fetch/$s_!nIMO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffdafd1d9-a372-4e3e-8b6f-9e29172905b4_1213x808.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><ol start="5"><li><p><strong>Signoz</strong> - <a href="https://signoz.io">https://signoz.io</a></p></li></ol><p>SigNoz is an open-source observability tool powered by OpenTelemetry. You can use SigNoz to monitor your applications and infrastructure and get insights about it. It supports a wide variety of telemetry signals like logs, metrics, traces, and exceptions. You can set alerts and get notified in your preferred channel about any issue or some critical metric crossing a threshold. You can then use SigNoz as an analytics tool to debug the issue using its different features.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Xo2U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Xo2U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 424w, https://substackcdn.com/image/fetch/$s_!Xo2U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 848w, https://substackcdn.com/image/fetch/$s_!Xo2U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 1272w, https://substackcdn.com/image/fetch/$s_!Xo2U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Xo2U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp" width="1448" height="829" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:829,&quot;width&quot;:1448,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:84266,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&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_!Xo2U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 424w, https://substackcdn.com/image/fetch/$s_!Xo2U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 848w, https://substackcdn.com/image/fetch/$s_!Xo2U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 1272w, https://substackcdn.com/image/fetch/$s_!Xo2U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7665a0b3-83fe-4268-95b4-b05f19ed86aa_1448x829.webp 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><h2>My takeaway</h2><p>I&#8217;ve tried several options, and while some are well-suited for specific use cases, I still lean towards a few favorites. In my opinion, if you're looking for a well-rounded APM with an intuitive UI, Jaeger is an excellent choice.</p>]]></content:encoded></item><item><title><![CDATA[Battlefront Chronicles: #2 Lost clicks]]></title><description><![CDATA["Battlefront Chronicles" series shares stories of production mishaps, how they were handled, and the lessons learned along the way.]]></description><link>https://bitnirmata.com/p/battlefront-chronicles-2-server-time</link><guid isPermaLink="false">https://bitnirmata.com/p/battlefront-chronicles-2-server-time</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 07 Oct 2024 07:00:47 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a77e30ba-8847-49b9-97d9-02826ab26a80_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p>Please keep in mind that the stories in the Battlefront Chronicles may not all be my own. Some of them come from other engineers working in the field, and their contributors may choose to remain anonymous.</p></blockquote><h2>Advertising company</h2><p>Back in the day I was working at an advertising company, making sure our servers were delivering ads as fast as possible, to as many clients as possible. It was at the time second biggest advertising company in the central europe and we were doing roughly 40-60k requests per second on our frontend servers.</p><h2>Infrastructure</h2><p>There were quite a lot of supporting servers and services, but ~20 main virtual servers were responsible for delivering ads to the clients. They were all running on hosts that had special kernels, which were patched to run containerized applications. The technology was called <a href="http://www.linux-vserver.org/Welcome_to_Linux-VServer.org">vServer</a>. Pretty similar to Docker, but very high performant. Along with these ones, we also ran few of virtualized frontend serving instances on kvm and XenServer. Keep in mind, these were very early days and money was scarce, so we had to do with what we got, often using very old hardware or reused/refurbished servers that we bought from other companies, which were replacing their own infrastructure with newer hardware.</p><h2>Incident</h2><p>One day, CTO approached me with very interesting finding. Looking at the charts, we figured out there was lower click rate of our ads. Looking further, it seemed to have started happening gradually, but in last 2 weeks or so. Advertising is very chaotic environment and a lot of events affect it a lot. For example, when Soccer World Cup was happening, we had no clue what is going on, because we were serving 30% of the traffic for an hour or so, but then got hit by a sudden enormous spike. We later figured out, it was a half time of the game. So, these kind of events drastically affect serving, but not the internal click rate and ad showing etc., so this was indeed a weird situation. </p><h2>Investigation</h2><p>As sysadmin in charge back at the time, I went and dug into the problem further and figured out that only 1 out of 20 servers has lower click rate. Very odd! Why only this server? Metrics were fine, everything was fine. But then, I started to think a bit and tried to understand what is actually going on. So&#8230; to put it simple, when the ad is served, we send an event of &#8220;ad served&#8221; back to the servers and when it&#8217;s seen, we send &#8220;ad opened&#8221; and so on. Logically, &#8220;ad served&#8221; and &#8220;ad opened&#8221; usually happen quite fast upon serve, but &#8220;ad clicked&#8221; really depends on a person, if they click an ad or not. Looking at code I figured additional information that helped debugging the situation. Our code was actually doing additional check, that if &#8220;ad click&#8221; came through way late, like 10-15 seconds late, that would mean for us, we need to discard it as non-valid click event. Digging even further, that is exactly what was happening on this offending server. This started ringing the bells. It has something to do with time!</p><h2>The culprit</h2><p>After the initial investigation, I checked server time of the offending server and then compared it with other servers. Bingo. A difference! This server, seemed to have difference of server time of about 10 seconds!</p><p>So what. You would say&#8230;</p><p>But no, this affects our &#8220;ad click&#8221; event. It will compare timestamp when ad was served, which was served from another server, that had clock in sync and then &#8220;ad" click&#8221; came to this server, that had difference in clock of about 10 seconds, which automatically flagged this click event as discarded. </p><p>Mind blown.</p><h2>Reasoning</h2><p>Okay, so why does this even happen? I mean, we already have ntpd running on all of the hosts! Investingating a bit more, I figured out there was a difference between the rest of the ad serving servers and this one that was faulty. This one, was actually running in full virtualization! Oh, noes. </p><p>Unfortunately full virtualization can have effects on the clock itself, since it exposes it through a virtual clock. Due to this, a clock can <a href="https://groups.google.com/g/ganeti/c/mEKH1S3Mp24?pli=1">drift significantly</a>.</p><h2>The fix</h2><p>I immediately installed ntpd on full virtualized servers. I also figured out, there were other fully virtualized VM&#8217;s, that were drifting over the months of running. As soon as ntpd synced on them, this solved the problem. Ad discards were no longer happening and we had to go and asses the damage. </p><h2>Aftermath</h2><p>We were actually discarding all ad clicks on 1/20th of the servers, which meant a lot of clicks in two week span. The loss in revenue wasn&#8217;t that substantial though and that was actually an issue. If it was greater loss, we would have noticed it much earlier and would go investigate. But, as it was only 1/20th of the traffic being discarded, that was still in margin of error in reporting, considering ad serving is quite chaotic environment as mentioned before. What we could do after that, was set alerts on these discards, just in case something like this happens again, this should give us fast enough alarm that there is something wrong.</p><h2>Final thought</h2><p>This incident was a lesson to myself that I should always have metrics for time drift from now on. No matter where I am working at and what I am doing, servers should have <strong>ntpd</strong> or <strong>chrony</strong>, since server time is something that applications rely heavily on. Any clock drift pops up in a very weird manner and it takes a lot of time to debug and pinpoint the exact issue.</p>]]></content:encoded></item><item><title><![CDATA[Schema Migrations in Large-Scale MySQL Databases]]></title><description><![CDATA[On small MySQL databases, making schema changes is as simple as running an ALTER query. However, with large databases, it&#8217;s not so easy. In this article you will learn how to tackle this challenge.]]></description><link>https://bitnirmata.com/p/schema-migrations-in-large-scale</link><guid isPermaLink="false">https://bitnirmata.com/p/schema-migrations-in-large-scale</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 30 Sep 2024 07:02:59 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a3420303-d20f-462b-8166-fd018098f88c_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Problems of schema migrations</h2><p>When dealing with large-scale databases, we often encounter the following challenges during schema migrations:</p><ol><li><p><strong>Downtime and Service Disruption - </strong> Schema changes many times require taking the database offline, resulting in downtime for applications depending on the database.</p></li><li><p><strong>Data Integrity Issues - </strong>Data consistency can be problematic during a migration, especially when altering large tables.</p></li><li><p><strong>Performance Degradation - </strong>Adding indexes, altering large tables, adding columns etc. can cause performance bottlenecks, slow queries, and increased load on the database during migration itself.</p></li><li><p><strong>Locking Issues - </strong>Most of schema changes result in table locks, blocking writes to the database.</p></li></ol><h2>Renaming approach</h2><p>Common approach when dealing with these kind of problems is, to take advantage of MySQL&#8217;s online operations and work a solution around that. One of those instantanious operations would be for example rename operation and here&#8217;s how we utilize rename to be able to do schema migration with zero downtime:</p><p><strong>Step 1: </strong>Copy schema of <code>Table1</code> and create empty <code>Table1_tmp</code></p><p><strong>Step 2:</strong> Write down and drop foreign keys from <code>Table1_tmp</code></p><blockquote><p>Reason we do this, is because foreing keys checks pose a lot of additional processing for the database when it&#8217;s inserting data. If we are to sync the data into this new table, we want to keep processing at minimum, to have as fast sync as possible.</p></blockquote><p><strong>Step 3: </strong>Apply schema migration on <code>Table1_tmp</code></p><blockquote><p>Make sure that if you are adding column, you specify the default value that will be used while inserting data from <code>Table1</code> to <code>Table1_tmp</code> for existing data.</p></blockquote><p><strong>Step 4: </strong>Start syncing data from <code>Table1</code> to <code>Table1_tmp</code></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n_Mn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n_Mn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 424w, https://substackcdn.com/image/fetch/$s_!n_Mn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 848w, https://substackcdn.com/image/fetch/$s_!n_Mn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 1272w, https://substackcdn.com/image/fetch/$s_!n_Mn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!n_Mn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png" width="460" height="152" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/042f3b34-557a-409a-be5b-cd107b7774be_460x152.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:152,&quot;width&quot;:460,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19331,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!n_Mn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 424w, https://substackcdn.com/image/fetch/$s_!n_Mn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 848w, https://substackcdn.com/image/fetch/$s_!n_Mn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 1272w, https://substackcdn.com/image/fetch/$s_!n_Mn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F042f3b34-557a-409a-be5b-cd107b7774be_460x152.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><blockquote><p>During the sync, <code>Table1</code> can be in use. This means, we are free to use database, but we need to make sure we have <strong>binlog</strong> enabled, so that write queries can be replicated on the new <code>Table1_tmp</code> and we won&#8217;t have it out of sync after filling of data from <code>Table1</code> finishes.</p></blockquote><p><strong>Step 5: </strong>Once we are in sync, just rename tables</p><blockquote><p>Rename is instantanious process, so what we need to do is rename Table1 to Table1_old for example and right after that, rename Table1_tmp to Table1.</p></blockquote><p><strong>Step 6:</strong> Add the dropped foreign keys</p><h2>Available tooling</h2><p>To help us with the process, we already have few open source tools available today. One of them would be <strong>gh-ost </strong>(<a href="https://github.com/github/gh-ost">https://github.com/github/gh-ost</a>), but there are others, like <strong>pt-online-schema-change </strong>(<a href="https://docs.percona.com/percona-toolkit/pt-online-schema-change.html">https://docs.percona.com/percona-toolkit/pt-online-schema-change.html</a>).</p><h2>Gh-ost snippets</h2><p>To save you some time, here are few snippets we usually run when doing the migrations using <strong>gh-ost</strong>,<strong> </strong>so you can modify them to your liking and test things yourself.</p><h3>Running gh-ost</h3><p>To run <strong>gh-ost</strong> you will need to install it on a server that has access to your database. Replace all <code>${VARS}</code> with appropriate details from your database and modify the <code>&#8220;ADD INDEX &#8230;&#8221;</code> with your schema change statement that you wish to perform over the table.</p><pre><code>gh-ost \
--assume-rbr \
--user="${DB_USER}" \
--password="${DB_PASS}" \
--host="${DB_HOST}" \
--allow-on-master \
--database="${DB_NAME}" \
--table="${DB_TABLE}" \
--verbose \
--alter="\
ADD INDEX table_name (column_one,column_two,datetime)," \
--initially-drop-ghost-table \
--skip-foreign-key-checks \
--max-load=Threads_running=30 \
--chunk-size=50 \
--cut-over=default \
--exact-rowcount \
--concurrent-rowcount \
--serve-socket-file=/tmp/ghost.sock \
--panic-flag-file=/tmp/ghost.panic.flag \
--postpone-cut-over-flag-file=/tmp/ghost.postpone.flag \
--execute</code></pre><blockquote><p>This command will create copy of schema of your ${<code>DB_TABLE</code>} table, run the<strong> --alter </strong>commands on the newly created table and start syncing data from main table to this new one. </p></blockquote><blockquote><p>Needless to say, you should run this command in <code>screen</code> or something similar, that you can detach from, since it will probably take long time.</p></blockquote><p>For further information on flags that you can/should choose, have a look at the <a href="https://github.com/github/gh-ost/blob/master/doc/cheatsheet.md">cheatsheet</a>.</p><h3>Checking status</h3><p>To check status of the sync, there is a convenient socket available.</p><pre><code>echo status | nc -U /tmp/ghost.sock

# Migrating `mydb`.`mytable`; Ghost table is `mydb`.`_mytable_gho`
# Migrating ip-172-27-0-49:3306; inspecting ip-172-27-0-72:3306; executing on ghost
# Migration started at Wed Jan 09 16:25:10 +0000 2024
# chunk-size: 500; max-lag-millis: 1500ms; dml-batch-size: 10; max-load: Threads_running=30; critical-load: ; nice-ratio: 1.500000
# throttle-additional-flag-file: /tmp/ghost.throttle
# postpone-cut-over-flag-file: /tmp/ghost.postpone.flag [set]
# panic-flag-file: /tmp/ghost.panic.flag
# Serving on unix socket: /tmp/ghost.test.sock
Copy: 22404000/81210224 27.6%; Applied: 4052; Backlog: 0/1000; Time: 2h21m25s(total), 2h21m24s(copy); streamer: mysql-bin-changelog.003876:31236708; State: migrating; ETA: 6h11m11s</code></pre><h3>Throttling</h3><p>If you see impact on production due to this process, you can set niceness and reduce burden on the database:</p><pre><code>echo "nice-ratio=1.5" | nc -U /tmp/gh-ost.sock</code></pre><h3>Perform rename</h3><p>Once your tables are in sync, you are free to perform cut off. To do that, gh-ost constantly checks specific file and if you remove it, the running process will perform cut off and exit, finishing the migration process.</p><pre><code>rm /tmp/ghost.postpone.flag</code></pre><h3>More commands&#8230;</h3><p>If you are interested in more interactive commands, you can check here:</p><p><a href="https://github.com/github/gh-ost/blob/master/doc/interactive-commands.md">https://github.com/github/gh-ost/blob/master/doc/interactive-commands.md</a></p><h2>Final thoughts</h2><p>Although <strong>pt-online-schema-change </strong>is a powerful tool, we prefer using <strong>gh-ost</strong> for the job. Its additional features, which are essential for managing large databases, make it invaluable. Of course you are free to test both and choose one of your liking.</p>]]></content:encoded></item><item><title><![CDATA[AI GitHub Code Analyzer]]></title><description><![CDATA[It's a command-line tool that clones a public GitHub repository, loads code into your chosen generative AI model as context and helps you answer any question you may have about the code.]]></description><link>https://bitnirmata.com/p/ai-github-code-analyzer</link><guid isPermaLink="false">https://bitnirmata.com/p/ai-github-code-analyzer</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 16 Sep 2024 07:00:37 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/62b517ed-f960-4b2e-a679-f6d7a1e029f2_923x866.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Retrieval-augmented generation</h2><p>To put it simple, when you want to provide a context that is too large to be &#8220;copy-pasted&#8221; into your context prompt, you need RAG.</p><p>Or, as NVIDIA says: </p><blockquote><p>&#8220;Retrieval-augmented generation (RAG) is a technique for enhancing the accuracy and reliability of generative AI models with facts fetched from external sources.&#8221;</p></blockquote><p>Here's how it works:</p><ol><li><p>The system first searches a large dataset (like documents, web pages, or code repositories) to retrieve the most relevant information based on a your question.</p></li><li><p>After retrieving the relevant data, the system uses a generative model to generate a response that incorporates the retrieved information.</p></li></ol><p>This way we can produce more accurate and contextually relevant answers by affecting its responses in real, retrieved data rather than relying on pre-existing knowledge.</p><h2>Enough talk, let&#8217;s roll!</h2><p>Let&#8217;s have a look at example of how my <a href="https://github.com/krmeljalen/ai-github-code-analyzer">AI GitHub Code Analyzer</a> written in Python does it&#8217;s thing.</p><h3>Prerequirements</h3><p>We will need ollama running on the same machine you want to run the analyzer. More information on how to set it up in my other article: <a href="https://bitnirmata.com/p/how-to-run-your-own-chatgpt">https://bitnirmata.com/p/how-to-run-your-own-chatgpt</a></p><h3>Installation</h3><p>Obviously, you should clone the repository and install dependencies:</p><pre><code>git clone https://github.com/krmeljalen/ai-github-code-analyzer.git
cd ai-github-code-analyzer
pipenv install</code></pre><h3>Configuration</h3><p>All kinda important configuration is in <code>config.yaml</code> file:</p><pre><code>############
# Defaults #
############

repo: "krmeljalen/kdeploy"
selected_model: "llama3.1:8b"
ollama_endpoint: "http://localhost:11434"

###############
# Llama-Index #
###############

chat_mode: "compact"

#####################
# Advanced Settings #
#####################

num_thread: 12
system_prompt: "You are a sophisticated virtual assistant designed to assist users in comprehensively understanding and extracting insights from a wide range of documents at their disposal. Your expertise lies in tackling complex inquiries and providing insightful analyses based on the information contained within these documents."
embedding_model: "BAAI/bge-large-en-v1.5"
top_k: 3</code></pre><p>Parameters you probably should change to fit your needs:</p><p><strong>repo</strong> - It&#8217;s basically repository url. This string is used this way https://github.com/{repo}</p><p><strong>selected_model </strong>- needs to be the same as the model that you downloaded and loaded into your ollama</p><p><strong>num_thread</strong> - if you are using CPU and don&#8217;t have GPU like my poor laptop for example, it can speed up things, so modify this to number of cores you have</p><p><strong>top_k </strong>- increase this if you are getting bad answers, to make it think a little more before blabbering nonsense</p><h2>Running</h2><p>Simple enough, just run these two commands in the folder you ran pipenv install:</p><pre><code>pipenv shell
python3 main.py</code></pre><p>It should look like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hrtx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hrtx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 424w, https://substackcdn.com/image/fetch/$s_!hrtx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 848w, https://substackcdn.com/image/fetch/$s_!hrtx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 1272w, https://substackcdn.com/image/fetch/$s_!hrtx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!hrtx!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png" width="1200" height="407.24499523355576" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:356,&quot;width&quot;:1049,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:95905,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!hrtx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 424w, https://substackcdn.com/image/fetch/$s_!hrtx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 848w, https://substackcdn.com/image/fetch/$s_!hrtx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.png 1272w, https://substackcdn.com/image/fetch/$s_!hrtx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa68be68b-1132-4453-b97e-6efea8f262eb_1049x356.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>You are free to ask it questions now and when you are done just type: EOF</p><h2>End of the line</h2><p>Thanks for your attention, now go parse some public repos and ask AI what kind of security vulnerabilities did it find in the code.</p>]]></content:encoded></item><item><title><![CDATA[Battlefront Chronicles: #1 Mail bomb attack]]></title><description><![CDATA["Battlefront Chronicles" series shares stories of production mishaps, how they were handled, and the lessons learned along the way.]]></description><link>https://bitnirmata.com/p/battlefront-chronicles-1-mail-bomb</link><guid isPermaLink="false">https://bitnirmata.com/p/battlefront-chronicles-1-mail-bomb</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Sun, 01 Sep 2024 07:00:27 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/8f01a4de-dd35-4ac0-bce4-1d70b0d8f2cf_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote><p>Please keep in mind that the stories in the Battlefront Chronicles may not all be my own. Some of them come from other engineers working in the field, and their contributors may choose to remain anonymous.</p></blockquote><h2>Webhosting</h2><p>It was way back in the day when I was only 16 years old and was running a small server to host websites on it. To mention, there wasn&#8217;t many webhosting companies at the time. The business grew, so I expanded business and actually created a webhosting company under my family business name. I started to accept more and more customers. Some of them migrated from other web hosting providers, because they got hacked there, or were using too many resources. But that was totally fine in my eyes. I always valued this in myself, that helping those in need is honorable. And if they are desperate, I am here to accept them and help them in any way I can.</p><h2>Webserver</h2><p>As I am coming from a bit of a black hat-ish background, I knew how to prevent majority of web attacks, even if code was very insecure. Apache&#8217;s module mod_security helped me tremendously. I was digging deep into kernel hardening with custom kernel grsec patches and similar stuff. Majority of the webpages were running PHP so I was running suPHP that actually allowed me to limit resources that each customer was using. I never was into cPanel and such proprietary solutions. No. I rather wrote my own control panel. I integrated all required services and tied them together. From ProFTPd, MySQL, Apache web server and mail server that was running Postfix, to disk quotas, cpu and memory limits with cgroups. It was perfect. </p><h2>Fear of attack</h2><p>Only thing I was worried about was being DDOS-ed. (Back in the time, internet was very chaotic environment.) So I decided to take it up a notch and bought co-location for my server with, at the time, enormous network pipe of 1Gbit! I was safe. There wasn&#8217;t many DDOS attacks that this kind of pipe couldn&#8217;t handle and even so, my ISP was very helpful, if I needed to block some traffic before it actually hit my server. So, that part was neatly covered.</p><h2>The Nightmare</h2><p>As engineers, we may think we got things covered, feel comfortable that we really nailed this one and nothing can go wrong&#8230; there is always another thing that we didn&#8217;t think about.</p><div><hr></div><p>One day, my customers started calling on my mother&#8217;s company phone, that their websites that are being hosted on my server are not available. Of course, I got chills in my neck. What could it be, I felt I need to act immediately. When I reflect on it now, I feel I was being a bit silly. Even if the website dedicated to some pet dog wasn&#8217;t working for 5mins, its not the end of the world. But at the time, it did feel like that to me. I thought I failed miserably and need to fix this right a way.</p><p>I barely could log in to the server through SSH. I noticed it was getting hammered with traffic. CPU was going wild and Load was terrible. But what kind of traffic is this that is causing this? Immediately I started iptraf to pinpoint where the traffic is coming from. It was thousands of different IPs, connecting to&#8230; SMTP server! What the hell? Is someone sending a lot of emails to one of my customers? Is this legit traffic or not? I started to dig into it and could pinpoint that ther was only one affected email address that was getting mail bombed. I contacted customer and asked if I can review some of these emails coming in, because I felt something is off and I can&#8217;t pinpoint without looking at the content, to say if its legit or not. Customer agreed and I reviewed his incoming mail. It was all rubbish text. A lot of it. Randomly generated. Not a single thing, besides &#8220;To:&#8221; field that had email of my client was same in any of them. I thought, why is this even hitting my mail server, I have SpamAssassin and I do check in Postfix if there is valid Reverse DNS on IP, before even accepting any mail. How is this coming through? I reviewed some of the offeding IPs and checked Reverse DNSes, MX records and SPF records. They were all fine! They were totally legit emails that are sending enormous amounts of rubbish spam and totally overwhelming my server. </p><div><hr></div><p>The situation seemed miserable. How can I stop this. I can either just block all SMTP traffic, but then every customer will get affected. I don&#8217;t want that. I also don&#8217;t know when this attack will stop and they cannot be without emails for all that time. There was no light at the end of the tunnel. But then I said, okay, lets chill out and think. What can we do? And then it hit me. Mail servers won&#8217;t quit sending email if service is unavailable, so blocking was out of question. They will just delay it for a while and retry after retry period expires. What will happen if I change the MX record for the domain name of this affected email address&#8230;. to 127.0.0.1 or better said: localhost? That will actually make mail servers to resolve domain name to their own mail server and&#8230; start spamming themselves. This will also utilize their own spam prevention systems, that if email account doesnt exist on their system, they will discard it. And so decision was made.</p><h2>Fight back</h2><p>I called affected customer and explained the situation. I had to break it to him that his email is screwed anyway, but in order to get the attackers to stop, is to let these mailservers DDOS themselves to oblivion and they will hopefully stop after some time. He agreed and I swapped MX record of that domain to localhost. Quite soon, my server&#8217;s load went back to normal. Attack was stopping, as TTLs for this MX record was expiring all over the world and my server was back online.</p><div><hr></div><h2>Victory is mine!</h2><p>Feeling of victory overwhelmed me. I got them good! I managed to throw their own rubbish back at them. Customers started to report everything is awesome and I could finally take a breather. I decided to leave this domain MX pointed to localhost for 24 hours, before I return it back. I was a bit worried, attack would start to happen again, after I reset it to correct IP, but no. Attackers learned their lesson and just stopped with the attack. Luckily, they never tried something like this again, but then again, they probably lost a lot of their zombie nodes, since server admins figured out something fishy is going on, with their mail servers DDOSing themselves and started to remove malicious code doing it.</p>]]></content:encoded></item><item><title><![CDATA[Task Shadowing]]></title><description><![CDATA[We&#8217;re familiar with job shadowing, but what about task shadowing? Let's explore how we can effectively use task shadowing when performing critical tasks in a production environment.]]></description><link>https://bitnirmata.com/p/task-shadowing</link><guid isPermaLink="false">https://bitnirmata.com/p/task-shadowing</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 26 Aug 2024 07:01:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/80428f6f-70ed-49ef-bfd6-210c345c2f71_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Definition</h2><p>Task shadowing is a concept similar to job shadowing but more focused on specific tasks or processes rather than an entire job role. In a production environment, especially when dealing with critical tasks, task shadowing can be a valuable practice to ensure accuracy, quality, and knowledge transfer.</p><h2>Considerations</h2><p>Understanding when and how to utilize task shadowing is crucial. Let&#8217;s break it down into a few key points to consider when implementing task shadowing:</p><ul><li><p><strong>Identify Critical Tasks:</strong> Determine which tasks in the production environment are critical and would benefit from task shadowing.</p></li><li><p><strong>Select Appropriate Engineers:</strong> Choose individuals who will perform the task and those who will shadow, ensuring the latter have the necessary foundational knowledge. Preferably the one shadowing should be a Senior Engineer that has the know how.</p></li><li><p><strong>Establish a Shadowing Plan:</strong> Plan the task shadowing session, including when it will take place and what will be covered in the session. If physical presence of the person shadowing is not possible, we usually utilize screen sharing software like Teams or Zoom. Person executing tasks on production environment is sharing a screen and usually waits for confirmation of the person shadowing.</p></li><li><p><strong>Engage in Active Observation:</strong> The person shadowing should actively observe, point out the mistakes and double check what is being executed.</p></li></ul><h2>Benefits</h2><p>We observed number of benefits utilizing such process. Let&#8217;s have a look at some of them:</p><ul><li><p><strong>Training:</strong> Task shadowing can be an effective way to train less experienced team members on critical tasks. Observer can add additional comments to the one executing commands, so they are more confident in what they are doing. </p></li><li><p><strong>Documenting:</strong> During task shadowing, the observer updates the steps involved in the task in case there is any change needed in the procedure for future reference.</p></li><li><p><strong>Double-checking:</strong> In a production environment, critical tasks often require high accuracy. Task shadowing allows for a second pair of eyes to oversee the process, reducing the likelihood of errors. We, as engineers are very prone to see other people&#8217;s errors and shadowing is leaning on it heavily.</p></li><li><p><strong>Real-time feedback:</strong> The shadowing individual can provide or receive immediate feedback on the process, identifying potential issues or areas for improvement.</p></li><li><p><strong>Minimizing risk:</strong> During the execution of particularly sensitive tasks (e.g., deploying a major update or handling a high-risk operation), having someone shadow can help ensure that all steps are followed correctly, minimizing chance of mistake happening.</p></li><li><p><strong>Contingency Planning:</strong> Often times person shadowing will give feedback about possible issues we can encounter executing a specific task, along with remediation procedure for it, ensuring that the person executing task is aware of what to do in case something goes wrong.</p></li><li><p><strong>Building Confidence:</strong> For someone who will eventually take over the task, shadowing provides hands-on experience that builds confidence. It relieves stress and basically removes unnecessary fear that could build up otherwise.</p></li><li><p><strong>Cross training:</strong> Sometimes we are using shadowing as method of ensuring that more people are capable of performing critical tasks if the primary person is unavailable.</p></li><li><p><strong>Feedback:</strong> Last but not least, person shadowing can give valuable feedback to the one executing a task after the session. Observer can give a positive feedback on well performed task, or points out areas that the person executing crucial task should work on, to do better next time.</p></li></ul><h2>Summary</h2><p>By integrating task shadowing into our critical production activities, we really enhanced the reliability and efficiency of our operations as well as lowered stress of engineers that are involved with executing these tasks. This is especially important in a sector like crypto and finance, where millions of dollars are on line for every minute of downtime. If your organisation is not doing task shadowing, you should strongly consider it.</p>]]></content:encoded></item><item><title><![CDATA[Shaving off milliseconds in AWS]]></title><description><![CDATA[In a high speed, low latency networks, every millisecond counts. This article takes a look at jumbo frames and their effect not only on throughput, but also latency.]]></description><link>https://bitnirmata.com/p/shaving-off-milliseconds-in-aws</link><guid isPermaLink="false">https://bitnirmata.com/p/shaving-off-milliseconds-in-aws</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Fri, 16 Aug 2024 15:12:47 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/1621903a-4581-490a-a06d-b2bb3ed34a49_1024x1024.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Hot path application</h2><p>Our work is highly specialized, focusing on optimizing network performance to ensure exchanges can handle the maximum number of requests without delay. To give you an idea, our median response time on certain endpoints is approximately 3-4ms. Enhancing performance beyond this level is extremely challenging. While our hot path applications are written in Go and we might achieve slight improvements by transitioning to Rust, we don&#8217;t see that as a viable option. Such small potential improvement does not justify the work and effort needed to achieve it.</p><h2>Further optimization</h2><p>At this point, we start looking into other kind of improvements that we can squeeze out of our infrastructure. One of them would be, using cpu and network optimized instances, using placement groups or cluster placement groups etc.</p><p>Arguably you should not put whole infrastructure in placement group that is latency optimized, since that brings additional risks, because instances are possibly located on the same rack in the datacenter. That being said, if something happened to that rack, a large portion of infrastructure would be at risk, not just few instances. It&#8217;s not really acceptable risk for us.</p><p>What we can actually do, without affecting overall risk, is improve general network performance inside VPC by utilizing Jumbo frames. But, Jumbo frames are used to improve throughput when dealing with large files, not the latency! Arguably that is true, but let&#8217;s have a look at the approach.</p><p><strong>Hint: </strong>There is an overhead of handling a large amount of small packets vs. handling small amount of large packets.</p><h2>Jumbo frames on AWS</h2><p>In general AWS supports 9001 MTU Jumbo frames. But how do we get to the 9001? Seems rather weird number. We would assume 9000 would be sensible in the first place. The answer lays in the AWS hardware setup. AWS hardware actually supports 9216 MTU, but AWS, to be able to encapsulate all the traffic inside a tunnel uses 215 bytes per frame. So (9216 - 215) brings us to 9001 and this is the portion that is left for us to use. </p><p>Jumbo frames are basically supported on latest generation instances<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>, but keep in mind, AWS Traffic is limited to a maximum MTU of 1500 in the following cases:</p><ul><li><p>Traffic over an internet gateway</p></li><li><p>Traffic over an inter-region VPC peering connection</p></li><li><p>Traffic over VPN connections</p></li><li><p>Traffic outside of a given AWS Region</p></li></ul><p>For our case, this is totally fine. We need Jumbo frames support on cross AZ and intra-AZ.</p><h2>Proof of Concept</h2><p>To prove the theory that overhead of processing large number of packets has its effect on overall latency, we will be using the largest packet that we can find on our hot path infrastructure, and that would be orderbook call. Fully fledged order books for coin pairs are usually up to 500kB of size, so we will take this as data size we want to test on.</p><h3>Enabling Jumbo frames</h3><p>To enable Jumbo frames on Amazon Linux 2023 upon boot up:</p><pre><code>echo "MTU=9001" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth0
echo "request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-search, domain-name-servers, host-name, nis-domain, nis-servers, ntp-servers;" | sudo tee -a /etc/dhcp/dhclient.conf</code></pre><p>Setting it manually for testing purposes:</p><pre><code>ip link set dev ens5 mtu 9001
ip link show ens5</code></pre><h3>Tracepath</h3><p>Once we&#8217;ve set MTU on instances that we wish to test, to be able to verify if our path is actually supporting that MTU, we need tracepath:</p><pre><code><code>sudo yum install iputils</code></code></pre><p>Testing if our server to client path supports our desired MTU:</p><pre><code>[root@mtu1 ec2-user]# tracepath 10.0.1.18
 1?: [LOCALHOST]                      pmtu 9001
 1:  10.0.1.18                                             0.166ms reached
 1:  10.0.1.18                                             0.127ms reached
     Resume: pmtu 9001 hops 1 back 2
[root@mtu1 ec2-user]#</code></pre><h3>Benchmark</h3><p>References in code:<br><strong>mtu1</strong> - 10.0.1.89 - eu-west-1a - Server that is running listening server to accept data<br><strong>mtu2</strong> - 10.0.2.55 - eu-west-1b - Server that is running tcpdump script and client that will send 500kB of data<br><strong>local </strong>- My own laptop that will trigger benchmark automation procedure remotely</p><p>I&#8217;ll be running server.py on <strong>mtu1</strong> server. It will listen to connection, accept data, write some info about the transfer and shutdown: </p><p><strong>server.py:</strong></p><pre><code>import socket

# Server configuration
HOST = '10.0.1.89'  # Localhost
PORT = 65432        # Port to listen on (non-privileged ports are &gt; 1023)

# Create a TCP/IP socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
    # Bind the socket to the address and port
    server_socket.bind((HOST, PORT))

    # Listen for incoming connections
    server_socket.listen(1)
    print(f"Server listening on {HOST}:{PORT}")

    # Wait for a connection
    conn, addr = server_socket.accept()
    with conn:
        print(f"Connected by {addr}")
        total_data = b''

        # Keep receiving data until the connection is closed
        while True:
            data = conn.recv(1000000)
            if not data:
                break
            total_data += data
            print(f"Received {len(data)} bytes")

        print(f"Total data received: {len(total_data)} bytes")
        print("Data received successfully.")</code></pre><p>Client code is run on <strong>mtu2</strong> instance that is in another AZ than mtu1. It basically crafts string of 512kB and sends it to mtu1 server. Nothing fancy.</p><p><strong>client.py:</strong></p><pre><code>import socket

def start_client(host='10.0.1.89', port=65432):
    # Create a TCP/IP socket
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # Connect to the server
    client_socket.connect((host, port))

    try:
        # Create a 500 KB message (512000 bytes)
        message = b'a' * 500 * 1024

        # Send the data
        client_socket.sendall(message)
        print(f"Sent {len(message)} bytes of data to the server.")

    finally:
        # Clean up the connection
        client_socket.close()

if __name__ == "__main__":
    start_client()</code></pre><p>We will run tcpdump script in automation script called analyzer besides the client on the <strong>mtu2</strong> server, so that we can verify the whole path, from the send of SYN packet, to the FIN packet received, marking our connection closed. We will subtract the times in this script and get total microseconds needed for connection and transfer to finish. This will be used to determine how changing MTU affects the latency.</p><p><strong>tcpdump script:</strong></p><pre><code>#!/bin/bash
echo "Starting analysis"

# Get current MTU
MTU=$(ip addr show | grep ens5 | grep mtu | awk -F" " {'print $5'})
echo "MTU: $MTU"

# Run for 5 seconds. Enough for us to run one execution and everything to be written down
timeout 4 tcpdump -i ens5 'port 65432' &gt; dump.log 2&gt;/dev/null

# Gather start and stop numbers
START_T=$(cat dump.log | grep "\[S\]" | awk -F" " {'print $1'} | awk -F "." {'print $2'})
END_T=$(cat dump.log | grep "\[F\.\]" | awk -F" " {'print $1'} | awk -F "." {'print $2'})
NUM_PACKETS=$(wc -l dump.log|awk -F" " {'print $1'})

# Cast to string cause sometimes we can have 092340 number
START=$(expr $START_T + 0)
END=$(expr $END_T + 0)
DIFF=$(($END - $START))
echo "Time: $(($END - $START)) &#956;s"

# Graph section:
# If we have argument, use that as index otherwise just put in timestamp
if [ $# -eq 0 ]; then
    INDEX=$(date +%s)
else
    INDEX=$1
fi

TIMESTAMP=$(date +%s)
# Log to csv
echo "$INDEX,$MTU,$NUM_PACKETS,$DIFF" &gt;&gt; data.csv</code></pre><p>To put everything together, we will run automation script on our own <strong>local</strong> computer that will execute everything in correct order. It&#8217;s all quick and dirty since this is PoC to show you how things behave.</p><p><strong>automation script:</strong></p><pre><code>#!/bin/bash
# Note:
# mtu1 = server
# mtu2 = client

# Stop if theres an error
set -eu -o pipefail

# We will test these MTUs
MTUS=("1500" "9001")
for MTU in "${MTUS[@]}"
do
    # Set MTU on both servers, then proceed with testing
    echo "Setting MTU to $MTU"
    ssh mtu1 sudo ip link set dev ens5 mtu $MTU
    ssh mtu2 sudo ip link set dev ens5 mtu $MTU

    # Run test 40 times and gather results. They will be available in data.csv as per analyze script code.
    for NUM in {1..40}
    do
        echo "Iteration ${NUM}: ${MTU} MTU"
        ssh mtu1 sudo "python3 server.py" &amp;
        sleep 1
        ssh mtu2 sudo "./analyze $NUM" &amp;
        sleep 1
        ssh mtu2 sudo "python3 client.py"
        sleep 4
    done
done</code></pre><p>I think 40 times is good enough to get at least some insight if there is difference between the two MTUs and transfer over network.</p><h2>Benchmark results</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yS0y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yS0y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 424w, https://substackcdn.com/image/fetch/$s_!yS0y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 848w, https://substackcdn.com/image/fetch/$s_!yS0y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 1272w, https://substackcdn.com/image/fetch/$s_!yS0y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yS0y!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png" width="1200" height="625.5494505494505" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:759,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:80498,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yS0y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 424w, https://substackcdn.com/image/fetch/$s_!yS0y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 848w, https://substackcdn.com/image/fetch/$s_!yS0y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.png 1272w, https://substackcdn.com/image/fetch/$s_!yS0y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe5ce9085-789c-4cea-acb6-d6f4fec4ef3c_1470x766.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>We can notice a rough estimation of 500 microseconds latency improvement sending 500kB of data over the wire. Difference in number of packets needed to send this data is noticable. In 9001 MTU the data was sent in total of ~88 packets logged by tcpdump, while the 1500 MTU needed ~401 packets to send this data. We also notice that cross AZ latencies vary. They are not consistent and they take 1ms more from time to time. If I ran this long enough we would see some spikes where latency cross AZ can spike much more than 1ms though, in range of 4ms or so. This is something we raised with AWS in the past, because this kind of fluctuation does affect our matching engine performance if we use it cross AZ, but unfortunately there was no follow up on it.</p><h2>Final thoughts</h2><p>The grand total of improvement on orderbook API call that in start needed 3ms and shaving off 0.5 millisecond is 16,67% and if we count the max numbers at 4ms, then its 12.5% improvement. Some may not think this is a lot, but when dealing with so low numbers and going into microseconds realm, this does make a difference, for very low effort needed to achieve it.</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>https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances</p><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[AWS Bedrock with OpenWebUI]]></title><description><![CDATA[AWS Bedrock lacks variety in web UI options. But there is a way to connect it to the OpenWebUI. In following article I'll show you a way to do it.]]></description><link>https://bitnirmata.com/p/aws-bedrock-with-openwebui</link><guid isPermaLink="false">https://bitnirmata.com/p/aws-bedrock-with-openwebui</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 05 Aug 2024 07:00:57 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/7233b5b5-931b-4817-b81d-2888a4f5f6ef_983x510.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>AWS Bedrock</h2><p>AWS Bedrock is a managed service by Amazon Web Services that lets developers build, train, and deploy machine learning models. It offers pre-trained models and scalable infrastructure, simplifying the integration of AI into applications.</p><h2>Problem</h2><p>AWS Bedrock, as it&#8217;s awesome and pretty cheap way of accessing variety of LLMs without having to run server on your own, which can be pretty pricey, it lacks decent web UI. I was searching around to find something useful, but just couldn&#8217;t find it.</p><p>What I did find though is a project called: <strong>Bedrock Access Gateway</strong>, which is basically OpenAI-compatible RESTful API for Amazon Bedrock. </p><h2>Putting it all together</h2><p><strong>Bedrock Access Gateway</strong></p><p>Let&#8217;s get our Bedrock Access Gateway first to get it up and running, lets not use default <code>Dockerfile</code>, but <code>Dockerfile_ecs</code>:</p><pre><code>git clone https://github.com/aws-samples/bedrock-access-gateway.git
cd bedrock-access-gateway/src/
rm Dockerfile
mv Dockerfile_ecs Dockerfile
docker build -t bedrock-proxy .</code></pre><p>We will need AWS access so let&#8217;s enter proper access credentials by running:</p><pre><code>aws configure</code></pre><p>Now that we have our credentials set, let&#8217;s bring up our bedrock-proxy and pass it credentials to get access to AWS Bedrock:</p><pre><code>docker run --rm -v $HOME/.aws/config:/root/.aws/config:ro -d -p 8081:80 bedrock-proxy &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code></pre><p><strong>OpenWebUI</strong></p><p>Now lets bring OpenWebUI up and running by executing:</p><pre><code>docker run --rm -d -p 8080:8080 -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:ollama</code></pre><p><strong>Configuring</strong></p><p>Lets spin up our http://localhost:8080 in web browser, register and login to the OpenWebUI. Click on your profile icon on top right and choose: <strong>Admin Panel &#8594; Settings &#8594; Connections</strong></p><p>Disable Ollama API and edit the OpenAI API host to match your docker local ip and path <code>/api/v1</code> as seen on the screenshot. Default password for Bedrock Access Gateway is: <code>bedrock</code></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qndZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qndZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 424w, https://substackcdn.com/image/fetch/$s_!qndZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 848w, https://substackcdn.com/image/fetch/$s_!qndZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 1272w, https://substackcdn.com/image/fetch/$s_!qndZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!qndZ!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png" width="1200" height="183.9541547277937" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:214,&quot;width&quot;:1396,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:21142,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!qndZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 424w, https://substackcdn.com/image/fetch/$s_!qndZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 848w, https://substackcdn.com/image/fetch/$s_!qndZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 1272w, https://substackcdn.com/image/fetch/$s_!qndZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4beb491f-ca15-4fa8-9db3-85236e9da764_1396x214.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Here we go, lets test it, as you can see on top we see bunch of available models on AWS Bedrock:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SHLB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SHLB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 424w, https://substackcdn.com/image/fetch/$s_!SHLB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 848w, https://substackcdn.com/image/fetch/$s_!SHLB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 1272w, https://substackcdn.com/image/fetch/$s_!SHLB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SHLB!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png" width="1200" height="380.7692307692308" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:462,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:87754,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!SHLB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 424w, https://substackcdn.com/image/fetch/$s_!SHLB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 848w, https://substackcdn.com/image/fetch/$s_!SHLB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.png 1272w, https://substackcdn.com/image/fetch/$s_!SHLB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24ea37fe-a8c1-497a-ae70-a726c05930f4_1634x518.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>I chose <strong>anthropic.claude-3-sonnet-20240229-v1:0</strong>, but you can choose any other. </p><h3>Voila!</h3><p></p><h4>Troubleshooting</h4><p>If you get an error like this, you probably didnt subscribe to the model in AWS model access.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LPeB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LPeB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 424w, https://substackcdn.com/image/fetch/$s_!LPeB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 848w, https://substackcdn.com/image/fetch/$s_!LPeB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 1272w, https://substackcdn.com/image/fetch/$s_!LPeB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LPeB!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png" width="1200" height="332.5077399380805" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:358,&quot;width&quot;:1292,&quot;resizeWidth&quot;:1200,&quot;bytes&quot;:30461,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LPeB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 424w, https://substackcdn.com/image/fetch/$s_!LPeB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 848w, https://substackcdn.com/image/fetch/$s_!LPeB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.png 1272w, https://substackcdn.com/image/fetch/$s_!LPeB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18ee11ed-5a0b-46d7-a416-fd1404e6a003_1292x358.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 verify it, you can check logs of bedrock-proxy container and you will see:</p><pre><code>    | fastapi.exceptions.HTTPException: 500: An error occurred (AccessDeniedException) when calling the ConverseStream operation: You don't have access to the model with the specified model ID.</code></pre><p>To enable it, just go to web console and under AWS Bedrock service, subscribe and add the model you wish to use. More info <a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html">here</a>.</p>]]></content:encoded></item><item><title><![CDATA[How to run your own ChatGPT]]></title><description><![CDATA[Concerned about sharing your data on public AI services? Have compliance requirements that restrict their use within your organisation? Discover how to run your own LLM.]]></description><link>https://bitnirmata.com/p/how-to-run-your-own-chatgpt</link><guid isPermaLink="false">https://bitnirmata.com/p/how-to-run-your-own-chatgpt</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 29 Jul 2024 07:01:22 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ed54996c-ac99-4b2d-8842-06c64151f08a_1400x933.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Concerns about public AI services</h2><p>Using public AI services involves several concerns that users and organisations need to be aware of to ensure security, privacy, and compliance, including:</p><ol><li><p>Data privacy</p></li><li><p>Security risks</p></li><li><p>Compliance and legal issues</p></li><li><p>Intellectual property</p></li><li><p>Cost and Vendor Lock-in</p></li></ol><p>Certainly, there are additional concerns, but these highlight some of the key challenges. Running your own Large Language Model (LLM) can help you overcome many of these issues.</p><h2>Considerations</h2><p>There are several ways to run your own LLM-powered AI service. You can choose to use CPU processing for your AI assistant or swap to GPU processing. I did test Distributed Llama, which uses multiple servers to enhance response times, but it didn't meet my expectations. Therefore, in this article, I will focus on setting up a server and utilising GPU processing.</p><h2>Setup</h2><p><strong>Step 1: Prepare server</strong></p><p>You will need a GPU server, and have SSH access to it. I will use AWS GPU instance, but you might consider some other provider that is a bit cheaper.</p><p>If you insist on AWS, few cheapest GPU instances on AWS would be:</p><ul><li><p>g3s.xlarge - NVIDIA Tesla M60 (~$0.3591/h Spot price)</p></li><li><p>g4dn.xlarge - NVIDIA T4 Tensor Core (~$0.1919/h Spot price)</p></li><li><p>p2.xlarge - NVIDIA Tesla K80 (~$0.3355/h Spot price)</p></li></ul><p>Choose at least 40GB of storage, depending on the LLM you will be using.</p><p>Be sure to choose AMI image that has your NVIDIA drivers installed, otherwise you will need to install them on your own. Instructions for installing the drivers on your own are <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/install-nvidia-driver.html#preinstalled-nvidia-driver">here</a>.</p><p><strong>Step 2: Setup Llama 3</strong></p><p>Once you have your instance up and running, lets install Llama 3 and test how it works. <a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></p><pre><code>curl -fsSL https://ollama.com/install.sh | sh</code></pre><p>Result should look like this:</p><pre><code>[root@llama ec2-user]# curl -fsSL https://ollama.com/install.sh | sh
&gt;&gt;&gt; Downloading ollama...
#######################################################################
&gt;&gt;&gt; Installing ollama to /usr/bin...
&gt;&gt;&gt; Creating ollama user...
&gt;&gt;&gt; Adding ollama user to video group...
&gt;&gt;&gt; Adding current user to ollama group...
&gt;&gt;&gt; Creating ollama systemd service...
&gt;&gt;&gt; Enabling and starting ollama service...
Created symlink from /etc/systemd/system/default.target.wants/ollama.service to /etc/systemd/system/ollama.service.
&gt;&gt;&gt; NVIDIA GPU installed.</code></pre><p><strong>Step 3: Test Llama</strong></p><pre><code>ollama run llama3</code></pre><p>My test looked like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jNKV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jNKV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 424w, https://substackcdn.com/image/fetch/$s_!jNKV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 848w, https://substackcdn.com/image/fetch/$s_!jNKV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 1272w, https://substackcdn.com/image/fetch/$s_!jNKV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jNKV!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png" width="1332" height="383.3159340659341" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:419,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1332,&quot;bytes&quot;:129462,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!jNKV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 424w, https://substackcdn.com/image/fetch/$s_!jNKV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 848w, https://substackcdn.com/image/fetch/$s_!jNKV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.png 1272w, https://substackcdn.com/image/fetch/$s_!jNKV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe32c0266-5646-46e6-b875-711b5e0890c8_1744x502.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>In above test, llama 3 answered really fast, unlike if we would be using CPU instead of GPU.</p><p><strong>Step 4: Setup OpenWebUI</strong></p><p>Let&#8217;s run OpenWebUI in docker and not go with pip version, since that one is in beta.</p><p>Prepare prerequirements:</p><pre><code>yum -y install docker docker-runtime-nvidia libnvidia-container-tools
systemctl enable docker
systemctl start docker</code></pre><p>Run the OpenWebUI docker:</p><pre><code><code>docker run -d -p 8080:8080 --gpus=all -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ghcr.io/open-webui/open-webui:ollama</code></code></pre><p>Verify that docker container is up and Healthy:</p><pre><code>[root@llama ~]# docker ps -a
CONTAINER ID   IMAGE                                  COMMAND           CREATED              STATUS                    PORTS                                       NAMES
d9a8c31d4ad2   ghcr.io/open-webui/open-webui:ollama   "bash start.sh"   About a minute ago   Up 56 seconds (healthy)   0.0.0.0:8080-&gt;8080/tcp, :::8080-&gt;8080/tcp   open-webui</code></pre><p><strong>Step 5: Test OpenWebUI</strong></p><p>OpenWebUI exposes port <code>8080</code> as we can see above. Let&#8217;s connect to it via web browser and register:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pAcn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pAcn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 424w, https://substackcdn.com/image/fetch/$s_!pAcn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 848w, https://substackcdn.com/image/fetch/$s_!pAcn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 1272w, https://substackcdn.com/image/fetch/$s_!pAcn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pAcn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png" width="1030" height="752" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c403df60-4c8b-4172-b952-0827e2498a40_1030x752.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:752,&quot;width&quot;:1030,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:72750,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!pAcn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 424w, https://substackcdn.com/image/fetch/$s_!pAcn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 848w, https://substackcdn.com/image/fetch/$s_!pAcn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.png 1272w, https://substackcdn.com/image/fetch/$s_!pAcn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc403df60-4c8b-4172-b952-0827e2498a40_1030x752.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>Lets fix the model now. On top right click your profile icon and go to <strong>Admin panel &#8594; Settings &#8594; Models</strong> and enter one of the models. I chose <strong>llama3.1:8b</strong>. To verify all other models click <a href="https://ollama.com/library">here</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wncj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wncj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 424w, https://substackcdn.com/image/fetch/$s_!wncj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 848w, https://substackcdn.com/image/fetch/$s_!wncj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 1272w, https://substackcdn.com/image/fetch/$s_!wncj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wncj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png" width="252" height="88" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c27d1853-70fb-4917-af28-da4073984bec_252x88.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:88,&quot;width&quot;:252,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9462,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!wncj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 424w, https://substackcdn.com/image/fetch/$s_!wncj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 848w, https://substackcdn.com/image/fetch/$s_!wncj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 1272w, https://substackcdn.com/image/fetch/$s_!wncj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc27d1853-70fb-4917-af28-da4073984bec_252x88.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>Once download process finishes, you can open new chat, choose your model on top left and ask your question.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!t91v!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!t91v!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 424w, https://substackcdn.com/image/fetch/$s_!t91v!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 848w, https://substackcdn.com/image/fetch/$s_!t91v!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 1272w, https://substackcdn.com/image/fetch/$s_!t91v!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!t91v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png" width="965" height="384" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:384,&quot;width&quot;:965,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:70203,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!t91v!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 424w, https://substackcdn.com/image/fetch/$s_!t91v!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 848w, https://substackcdn.com/image/fetch/$s_!t91v!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.png 1272w, https://substackcdn.com/image/fetch/$s_!t91v!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52891918-42cb-4c9b-83ef-c7fec0bcd265_965x384.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><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>Be sure your Nvidia drivers are already working, else you will have a bad time. I chose to go with <strong>g4dn.xlarge</strong> instance and preinstalled drivers, so AMI for this one at time of writing this article in <strong>eu-west-1</strong> region was <strong>ami-0faa087f5b4d78dc7</strong> <strong>- Amazon Linux 2 AMI with NVIDIA TESLA GPU Driver</strong></p></div></div>]]></content:encoded></item><item><title><![CDATA[Saving costs on RDS Audit log exports]]></title><description><![CDATA[If you&#8217;re sending RDS Audit logs to CloudWatch Logs, you might be overspending. Learn how to optimize your costs.]]></description><link>https://bitnirmata.com/p/saving-costs-on-rds-audit-log-exports</link><guid isPermaLink="false">https://bitnirmata.com/p/saving-costs-on-rds-audit-log-exports</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Mon, 22 Jul 2024 07:00:30 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a49d15a8-edfc-4a55-99da-122a33e7a318_780x438.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>RDS Audit logs</h2><p>RDS audit logs are a crucial component of monitoring and maintaining the security and compliance of a database. These logs capture all activities and events within the RDS instance, providing a detailed record of who accessed the database, when they accessed it, and what actions they performed.</p><h2>CloudWatch Log exports</h2><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vh-d!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vh-d!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 424w, https://substackcdn.com/image/fetch/$s_!vh-d!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 848w, https://substackcdn.com/image/fetch/$s_!vh-d!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 1272w, https://substackcdn.com/image/fetch/$s_!vh-d!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vh-d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png" width="535" height="270" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/683317b6-5254-4691-8413-81b598cb016d_535x270.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:270,&quot;width&quot;:535,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33174,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&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="" title="" srcset="https://substackcdn.com/image/fetch/$s_!vh-d!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 424w, https://substackcdn.com/image/fetch/$s_!vh-d!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 848w, https://substackcdn.com/image/fetch/$s_!vh-d!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.png 1272w, https://substackcdn.com/image/fetch/$s_!vh-d!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F683317b6-5254-4691-8413-81b598cb016d_535x270.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><p>By default, RDS audit log exports are sent to CloudWatch Logs. However, for databases with high activity, this can result in significant costs reaching tens of thousands of dollars per month. As a result, it is important to explore alternative solutions to manage these costs effectively.</p><h2>Solutions</h2><p>There are two solutions to this:</p><ol><li><p><strong>Download logs via RDS API and store them manually</strong></p><p>This is the cheapest method, but requires manual handling and combining of these logs, since logs are rotated by RDS quite frequently. You need to make sure you store the logs to alternative location, before they expire. Fortunately calls to RDS API are free and you will not be charged for them, but you will be charged for data transfer. Keep in mind API calls do have rate limits, so you will have to work around that.</p></li><li><p><strong>Change CloudWatch log group to infrequent access</strong></p><p>Since these logs are not meant to be searched all the time, changing log group to infrequent access might just do it. Its much simpler solution that only requires recreation of log group and setting it to infrequent access.</p></li></ol><p>In this article, we will explore the second option as an alternative to the first, which requires coding a custom solution from scratch.</p><h2>Procedure</h2><p><strong>Backup</strong></p><p>RDS uses predefined paths for exporting logs to CloudWatch. These paths are static and cannot be changed:</p><ul><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/error</p></li><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/slowquery</p></li><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/audit</p></li><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/general</p></li></ul><p>Because of this reason, there is a small drawback that you will have to delete them. They cannot be renamed, so if you want to keep logs, you can export them to S3 beforehand by clicking on log group and under action you can choose:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!e87E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!e87E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 424w, https://substackcdn.com/image/fetch/$s_!e87E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 848w, https://substackcdn.com/image/fetch/$s_!e87E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 1272w, https://substackcdn.com/image/fetch/$s_!e87E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!e87E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png" width="285" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:285,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32311,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!e87E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 424w, https://substackcdn.com/image/fetch/$s_!e87E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 848w, https://substackcdn.com/image/fetch/$s_!e87E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.png 1272w, https://substackcdn.com/image/fetch/$s_!e87E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf65ee3-7add-4854-9d7b-14bf41a77640_285x294.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><strong>Changing log group to Infrequent Access</strong></p><ol><li><p>Disable current CloudWatch Exports, so your current log group gets released. Unless you do this, log groups will be constantly recreated by RDS.</p></li><li><p>Delete log groups:</p><ul><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/error</p></li><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/slowquery</p></li><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/audit</p></li><li><p>/aws/rds/cluster/&lt;cluster_name&gt;/general</p></li></ul></li><li><p>Recreate all log groups with exact same name, but with Infrequent Access log class</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c3CH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c3CH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 424w, https://substackcdn.com/image/fetch/$s_!c3CH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 848w, https://substackcdn.com/image/fetch/$s_!c3CH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 1272w, https://substackcdn.com/image/fetch/$s_!c3CH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c3CH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png" width="824" height="476" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5d3994bd-6506-4508-95e4-546a1446b480_824x476.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:476,&quot;width&quot;:824,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50283,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!c3CH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 424w, https://substackcdn.com/image/fetch/$s_!c3CH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 848w, https://substackcdn.com/image/fetch/$s_!c3CH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.png 1272w, https://substackcdn.com/image/fetch/$s_!c3CH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d3994bd-6506-4508-95e4-546a1446b480_824x476.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></li><li><p>Enable log exports on your cluster again</p><p>Log groups that you created will be reused, meaning they will be using new Infrequent Access log class.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!su8F!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!su8F!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 424w, https://substackcdn.com/image/fetch/$s_!su8F!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 848w, https://substackcdn.com/image/fetch/$s_!su8F!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 1272w, https://substackcdn.com/image/fetch/$s_!su8F!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!su8F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png" width="821" height="103" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:103,&quot;width&quot;:821,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16791,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!su8F!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 424w, https://substackcdn.com/image/fetch/$s_!su8F!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 848w, https://substackcdn.com/image/fetch/$s_!su8F!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 1272w, https://substackcdn.com/image/fetch/$s_!su8F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17c20e8f-18c0-4868-9566-fe691fd686e8_821x103.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div></li></ol><h2>Summary</h2><p>By switching log exports to infrequent access, you can reduce your storage costs by approximately 50%. This reduction also applies to API calls, which are the primary cost generator when publishing to CloudWatch logs.</p><p>Reference pricing 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_!B5jc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!B5jc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 424w, https://substackcdn.com/image/fetch/$s_!B5jc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 848w, https://substackcdn.com/image/fetch/$s_!B5jc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 1272w, https://substackcdn.com/image/fetch/$s_!B5jc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!B5jc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png" width="619" height="356" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:356,&quot;width&quot;:619,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:41922,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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_!B5jc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 424w, https://substackcdn.com/image/fetch/$s_!B5jc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 848w, https://substackcdn.com/image/fetch/$s_!B5jc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.png 1272w, https://substackcdn.com/image/fetch/$s_!B5jc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c1188da-f1d6-4811-b2e9-43f4a6ccdc14_619x356.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>Latest prices for your region: <a href="https://aws.amazon.com/cloudwatch/pricing/">https://aws.amazon.com/cloudwatch/pricing/</a></p>]]></content:encoded></item><item><title><![CDATA[AWS Secrets Manager Agent launched!]]></title><description><![CDATA[My take on this new agent that complements Secrets Manager and where it still falls a bit short...]]></description><link>https://bitnirmata.com/p/aws-secrets-manager-agent-launched</link><guid isPermaLink="false">https://bitnirmata.com/p/aws-secrets-manager-agent-launched</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Fri, 12 Jul 2024 00:26:30 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c3d78cd4-b32a-47d3-a434-4d3e4bf83950_502x368.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Secret Manager</h2><p>Finance sector in general, as you can imagine, is very paranoid about credentials storing and rightfully so. To mitigate this issue and only use encrypted store for credentials, using AWS Secrets Manager is one way to tackle the problem. It has been de facto standard for storing credentials for many companies, including ours.</p><h2>Problems</h2><p>But here come the problems. So far using secrets manager has resulted in few issues to say the least. Calling Secret Manager API directly from your code was the way it was suppose to be used and if you have few secrets, that might even float the boat. But as soon as you have 100s of credentials and a huge infrastructure, you run into several issues:</p><ul><li><p>Slow boot of an application - Calling API to load these secrets and so on, it just precious time to the boot up of application and we hate that.</p></li><li><p>API rate limits - Even if high by AWS specification, you need to multiply amount of credentials by the amount of servers and this number all of the sudden gets pretty high. </p></li><li><p>Costs - Imagine continuous deploys and autoscaled infrastructure where servers are all the time going up and down and being deployed and so on&#8230; these calls get costly after a while.</p></li><li><p>Secrets Manager not being available - Low probability, but still&#8230; Ouch. You better not restart anything and immediately stop all autoscaling processes&#8230; :)</p></li></ul><p>AWS did introduce bulk loading of secrets, which kinda helped with the situation, but still doesn&#8217;t solve all of the problems.</p><h2>Secret Manager Agent</h2><p>One way to deal with the situation is running some kind of an agent next to your application and here comes AWS Secrets Manager Agent. You can find it here: <a href="https://github.com/aws/aws-secretsmanager-agent">https://github.com/aws/aws-secretsmanager-agent</a></p><p>What it does is, it basically caches secrets for application to have them available immediately. This solves majority of the above listed problems.</p><p>To list at least few features that are significant improvement vs directly calling Secrets Manager API:</p><ul><li><p>Caches secrets (d0h!)</p></li><li><p>In-memory storage of these secrets - thats good, cause it doesn&#8217;t store them on disk and they are immediatly available</p></li><li><p>Ability to expire secrets after a while and re-retrieve them from Secrets Manager</p></li><li><p>Interface to communicate with Agent instead of Secret Manager directly</p></li></ul><p>For most of AWS Cloud infrastructures this is good enough. Unfortunately not for all. There are several issues where Agent still falls short:</p><ul><li><p>Doesn&#8217;t do cache invalidations - It&#8217;s a pull method upon TTL expiry. It doesn&#8217;t know that a secret changed and it should go re-fetch it and expose new value to the app.</p></li><li><p>Secrets values in memory are not encrypted - Scrubbing memory and trying to protect credentials from memory dump attacks is hard.</p></li><li><p>It fetches secret by secret, doesn&#8217;t do bulk load.</p></li><li><p>Restart of Agent will wipe out all cached secrets and it will need to re-fetch them - Arguably this is good thing, since this means secrets are for sure refreshed and this way you can force cache invalidation.</p></li></ul><h2>Summary</h2><p>Unfortunately this Agent came out a little late for us, to be using it, because we already implemented our own, called Secrets Caching Service or SCS in short. For now we will stick to our implementation, since SCS actually supports push method, grouping of secrets (pushing only a group of secrets in bulk to a SCS that is running on server) and utilizing Redis pub/sub functionality to notify appropriate servers that they should pull new secrets (because one of them changed in Secret Manager for example).</p><p>Disregarding the above, I still think majority of companies that are using AWS Secret Manager, should use Secret Manager Agent from now on. It&#8217;s just a no-brainer and a great improvement in secrets management in general. Great work AWS, I hope there will be additional features coming to it soon&#8230;</p>]]></content:encoded></item><item><title><![CDATA[High Throughput Internal Load Balancing in AWS Cloud]]></title><description><![CDATA[I delved into different approaches to internal load balancing. What kind of options there are and benchmark them in order to see how they behave and perform under high load.]]></description><link>https://bitnirmata.com/p/high-throughput-internal-load-balancing</link><guid isPermaLink="false">https://bitnirmata.com/p/high-throughput-internal-load-balancing</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Thu, 11 Jul 2024 16:43:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9aa9d4d6-2bef-48b1-9e13-0b17b6dbc9d1_854x653.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>Introduction</h2><p>I work at a crypto exchange, where latency and througput of trading hot path is utmost important. We try to use every trick that we can come up with in AWS Cloud in order to get even more performance out of our systems. Saying that, load balancing is obviously very important. AZ aware connections, proximity of servers inside AZ, network hops from service to service, direct memory access, optimizing TCP stack, so that data fits in one packet&#8230; it all matters. In this post we will focus on our benchmark process regarding internal load balancing. </p><h2>Loadbalancing approaches</h2><p>Idea is not to delve too much into details of each, but high overview is still due.</p><p><strong>AWS Application load balancer</strong></p><ul><li><p>Provided by AWS</p></li><li><p>Operates at Layer 7 (HTTP/HTTPS) and supports features like path-based routing, host-based routing, and HTTP/2</p></li><li><p>Automatically scales to handle changes in application traffic</p></li></ul><p><strong>AWS Network load balancer</strong></p><ul><li><p>Provided by AWS</p></li><li><p>Operates at Layer 4 (TCP/UDP) and provides extreme performance</p></li><li><p>Handles millions of requests per second while maintaining ultra-low latencies</p></li><li><p>Provides a static IP address per Availability Zone</p></li><li><p>Useful for load balancing traffic to databases, media streaming, and other use cases that require ultra-low latencies</p></li></ul><p><strong>IPVS load balancer</strong></p><ul><li><p>Not provided by AWS as service and usually used in conjunction with kubernetes</p></li><li><p>IPVS is a load balancing solution built into the Linux kernel</p></li><li><p>It implements transport-layer load balancing, handling TCP and UDP traffic</p></li><li><p>IPVS can direct requests to a cluster of real servers and make the services appear as virtual services on a single IP address</p></li></ul><p><strong>iptables load balancer</strong></p><ul><li><p>Not provided by AWS as service and usually used in conjunction with kubernetes</p></li><li><p>iptables load balancing is implemented directly in the Linux kernel, providing very high performance</p></li><li><p>The <code>nat</code> table in iptables is used to perform Network Address Translation (NAT). This allows iptables to redirect incoming traffic to different backend servers</p></li></ul><p><strong>Proxy load balancer</strong></p><ul><li><p>Not provided by AWS as service</p></li><li><p>HAProxy, NGINX Plus, Traefik etc&#8230;</p></li><li><p>Distributes incoming traffic across multiple backend servers based on predefined algorithms (e.g., round-robin, least connections)</p></li><li><p>In summary proxy load balancer combines the benefits of a reverse proxy (security, caching, SSL termination) with the load balancing capabilities (traffic distribution, health checks, scalability) to provide a comprehensive solution for optimizing the delivery of web applications.</p></li></ul><p><strong>DNS based loadbalancing</strong></p><ul><li><p>Not provided by AWS as service</p></li><li><p>Consul, there might be more, but the priciple is same.</p></li><li><p>DNS load balancer provides active health checking of services</p></li><li><p>If a service fails its health check, it is removed from the service discovery results</p></li><li><p>This enables load balancing to avoid unhealthy instances</p></li></ul><h2><strong>Purpose</strong></h2><p>I aim to determine which type of load balancer is best suited for throughput in terms of requests per second with as little, to no loss comparing to actual direct client / server throughput.</p><h2>Rules</h2><ol><li><p><strong>HTTP traffic</strong></p></li></ol><p>Since there are multiple approaches of talking service to service, majority of clients that actually use these services in finance usually talk HTTP or FIX protocol. For intra service communication gRPC would probably be more suitable, but for the sake of giving all loadbalancers a chance in the race, I chose HTTP to be the one that we are going to benchmark. No keep-alive connections!</p><ol start="2"><li><p><strong>Static file serving</strong></p></li></ol><p>Purpose is to benchmark load balancers, not webserver performance itself. Static file serving (an image) is as simple as it gets for a webserver to serve without any interruption. Image gets cached and we get minimum delay serving it from memory upon receiving request. Decision was made, to serve small, only 4kb image file which more or less reflects size of common API service response.</p><p><strong>Sweet spot</strong></p><p>A baseline benchmark from one server to another, without any load balancer, has been established as our target requests per second. We aim to achieve this target, or get as close to it as possible, while introducing various load balancers between the client server and the webserver.</p><h2><strong>Setup</strong></h2><h4>General</h4><ul><li><p>VPC</p></li><li><p>1 AZ (no cross AZ traffic allowed)</p></li><li><p>c5.large instance for client and server</p></li><li><p>Amazon Linux 2023</p></li><li><p>No additional optimizations of TCP stack in kernel apart from necessary changes needed for specific loadbalancer to actually work</p></li><li><p>Apache benchmark tool</p></li><li><p>200 concurrent connections and 1 million requests, repeated at least 10 times, taking average requests per second as a metric that we are observing</p></li></ul><h4>AWS Application Load Balancer</h4><p>Loadbalancer with HTTP port 80 forwarding to target group with webserver. Additional AZ subnet was added to ALB, since it requires at least 2 AZs to be able to run, but no instances exist in that second AZ.</p><h4>AWS Network Load Balancer</h4><p>TCP loadbalancer, forwarding port 80 to target group.</p><h4>IPVS</h4><p>First we installed ipvsadm, loaded kernel module and set kernel params to be able to run IPVS. Whole setup is basically the same as kube-proxy does it, when choosing IPVS as proxy mode.</p><pre><code>yum -y install ipvsadm

modprobe ip_vs

sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv4.ip_nonlocal_bind=1

systemctl start ipvsadm</code></pre><p>After that we created a virtual IP and added our server as backend to it:</p><pre><code>ipvsadm -A -t 10.0.1.50:80 -s rr
ipvsadm -a -t 10.0.1.50:80 -r 10.0.1.100:80 -m</code></pre><p>At this point we can run benchmark on our vip 10.0.1.50.</p><h4>iptables</h4><p>I made minimal setup. Intentionally I didn&#8217;t add all additional stuff that usually kubernetes does by marking chains and all shebang that would result in even more impact on the actual benchmark, cause of additional rule processing. In the end it comes down to this:</p><pre><code>iptables -F
iptables -t nat -F
iptables -t nat -X

# Forward traffic from port 80 to 192.168.10.211:80
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.10.211:80
iptables -t nat -A OUTPUT -p tcp -o lo --dport 80 -j DNAT --to-destination 192.168.10.211:80
iptables -t nat -A POSTROUTING -p tcp -d 192.168.10.211 --dport 80 -j MASQUERADE</code></pre><p>What this does is very similar or even simplified version that kube-proxy does when you choose to run iptables as proxy mode.</p><h4>Proxy server</h4><p>Even if it seemed as non-sence to even try this one, since running additional webserver and amount of processing needed to run it, just to forward traffic to another backend seems very resource intense and a very poor solution for load balancer. I still decided to give it a chance and chose HAProxy as it&#8217;s suppose to be most suitable for these cases general.</p><p>Here is the excerpt of the config for HAproxy:</p><pre><code>frontend myfrontend
  mode http
  bind :80
  default_backend web_servers

backend web_servers
  mode http
  balance roundrobin
  server webserver 192.168.10.211:80 check</code></pre><h2>Benchmark results</h2><p><strong>Forenote</strong>: For obvious reason it makes no sense to be benchmarking DNS load balancing solution, since that kind of load balancing already happens on the DNS resolution stage, before we even start establishing connection to the server and therefore is treated as a direct client to server connection.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w5UI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w5UI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 424w, https://substackcdn.com/image/fetch/$s_!w5UI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 848w, https://substackcdn.com/image/fetch/$s_!w5UI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 1272w, https://substackcdn.com/image/fetch/$s_!w5UI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!w5UI!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png" width="874" height="536.7302904564316" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2185397b-6e9d-40ad-b754-88387bfad647_723x444.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:444,&quot;width&quot;:723,&quot;resizeWidth&quot;:874,&quot;bytes&quot;:33192,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&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-large" alt="" srcset="https://substackcdn.com/image/fetch/$s_!w5UI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 424w, https://substackcdn.com/image/fetch/$s_!w5UI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 848w, https://substackcdn.com/image/fetch/$s_!w5UI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.png 1272w, https://substackcdn.com/image/fetch/$s_!w5UI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2185397b-6e9d-40ad-b754-88387bfad647_723x444.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><h2>Observation</h2><p><strong>AWS Application Loadbalancer</strong></p><p>We can immediately notice how slow start is in effect here. It starts with about 30% of final throughput. It took loadbalancer roughly 10 minutes to scale up on AWS side to be performing at par.</p><p><strong>AWS Network Loadbalancer</strong></p><p>As advertised by AWS, very fast to react and at times even faster than direct connection to webserver. One could say, that doesn&#8217;t even make sense! But it actually does, you just don&#8217;t see whats going on in the background since it&#8217;s hidden in the &#8220;Cloud&#8221;. The fact is, servers are scattered around in datacenter and there is X switches between them. I would assume AWS reserves portion of the switches and routes network so that their services get best latency from servers. this doesn&#8217;t mean server to server is same well optimised! Meaning, RTT from client to server might take longer than RTT from client to network loadbalancer to server. Interesting, although as seen from the graph, difference is very minimal.</p><p><strong>IPVS</strong></p><p>Best from non AWS native load balancers. As it came up strong, it still fell short in the long run vs Application Load Balancer. Kernel module as soon as it was loaded did have an effect on the overall network performance. It added additional processing needed to be done and that is seen from the graph. For kubernetes, if you don&#8217;t want to be paying for network load balancers, because you might have a lot of microservices and what not, IPVS is best option to go with.</p><p><strong>iptables</strong></p><p>Second to last. Processing of iptables is burdening the system and if you add even more rules that usually kubernetes comes with, you will have a cumbersome infrastructure. It might do it for non latency sensitive and low troughput stuff, but I don&#8217;t see why would anyone use it, if the change to IPVS in kube-proxy proxy mode is pretty trivial.</p><p><strong>Proxy</strong></p><p>For obvious reasons last. Processing needed to forward traffic is just too much for server to be dealing with additionally, to stay competitive. Usually HAProxy is something you would use in AWS to overcome other limitations of native AWS load balancers. Example of that would be like a active-standby setup. Where only one server can be answering, but you still want to have a highly available setup in case it goes down. </p><h2>Summary</h2><p>We can conclude best choice for internal load balancer would be AWS Network Load Balancer. If you don&#8217;t have a lot of microservices and are in need of huge number of load balancers, this is your preferred choice. It can become costly though in the long run as your infrastructure grows and you need more and more of them&#8230;</p><p>IPVS is best &#8220;free&#8221; loadbalancer, if you go with kubernetes and kube-proxy to manage it, otherwise it can become quite a burden to manage.</p><p>General rule of thumb is, if you want to even further optimise the impact of loadbalancer on overall performance and throughput, is to use keep alive or connection pooling. Not all programming languages support connection pooling, but HTTP keep-alive is pretty straight forward improvement. From my testing, enabling keep-alive pretty much doubled the performance in requests per second.</p>]]></content:encoded></item><item><title><![CDATA[kdeploy - Automating kubernetes and docker deploying]]></title><description><![CDATA[I recently coded kdeploy, which is small tool that helps you to deploy your docker image to your kubernetes cluster by providing a manifest file and running kdeploy.]]></description><link>https://bitnirmata.com/p/kdeploy-automating-kubernetes-and</link><guid isPermaLink="false">https://bitnirmata.com/p/kdeploy-automating-kubernetes-and</guid><dc:creator><![CDATA[Alen Krmelj]]></dc:creator><pubDate>Sun, 07 Jul 2024 15:27:32 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/347341b7-d473-47d8-a541-b988ce30fbc9_300x168.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p></p><h1><strong>Intro to kdeploy</strong></h1><p>kdeploy is small tool written in python that utilizes kubernetes and docker libs to build &amp; publish images to your docker repository and deploy them to kubernetes cluster. Aim is to have your development environment very simple, fast and with little to no tinkering to get your small dockerized app up and running.</p><h1><strong>Problem with development env</strong></h1><p>Coding on your own laptop and trying your code out should be fun and easy. Majority of developers don&#8217;t want to deal with publishing, building and doing pipelines for their small app they developed in their spare time. Preparing scripts that will deploy an app, copying them around from project to project is cumbersome. Let&#8217;s say I coded small flask app and I just want it up and running as soon as possible, without figuring out kubernetes deployment, services and fixing the secrets for docker repo etc. I just want to specify what is name of my app, it should run in pod and it needs exposed port 80 as service, thats it. Here comes kdeploy that gives you just that.</p><h1><strong>Overview of kdeploy</strong></h1><p>So let&#8217;s quickly overview what kdeploy needs as requirement to run and what it does.</p><h3><strong>Requirements</strong></h3><ul><li><p>python - obviously</p></li><li><p>kubernetes cluster configured - you should have your kubernetes cluster configured and be able to run kubectl on it, to manipulate it.</p></li><li><p>docker repository configured - you should have your docker credentials setup and be able to login to your docker repository that you want to store your app to. </p></li></ul><h3>Process</h3><p>Once you have kdeploy installed locally, you should have manifest.yaml in your folder and just run: <code>kdeploy</code></p><p>What it kdeploy does is:</p><ol><li><p>Finds <code>Dockerfile</code> in folder you ran kdeploy</p></li><li><p>Reads <code>manifest.yaml </code>file to make sure what is the name of this app and how do you want it deployed (Either as Pod, CronJob or maybe a Deployment with replicas&#8230;). It will also figure out if you need a service if you provided exposed port etc.</p></li><li><p>Builds docker image locally and tags it with app name</p></li><li><p>Pushes image to your docker repository with appropriate tag and version</p></li><li><p>Checks if you have secret set for kubernetes to be able to pull this docker image</p></li><li><p>Generates kubernetes files for deploying the app</p></li><li><p>Deploys app to your kubernetes</p></li></ol><h3>Demo</h3><p>Here is simple example how would you deploy a very simple html serving app:</p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;d8ad11ea-85ac-446c-8323-e032b73ebd8b&quot;,&quot;duration&quot;:null}"></div><h3>Try it yourself</h3><p>You are welcome to follow instructions for installation and usage on my github: <a href="https://github.com/krmeljalen/kdeploy">https://github.com/krmeljalen/kdeploy</a></p><h3>Final words</h3><p>I basically swapped all my personal projects to kdeploy. I used to have bunch of bash scripts that did similar things and I just got to a point where I wanted to change something in that deploy process and would need to update bunch of repos for it. kdeploy solved this issue for me. There will probably be more updates to kdeploy as I might need more features, but for majority of my projects, kdeploy already covers them. There are just few projects that need specific kubernetes files, but for those, kdeploy also supports path to kubernetes yaml specifying. This means, even if I want to have this one project very special and need to setup some persistent volumes and whatnot, I still can use kdeploy for it.</p>]]></content:encoded></item></channel></rss>