<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Development on Flavio Silva</title><link>https://fsilva.me/tags/development/</link><description>Recent content in Development on Flavio Silva</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><managingEditor>flavio1110@gmail.com (Flavio Silva)</managingEditor><webMaster>flavio1110@gmail.com (Flavio Silva)</webMaster><lastBuildDate>Mon, 28 Aug 2023 14:00:00 +0100</lastBuildDate><atom:link href="https://fsilva.me/tags/development/feed.xml" rel="self" type="application/rss+xml"/><item><title>🐔 What happened with my project on the Rinha de Backend challenge</title><link>https://fsilva.me/posts/rinha-de-backend/</link><pubDate>Mon, 28 Aug 2023 14:00:00 +0100</pubDate><author>flavio1110@gmail.com (Flavio Silva)</author><guid>https://fsilva.me/posts/rinha-de-backend/</guid><description>&lt;img src="https://fsilva.me/posts/rinha-de-backend/rooster_fight.png" alt="Featured image of post 🐔 What happened with my project on the Rinha de Backend challenge" /&gt;&lt;p&gt;I participated in the &lt;a class="link" href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3" target="_blank" rel="noopener"
 &gt;Rinha de backend (pt-BR)&lt;/a&gt; or &lt;a class="link" href="https://en.wikipedia.org/wiki/Cockfight" target="_blank" rel="noopener"
 &gt;&amp;ldquo;Backend Rooster Fight&amp;rdquo; in English&lt;/a&gt; challenge and I was super excited to see the results of my super hacky and performant solution.&lt;/p&gt;
&lt;p&gt;The results were scheduled to be published at 21:00 BRT (2 AM CEST my local time). So I stayed up til later that night grabbed popcorn, and waited for the results.&lt;/p&gt;
&lt;p&gt;Well, I wish I hadn&amp;rsquo;t waited&amp;hellip;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;TL;DR; My solution didn&amp;rsquo;t run on the official test server because I built the docker image to &lt;code&gt;linux/arm64&lt;/code&gt; instead of &lt;code&gt;linux/amd64&lt;/code&gt; 🤦🤦🤦 . I fixed the issue and ran the same tests afterward and I reached ~50% of points of the winner, mainly because in my solution I didn&amp;rsquo;t tolerate any risk of losing writes. Checkout my repository &lt;a class="link" href="https://github.com/flavio1110/rinha-de-backend" target="_blank" rel="noopener"
 &gt;&lt;strong&gt;flavio1110/rinha-de-backend&lt;/strong&gt;&lt;/a&gt; with my solution.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;h3 id="what-was-the-rinha-de-backend"&gt;What was the Rinha de Backend?
&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Before we get into the details, a brief explanation of what was the challenge.&lt;/em&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;From July 28th to August 25th, the Backend Fight was held, a tournament in which the API that supported the most load during a stress test would be the winner. Participants had to implement an API with endpoints to create, query and search for &amp;lsquo;people&amp;rsquo; (a kind of CRUD without UPDATE and DELETE). In the tournament, participants still had to deal with CPU and memory restrictions – each participant had to deliver the API in docker-compose format and could only use 1.5 CPU units and 3GB of memory. More details on technical aspects can be found in the instructions) – &lt;a class="link" href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3/tree/main#o-que-%C3%A9" target="_blank" rel="noopener"
 &gt;(translated from its repository in English)&lt;/a&gt;.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;On top of the description above, some things important to highlight are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You can write your API with any language or framework, as long as you can build a docker image out of it&lt;/li&gt;
&lt;li&gt;The solution has to run two instances of the API in parallel.&lt;/li&gt;
&lt;li&gt;The requests will be balanced as you wish between these instances via Nginx.&lt;/li&gt;
&lt;li&gt;You have to use one of the following data stores: MySQL, PostgreSQL, or MongoDB.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It was a super fun, informal, practical, and a very good opportunity to exercise and learn new things.&lt;/p&gt;
&lt;h4 id="how-the-winners-were-determined"&gt;How the winners were determined?
&lt;/h4&gt;&lt;p&gt;To make the comparison easier and fun, the &lt;strong&gt;single parameter&lt;/strong&gt; used to determine the winner of the challenge was the &lt;strong&gt;number of people inserted&lt;/strong&gt; into the database.&lt;/p&gt;
&lt;h2 id="how-did-i-do"&gt;How did I do?
&lt;/h2&gt;&lt;figure class="aligncenter"&gt;
 &lt;img src="https://fsilva.me/images/rinha-2023-q3-meme.jpeg" alt="my solution explodes" /&gt;
 &lt;figcaption&gt;POV you are looking at me while I check the results.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I didn&amp;rsquo;t. I was disqualified because the container with my APIs didn&amp;rsquo;t start. Therefore I got nothing. 🤦🤦🤦&lt;/p&gt;
&lt;h3 id="wrong-platform"&gt;Wrong platform?
&lt;/h3&gt;&lt;p&gt;Yes, that&amp;rsquo;s true. My solution didn&amp;rsquo;t even run because &lt;a class="link" href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3/blob/main/resultados/primeira-fase/flavio1110/docker-compose.logs#L63" target="_blank" rel="noopener"
 &gt;it failed to start the APIs&lt;/a&gt;. I built the images for &lt;code&gt;linux/arm64&lt;/code&gt; instead of &lt;code&gt;linux/amd64&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It was a mistake on my end, and it made me super disappointed. I ran the tests on the &lt;a class="link" href="https://github.com/flavio1110/rinha-de-backend/actions/runs/5949338191" target="_blank" rel="noopener"
 &gt;CI pipelines&lt;/a&gt;, and it gave me confidence the image was properly built and I didn&amp;rsquo;t double-check the requirements. Shame on me.&lt;/p&gt;
&lt;p&gt;Well, I was disqualified but I was curious to see how it would perform on a server with the &lt;a class="link" href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3/blob/main/misc/lshw-aws" target="_blank" rel="noopener"
 &gt;same configuration as the one used for the official tests&lt;/a&gt;. So, I fixed the platform of the image, spun up an EC2 with the same configuration, and finally ran the tests. The results were a bit disappointing compared to the TOP 10.&lt;/p&gt;
&lt;h3 id="how-did-i-approach-the-problem"&gt;How did I approach the problem?
&lt;/h3&gt;&lt;p&gt;I had two constraints in mind while designing and building:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It has to work – each endpoint has to do what it is supposed to do.&lt;/li&gt;
&lt;li&gt;Keep things as simple as possible.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these points brought a few tradeoffs that ended up limiting the overall performance of the solution.&lt;/p&gt;
&lt;p&gt;You can check my solution on &lt;a class="link" href="https://github.com/flavio1110/rinha-de-backend" target="_blank" rel="noopener"
 &gt;flavio1110/rinha-de-backend&lt;/a&gt;. It&amp;rsquo;s built with Go and PostgreSQL.&lt;/p&gt;
&lt;p&gt;Given many APIs were performing super well, a few days before the last day of the challenge, &lt;a class="link" href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3/commit/be637c944434bdddfe4a92a31bd17cd528f68a38" target="_blank" rel="noopener"
 &gt;the load for the stress test was doubled&lt;/a&gt;, and it had a massive impact on the performance of my API. You can check the comparison below:&lt;/p&gt;
&lt;p&gt;Before&amp;hellip;&lt;/p&gt;
&lt;figure class="aligncenter"&gt;
 &lt;a href="https://fsilva.me/rinha-de-backend/rinhabackendsimulation-20230821183911665/" target="_blank"&gt;&lt;img src="https://fsilva.me/images/gh_results_before.png" alt="rooster fight" /&gt;&lt;/a&gt;
 &lt;figcaption&gt;Print of part of the report generated by Gatling of my solution run on Github BEFORE the load was doubled.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After&amp;hellip;&lt;/p&gt;
&lt;figure class="aligncenter"&gt;
 &lt;a href="https://fsilva.me/rinha-de-backend/rinhabackendsimulation-20230823091057409/" target="_blank"&gt;&lt;img src="https://fsilva.me/images/gh_results_after.png" alt="rooster fight" /&gt;&lt;/a&gt;
 &lt;figcaption&gt;Print of part of the report generated by Gatling of my solution run on Github AFTER the load was doubled.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="what-were-the-bottlenecks"&gt;What were the bottlenecks?
&lt;/h3&gt;&lt;p&gt;The inserts were the bottleneck. Because I didn&amp;rsquo;t tolerate the risk of losing writes and wanted to keep it simple, I missed the opportunity to introduce a distributed mechanism to validate the data before trying to insert it into the database and perform the inserts in batch.&lt;/p&gt;
&lt;h4 id="validating-the-uniqueness-of-a-field-apelido-nickname"&gt;Validating the uniqueness of a field &lt;em&gt;Apelido&lt;/em&gt; (Nickname)
&lt;/h4&gt;&lt;p&gt;On my designed solution, without a distributed cache, it was not possible to perform without the DB in 100% of the cases.&lt;/p&gt;
&lt;p&gt;I had an in-memory cache, but if the nickname wasn&amp;rsquo;t there because it wasn&amp;rsquo;t there because the entry was inserted via the other instance, that request would reach the DB, occupy a connection, take resources, etc.&lt;/p&gt;
&lt;p&gt;Introducing a distributed cache like &lt;a class="link" href="https://redis.uptrace.dev/" target="_blank" rel="noopener"
 &gt;Redis&lt;/a&gt; would enable me to add and check the entry in a single place. As a result, we could decrease the memory necessary to run the APIs and move to the cache.&lt;/p&gt;
&lt;h4 id="batching-inserts"&gt;Batching inserts
&lt;/h4&gt;&lt;p&gt;I inserted each entry per a valid request because I didn&amp;rsquo;t want to risk losing valid writes in case there was any error between the construction of the batch and its execution.&lt;/p&gt;
&lt;p&gt;This was a huge problem because it used too many DB connections and resources, and slowed down the creation request.&lt;/p&gt;
&lt;h3 id="did-i-like-it"&gt;Did I like it?
&lt;/h3&gt;&lt;p&gt;Despite my results, I loved the challenge! I learned quite some tricks with nginx config and some insteresting stuff like using &lt;a class="link" href="https://redis.io/docs/interact/pubsub/" target="_blank" rel="noopener"
 &gt;Redis&lt;/a&gt; or even &lt;a class="link" href="https://www.postgresql.org/docs/current/sql-notify.html" target="_blank" rel="noopener"
 &gt;PostgreSQL&lt;/a&gt; as a &amp;ldquo;PubSub&amp;rdquo;.
The interaction with the community via &lt;a class="link" href="https://twitter.com/flavio1110" target="_blank" rel="noopener"
 &gt;Twitter&lt;/a&gt; and Github was super nice!
I also liked the fact of working with something challenging and closer to reality. Loved it!&lt;/p&gt;
&lt;h3 id="what-could-i-have-done-differently"&gt;What could I have done differently?
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Build the image using the correct platform.&lt;/li&gt;
&lt;li&gt;A challenge is a challenge. I should have been more flexible with the writing.&lt;/li&gt;
&lt;li&gt;Tweak the Nginx configuration to load balance based on fewer connections and disable logs.&lt;/li&gt;
&lt;li&gt;Use a distributed cache and drop the read table.&lt;/li&gt;
&lt;li&gt;Batch inserts.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="whats-next"&gt;What&amp;rsquo;s next?
&lt;/h2&gt;&lt;p&gt;Check the &lt;a class="link" href="https://github.com/zanfranceschi/rinha-de-backend-2023-q3#resultados" target="_blank" rel="noopener"
 &gt;official results&lt;/a&gt; and look into the repositories of the participants. I guarantee I&amp;rsquo;ll learn something new.&lt;/p&gt;
&lt;p&gt;Stay tuned on &lt;a class="link" href="https://twitter.com/rinhadebackend" target="_blank" rel="noopener"
 &gt;@rinhadebackend&lt;/a&gt; for the next challenges, I can&amp;rsquo;t wait for the next ones.&lt;/p&gt;
&lt;p&gt;Other than that, I&amp;rsquo;ll apply the lessons learned to my solution and hopefully get better results. Watch &lt;a class="link" href="https://github.com/flavio1110/" target="_blank" rel="noopener"
 &gt;flavio1110/rinha-de-backend&lt;/a&gt; and see how it will evolve.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;This challenge is officially over, but you can still do it. Challenge accepted?&lt;/em&gt;&lt;/p&gt;</description></item></channel></rss>