<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="http://blog.freira.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="http://blog.freira.dev/" rel="alternate" type="text/html" /><updated>2026-06-10T23:30:10+00:00</updated><id>http://blog.freira.dev/feed.xml</id><title type="html">Mateus Freira</title><subtitle>MSc, Developer, and Nun-db maintainer</subtitle><entry><title type="html">I am fully offgrid now!</title><link href="http://blog.freira.dev/@mateusfreira-2026-06-07-i-am-fully-off-grid-now/" rel="alternate" type="text/html" title="I am fully offgrid now!" /><published>2026-06-07T07:23:43+00:00</published><updated>2026-06-07T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2026-06-07-i-am-fully-off-grid-now</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2026-06-07-i-am-fully-off-grid-now/"><![CDATA[<p>Last year I wrote about <a href="https://blog.freira.dev/@mateusfreira-2025-05-07-why-I-am-using-off-grid-solar-energy/">“Why I am using Off-grid Solar energy in my Home office”</a>, and it has become an addicting practice.</p>

<p>When I wrote that blog post, I was living in a rented house. At the end of last year, my wife and I decided to buy a house in Nova Lima, the city with the highest HDI in our state. It is an amazing city to live in — we are in a gated community with a lot of green areas, and we are close to the city center.</p>

<p>Since the start, I planned to make it 100% off-grid. Our condominium already provides the water, so electricity would be our main focus.</p>

<p>I invested in 9 solar panels of 550 W each, 10 smaller panels of 160 W each, 4 batteries of 100 Ah 48 V (LiFePO4), and 2 inverters in parallel of 5 kW (10 kW peak) each, as the main system.</p>

<p>I also had a few spare flexible panels, and I used them to set up my old 24 V system, where I have 4 12 V batteries (2 in series) and one extra 100 Ah 24 V battery. Today it works as a complementary system to my EcoFlow Delta Pro, which I use as a complementary battery system for my network.</p>

<p>With that, my setup has approximately 28 kWh of storage and approximately 3 days of autonomy with low usage, or 2 days with high usage.</p>

<p>I DIY’d the entire setup and it was a great learning experience. The next step will be to learn how to produce food at home, enough quality food to supply most of what my family needs. For that, I am planning to implement a framework called “Sisteminha Embrapa”, a circular system of food production where we will produce tilapia, eggs, and vegetables.</p>

<p>The self-sufficiency activities turn out to be very fun, and an amazing hobby to work on during off hours.</p>

<p>Ever since AI coding took off, I feel like I am working without any blockers, and it is very easy to code for 8, 9, or 10 hours nonstop. Having fixed activities away from the computer like this keeps me sane, and they turn out to be very useful and save money as a side effect. I have not had a power outage or internet outage (because of Starlink) in over a year, and it feels really good — not to mention the $100+ I save every month on the electricity bill. Maybe food is next; let’s see how it goes.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">What Would It Take for You to Merge a PR Without Looking at the Code?</title><link href="http://blog.freira.dev/@mateusfreira-2026-04-21-what-would-it-take-for-you-to-merge-a-pr-without-looking-at-the-code/" rel="alternate" type="text/html" title="What Would It Take for You to Merge a PR Without Looking at the Code?" /><published>2026-04-21T07:23:43+00:00</published><updated>2026-04-21T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2026-04-21-what-would-it-take-for-you-to-merge-a-pr-without-looking-at-the-code</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2026-04-21-what-would-it-take-for-you-to-merge-a-pr-without-looking-at-the-code/"><![CDATA[<p>Prior to AI, this would be an easy answer. If the code is well written, small, covered by tests, the PR has a clear spec of what it is doing, and the author is trustworthy (meaning they know, or seem to know, what they are doing), most of the time you just scan the code to check it won’t hurt anything and merge. With AI, it gets trickier: the person submitting the code may not be the one who wrote it. How do we trust that?</p>

<p>This is exactly what I asked a few of my team leaders a couple of weeks ago: “What would it take for you to merge a PR without even looking at the code?” We had a bunch of answers, and in the end the conclusion was that it’s not different from what it was prior to AI. Namely:</p>

<ul>
  <li>small, well-tested changes</li>
  <li>all CI checks pass</li>
  <li>a clear goal</li>
  <li>the PR is sized to the problem, no bigger, no smaller</li>
</ul>

<p>Those are the PRs that are easy to merge, and that shouldn’t change regardless of whether AI or a human wrote the code.</p>

<p>If your process wasn’t mature before AI arrived, you won’t be able to capture the speed benefits AI offers. AI will produce far more code than we can ever review, and we have to be able to move fast. That means we have to be able to verify quickly if the code is harmful or not. That can only be achieved by automation, checks that verify (among others checks):</p>

<ul>
  <li>the code does not introduce new security problems (Dependabot, Snyk, etc.)</li>
  <li>the code does not add excessive cyclomatic complexity, duplication, or similar code-smell signals (SonarQube, CodeClimate, etc.)</li>
  <li>the code is not doing something it was not supposed to be doing (This point is trickier and still need a human reviewer to judge.)</li>
</ul>

<p>For the first time in my career, a developer has zero excuse: not to write tests, not to write meaningful and succinct documentation, and not to ship an end-to-end test that proves the fix works across the stack without introducing regressions. We should leverage that.</p>

<p>We should use these tools not only to produce more code but also to produce safer code, that is better covered by tests than ever, and code that, even if humans aren’t reading all of it, is easy to replace when the time comes. I’ve said more than once on <a href="https://blog.freira.dev/@mateusfreira-rules-for-great-software-architects/">this blog</a> that good design is easy to change. That remains the core of good architecture in my book. With AI, even more so. If something is hard to change, if a change is touching way too much code and moving way too many parts, you probably should step back and check if that’s the direction you want to go. The design principle hasn’t changed.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Your answer to “what would it take to merge a PR without reading every line?” shouldn’t depend on whether AI wrote it. With a mature process, tests, coverage, and a clear understanding of the change, the decision is easy. Without those criteria, it’s not a PR worth merging. There will always be PRs you want to review carefully because they are bigger, more impactful, or riskier.</p>

<p>But there will also be PRs that are small, incremental steps forward, and it should be easy to scan them, merge, and move on. With AI we should have those on steroids, many small, incremental changes moving forward. If your process or tools don’t allow that, go back and fix them; otherwise you’re going to miss the speed this thing can bring us.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Rules to become a great software architect</title><link href="http://blog.freira.dev/@mateusfreira-2025-10-02-rules-for-great-software-architects/" rel="alternate" type="text/html" title="Rules to become a great software architect" /><published>2025-10-02T07:23:43+00:00</published><updated>2025-10-02T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2025-10-02-rules-for-great-software-architects</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2025-10-02-rules-for-great-software-architects/"><![CDATA[<p>What defines software design? Good software design is easy to change.</p>

<p>This is a widely accepted concept, as we can see in the following quotes:</p>

<blockquote>
  <p>“Refactoring improves the design. What is the business case of good design? To me, it’s that you can make changes to the software more easily in the future.” — Martin Fowler <a href="https://softwarequotes.com/quote/refactoring-improves-the-design--what-is-the-busin">Ref</a></p>
</blockquote>

<blockquote>
  <p>“Good Design Is Easier to Change Than Bad Design.” — The Pragmatic Programmer <a href="https://pragprog.com/titles/tpp20/the-pragmatic-programmer-20th-anniversary-edition/">Ref</a></p>
</blockquote>

<p>Therefore, to be a good architect, one must make things easier to change over time.</p>

<h2 id="1-learn-to-design-change-designing-is-not-only-about-creating-new-things">1. Learn to design change. Designing is not only about creating new things</h2>

<p>Ninety-nine percent of what you do as an architect is designing change. Get used to learning existing architectures and seeing the emerging design. Most of your career will be about changing existing software. If you fail to learn the existing architecture or fail to recognize the design that emerges from existing projects, you’ll likely become the “let’s rewrite” person.</p>

<blockquote>
  <p>“Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure.” — Melvin Conway <a href="https://martinfowler.com/bliki/ConwaysLaw.html">Ref</a></p>
</blockquote>

<h2 id="2-avoid-revolutions-no-rewrites">2. Avoid revolutions (No rewrites)</h2>

<h3 id="revolutions-may-result-in-a-better-future-but-frequently-the-revolutionary-dies">Revolutions may result in a better future, but frequently the revolutionary dies</h3>

<p>By definition, rewrites are very risky. I like to call them <em>revolutions</em>. What you’re asking your organization or customer is to spend a lot of time, money, and energy to end up, months later, in roughly the same place and hopefully better. Revolutions sometimes result in a better future, but frequently the revolutionary dies in the process.</p>

<p>For that reason, rewrites must be avoided unless they are absolutely necessary. Small, continuous improvements are much better. The new always shines, and in the computer field there will always be new things fighting for a stake in the market. They will try to get your attention, read about them, run POCs, but don’t try to follow every new trend, which would inevitably lead to never-ending projects.</p>

<h3 id="assume-that-the-person-who-wrote-the-old-code-might-have-known-something-you-dont">Assume that the person who wrote the old code might have known something you don’t</h3>

<blockquote>
  <p>“ASSUME THAT THE PERSON YOU ARE LISTENING TO MIGHT KNOW SOMETHING YOU DON’T.” — Jordan Peterson</p>
</blockquote>

<p>When writing the code that today is called legacy code, the person who wrote it had something in mind, and often this information is lost in the process. If you look at ugly code with arrogance, you will miss the opportunity to learn from it. Sometimes you’ll be lucky and they will still be around so you can talk to them and learn the reasons behind the code and why it was done the way it was. But most of the time, you have to act like an archaeologist and rebuild the context in which the code was created by looking at the final code and the commit history.</p>

<p>Don’t get me wrong: rewrites are necessary sometimes. I have led some big rewrites in my career as an architect; they often help solve problems the team is facing with the old codebase. On the other hand, most of the time they bring back old problems that the team didn’t even remember they had solved before; or the people who solved them are no longer around to explain why they did what they did.</p>

<p>In the book <em>Built to Last</em>, the authors have a chapter dedicated to the concept of “Preserve the core, stimulate progress.” This does not mean the team won’t make significant changes or try new solutions; rather, it means preserving what is well established and innovating around the core. Eventually, everything may change, but that should be the result of continuous progress rather than sudden, drastic revolutions.</p>

<p>Martin Fowler has an entire book on refactoring if you don’t feel comfortable changing a massive amount of code.</p>

<p>There are methods to change existing code and great references that would require more space than I can dedicate in this blog post. But if you are afraid of changing legacy code, you are most likely living in the <em>“Edit and Pray”</em> mode. You must change the mode to <em>“Cover and Modify,”</em> which is the correct way to deal with changing code. This is a reference to the book <a href="https://www.amazon.com/Working-Effectively-Legacy-Code-EFFECT-ebook/dp/B005OYHF0A"><em>Working Effectively with Legacy Code</em></a>, and I also talk about it in this very blog in the post <a href="https://blog.freira.dev/@mateusfreira-how-not-to-burn-out-solving-hard-problems-as-a-developer/"><em>How not to burn out when working on hard problems as a developer</em></a>.</p>

<h2 id="3-code-often-and-well-code-well">3. Code often and well (Code well)</h2>

<p>Take on at least one coding task during each iteration (sprint, month, release, etc.). This is the only way to keep your skills sharp, understand the code, and ensure the things you are designing will fit well in the already running code.</p>

<p>Set an example for the other engineers by demonstrating the standards you want to uphold when writing code. Even the best design will fail if the implementation is a disaster.</p>

<h2 id="4-sync-frequently-biweekly-architectural-review">4. Sync frequently (Biweekly Architectural Review)</h2>

<p>Open a regular forum for people to bring design challenges. I run this every other week, and any person on the team can call an emergency meeting at any time if something has to be designed in advance.</p>

<p>At most, once every other week, run a meeting specifically to talk about architectural decisions and open space for people to bring architectural problems.</p>

<h2 id="5-document-decisions-adr">5. Document decisions (ADR)</h2>

<blockquote>
  <p>“The only thing worse than failure is passing by accident.” — Everything in Its Place <a href="https://www.amazon.com.br/Everything-Its-Place-Mise-En-Place-Organize-ebook/dp/B06Y2PFG5Q">Ref</a></p>
</blockquote>

<p>If you have been in a car accident, you know that when we make mistakes, we tend to rethink everything that happened, every second, and how we could have prevented it. We rarely, or never, do the same when we have success, and there are lessons to be learned in both cases. Documenting your decisions is crucial to evaluate why a plan did or did not work.</p>

<h3 id="adr--architectural-decision-records">ADR — Architectural Decision Records</h3>

<p>This is one of the most important points: use ADRs so future architects/developers working on your codebase understand the context in which decisions were made and what trade-offs you considered when they were made. As important as documenting what decision you took is documenting the context and what problems you foresaw and are willing to deal with the consequences that may come.</p>

<p>Every hard decision is controversial; otherwise it would be trivial and wouldn’t even be a decision. Therefore, it is important to document the controversy and why you took the decision you took.</p>

<p>ADRs are a simple yet powerful way to document decisions, with a template to capture the context, consequences, and alternative directions considered.</p>

<h2 id="6-use-more-than-one-architectural-framework-architecture-style-is-not-a-religion">6. Use more than one architectural framework (Architecture style is not a religion)</h2>

<p>I know many architects who focus on only one source for architectural style. Having only one tool for all problems rarely yields amazing solutions. To be a good architect, one must know more than one architectural framework.</p>

<ul>
  <li>Hexagonal Architecture</li>
  <li>Clean Architecture</li>
  <li>Microservices architecture</li>
  <li>iDesign</li>
  <li>Event-Driven Architecture</li>
  <li>Microkernel Architecture</li>
  <li>etc.</li>
</ul>

<p>Do not let architectural style become your religion. Read all of them, take the good parts, choose one that is close to your problems, and apply them in different contexts so you can learn where they fit and where they won’t.</p>

<h2 id="7-read-and-write-book-club-and-internal-blog-personal-blog-notes">7. Read and Write (Book club and internal blog, personal blog, notes)</h2>

<p>Read the library documentation, good books (also the ones you don’t love but are well respected in the field), and argue from references and evidence.</p>

<h3 id="know-the-basics-or-at-least-have-a-good-understanding-of-what-they-mean">Know the basics (Or at least have a good understanding of what they mean)</h3>

<p>For each topic, I will provide a reference. Please do not feel obligated to read them all from beginning to end, and also do not limit yourself to the list I am providing here. Seek out other sources that will enhance your knowledge. (Check the reference links, some of them are old reads)</p>

<ul>
  <li>Distributed systems <a href="https://www.amazon.com.br/Designing-Data-Intensive-Applications-Reliable-Maintainable-ebook/dp/B06XPJML5D/ref=sr_1_1?__mk_pt_BR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;crid=NBCFL9E7ORR6&amp;dib=eyJ2IjoiMSJ9.rEpJI0XyUX-wShpc1aQCycqqhs8HaFL_afIYHA9yhe1wTza7GS5Ibzdt0_z6ZqONEzBE5cqPmhlvNzuoOMrYPLLYuvzJOeXzZJHfiJeBB8b3MxEZPhHaYlmfM0ppaAZQgYTyzybIg1PNlPHG3Pcj_g.XZDlvvkYbouLdRFhbAp-IeAtTQMsLxJh6AZOt902gbw&amp;dib_tag=se&amp;keywords=desining+data+intensive+application&amp;qid=1758998136&amp;s=books&amp;sprefix=desining+data+intensive+ap%2Cstripbooks%2C861&amp;sr=1-1">Ref</a></li>
  <li>Design patterns <a href="https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?dib=eyJ2IjoiMSJ9.mTRaTOPYqsPcUsGD8azntQP7U0dev0vjzfyX1Yj7tw_kuCM8nqctgxiD9dEFYIxmpmPf3X2PXQkO2My95WQtl8MnYhX296jKeOxHT-t-sEhRfbyO7cqugD7EJP8e24MIOCko5wRKOwYNnOuLrgI4AD8ArBAnkZcZOp2MAWoAnJMafzaA5Mhh6soPLJE3uow3-DdpgYb7b5Dg-kOxM6oS-_SPkSrcZUcKGADhSoslls8.U7guZ5WIhTAIDf3N8sLoBgQF4Px-VhPX98N6sG4Q9Lo&amp;dib_tag=se&amp;keywords=Design+patterns&amp;qid=1758998262&amp;s=books&amp;sr=1-1">Ref</a></li>
  <li>Database theory <a href="https://www.amazon.com/Database-Internals-Deep-Distributed-Systems-ebook/dp/B07XW76VHZ/ref=sr_1_3?crid=1HE6VLNZ9V1ZE&amp;dib=eyJ2IjoiMSJ9.w71ajn_w7LezEpBtO8JKVlvMy8l-Qxem7TNTx_9XPWs2YO5MwugMZyLY6-kW9Q8nAOoL8KvYeGphu0O0K-Cb1j5mMSseC3Ex0bXepJuZtCwtEJfQWKbjjRGMNnwVoXUTTeSvc_XfPV8BprmI1BMrum3UyxafvawB7j1cJq9TfoTQAqp5qS4r5r26DPIZhUfx9oPBCFNGNPfaBM8NM34opP9I_cAUpGnBl0yCMMW7XQE.yBB3CEVjRRLffBR54NrlKwCW4zXWYP4a2ZlGeWHyxJ8&amp;dib_tag=se&amp;keywords=database&amp;qid=1758998285&amp;s=books&amp;sprefix=d%2Cstripbooks-intl-ship%2C856&amp;sr=1-3">Ref</a></li>
  <li>Network theory <a href="https://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional-ebook/dp/B00666M52S/ref=tmm_kin_swatch_0">Ref</a></li>
  <li>Formal verification <a href="https://www.amazon.com.br/Principles-Model-Checking-Christel-Baier/dp/026202649X">Ref</a></li>
  <li>Automata theory <a href="https://www.amazon.com.br/Introduction-Automata-Theory-Languages-Computation/dp/0321455363">Ref</a></li>
</ul>

<p>Knowing the basics will help you to evaluate any technology, even if it is brand new and the problem it is trying to solve is not yet clear. For example, a web developer can still perform well without knowing much about TCP/IP or any other network theory or protocol. However, if they do know it, many problems can be avoided, such as preferring one request to bring more information rather than many requests bringing a small amount of information.</p>

<h3 id="notes">Notes</h3>

<ul>
  <li>Take notes and share them with the team. (I have way too many posts about this, check out the other posts about notes for more details)</li>
</ul>

<h2 id="8-keep-an-eye-on-the-future-tech-radar">8. Keep an eye on the future (Tech radar)</h2>

<p>Research, experiment, and drive the future of the tech in your company. Things move fast and you, as the architect, have the responsibility to ensure the team and the company take advantage of new technologies that emerge in the market. That does not mean you need to rewrite your frontend in every framework that is released every other month (re-read my first rule if you need).</p>

<p>At leas once an year update the company’s tech radar, TW has a great template you can follow <a href="https://www.thoughtworks.com/radar/byor">Tech radar example</a></p>

<h2 id="9-dont-take-yourself-too-seriously-be-humble">9. Don’t take yourself too seriously (Be humble)</h2>

<p>Interesting ideas come from everyone; even the most junior engineers on the team can bring the most interesting ideas. In fact, innovations often come from newcomers. Don’t get me wrong, specialists will have a view of the problems already documented in the literature and academia, but a new person may bring a perspective that by not limiting their imagination may lead to great solutions.</p>

<p>Listen to everyone’s ideas carefully, assess them, challenge them, and let them take shape no matter who they come from. Decide, document the decision, and move on.</p>

<h2 id="10-bonus-experiment">10. (Bonus) Experiment</h2>

<p>It takes time to become an architect, and it is not easy to train new architects. It may take years of formal training to get the academic background needed, and after that a couple of years experimenting in small and medium-size projects.</p>

<p>I struggle to see how any person could become a good architect without designing at least a handful of systems or making significant changes in big systems and dealing with the consequences of those decisions for at least five years.</p>

<p>That is why, when mentoring, I advise creating personal projects with paid users. This allows individuals to see how small problems progress and grow over time. Often, the trade-offs only prove to be good or bad after years. Sometimes this happens only after a new tech cycle (such as frameworks becoming obsolete or technological disruptions). Moreover, if you only design for your job, you may not be there to see all the consequences of your decisions.</p>

<h2 id="closing-thoughts">Closing thoughts</h2>
<p>This post focuses on the non-obvious things you need to do to become a great architect. Every architecture book will teach you how to design greenfield systems, and it’s not hard to find architects who don’t code (or even look at code) for years; in my opinion, that’s a clear mistake.</p>

<p>Use this as a guide for your journey. If you’re junior or just starting your career, don’t obsess over every detail. Take what you can remember, apply it, and come back in a few months or years to revisit what your next step could be.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Why I am using Off-grid Solar energy in my Home office</title><link href="http://blog.freira.dev/@mateusfreira-2025-05-07-why-I-am-using-off-grid-solar-energy/" rel="alternate" type="text/html" title="Why I am using Off-grid Solar energy in my Home office" /><published>2025-05-07T07:23:43+00:00</published><updated>2025-05-07T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2025-05-07-why-I-am-using-off-grid-solar-energy</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2025-05-07-why-I-am-using-off-grid-solar-energy/"><![CDATA[<p>I don’t trust the grid, even though energy in Brazil has been improving. The last time we had significant issues with not enough energy was around <a href="https://pt.wikipedia.org/wiki/Crise_do_apag%C3%A3o#:~:text=A%20crise%20do%20apag%C3%A3o%20foi,do%20presidente%20Fernando%20Henrique%20Cardoso.">2002</a>.</p>

<p>In the city or in the neighborhood, it is normal to have issues from time to time. In this blog have wrote in the past about having a city blackout in the day of a very important meeting <a href="https://blog.freira.dev/@mateusfreira-2022-04-04-are-you-working-remotely-you-should-be-ready-to-hit-the-road-at-any-time-in-2022/">in 2022</a>. Even having StarLink at that date did not save me from having a hard time to complete my working day as expected.</p>

<p>Not too long ago, there was a huge incident in <a href="https://x.com/mateusfreira/status/1916817962201239872">Portugal and Spain</a> where there was no energy.</p>

<p>How not to be impacted by these small or big incidents?</p>

<p>Off-grid energy is the solution. Like any other system, redundancy is necessary, and solar power is currently the most convenient option.</p>

<p>Today, it is inexpensive to purchase solar panels. In Brazil, you can buy panels for $100 that will generate approximately $1 of energy per day. You will also need a battery to store energy for use at night and when the sun is not shining.</p>

<p>After some research, I have learned that the best battery available today is a LifePo4 battery, which is already cost-effective to acquire.</p>

<p>If you do not want to make this a hobby, I advise you to buy an out-of-the-box solution like EcoFlow (my first one was an EcoFlow Delta 2 with an extra battery). These are extremely easy to set up. All you need is a solar panel (it does not need to be the expensive flexible ones they sell). Any panel in the same voltage range will work like a charm.</p>

<p>It was so easy to get it to work that I decided to learn more about this field. I put together a system myself using other components. Today, I have 2 MPPT charge controllers, 2 24v inverters, and 4 LifePo4 batteries on a second system connected to 2 strings of panels with 1.1K and 600w running +75% of my house. That is a conversation for a future post, by doing that you can save a lot of money and having a lot of fun to get it to work.</p>

<p>In conclusion, there is no magic in obtaining a secondary source of energy today. In future ports, I may bring my own setup and learn how to make it work technically. For now, if you need to search for Ecoflow or Bluetti and see how easy it is to set them up to work. I would advise buying one twice as big as the one you think you need. You will thank me later. Alternatively, take some time for a DIY project and save over $3,000 to get a project that can power 99% of your house.</p>

<p>I don’t think I will ever use only grid energy again. I am already planning to make my house completely off-grid in the next few years once I buy my “forever home.” It is a relief to see the whole city or neighborhood go dark and still be able to watch your favorite Netflix show with your wife before bed without worrying. That has happened twice since I start using Off-grid energy in the last 6 months. I am also paying 75% less to the grid energy company, even tho money was not the factor of this project.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Yes it is possible. But is it worth it?</title><link href="http://blog.freira.dev/@mateusfreira-2025-02-28-yes-it-is-possible-but-is-it-worth-it/" rel="alternate" type="text/html" title="Yes it is possible. But is it worth it?" /><published>2025-02-28T07:23:43+00:00</published><updated>2025-02-28T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2025-02-28-yes-it-is-possible-but-is-it-worth-it</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2025-02-28-yes-it-is-possible-but-is-it-worth-it/"><![CDATA[<p>Many times in your career as a software developer you will be asked if something is possible.</p>

<p>The answer is almost always yes. But that is rarely the question you are really being asked. The real question is: Is it worth it?</p>

<p>Let me give you one concrete example.  I will describe a conversation between me and my partner.</p>

<p><em>My partner</em>: It is possible to reduce the image size of the images we store in our system? Compacting them during the upload? Or maybe we could use some service to remove it from the disk?</p>

<p><em>Me, if I were inexperienced</em>: Yes, of course! There is this Scala lib that can do it. We can also migrate our storage to S3 and  use cold storage for the images that are not being accessed.</p>

<blockquote>
  <p>Right there. I just created several hours of work to myself. And now we would need to worry about security of the new system, maybe new cloud bill to pay. Risk of waking up with a 10K bill from AWS. And so on.</p>
</blockquote>

<p>Now, what did I really answer?</p>

<p><em>Me in reality</em>: Yes, it is possible, but why would we do it now? How much is it costing us today? How much would cost us to grow it 10 times?</p>

<p><em>My partner</em>: Today we have 160Gb and only 3 clients are using over 74G.</p>

<blockquote>
  <p>I went and checked the cost of disk in Linode (Our cloud storage) and it would cost 100 USD to increase 1T of disk.</p>
</blockquote>

<p><em>Me</em>: It is not worth it. I am not going to do it. With just two customers, we can pay for ten times that amount (Today, we have hundreds of customers).</p>

<p>My partner laughed and we changed subjects.</p>

<p>This conversation could have gone in many directions. If I were inexperienced, or had nothing better to do with my time (like writing this blog, LOL).</p>

<p>This is how I manage to run a side project with hundreds of customer for over 10 years, while having a full time job, family, my open source project and hobbies. I know how to choose my battles.</p>

<p>I love to give example with my own SaaS software because I will deal with the gains and losses of that decision, and if that means that I will have to get 1K USD less a year and have more time to work on the more interesting things so be it.</p>

<p>When working for someone else you not always have all the information to make the best decision. But you should always ask the questions and express exactly how much will something cost. Not only in time but also in infrastructure, money, and so on.</p>

<p>Next time someone asks you if something is possible, remember to ask yourself, “Is it worth it?” and go find the answer.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Throw Less at the Problem</title><link href="http://blog.freira.dev/@mateusfreira-2025-01-28-throw-less-at-the-problem/" rel="alternate" type="text/html" title="Throw Less at the Problem" /><published>2025-01-28T07:23:43+00:00</published><updated>2025-01-28T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2025-01-28-throw-less-at-the-problem</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2025-01-28-throw-less-at-the-problem/"><![CDATA[<p>A few weeks ago, I was on a call with one of my mentees and he was creating a plan for a consultancy project he was working on. They were having issues with pages taking more than 30s.</p>

<p>He had a great plan with many steps on how to implement a data warehouse and how they would clean the transactional tables every now and then to keep it “small”.</p>

<p>After hearing his plan, and giving him some architecture advice on the design and where it could go wrong, I proposed him to try something 100x simpler.</p>

<p>Analyze the queries and make sure every query gets to an index. Preferably a composite index that will meet the query fields. We talked about it for a while, I took some time to explain why that would work and how indexes work on databases (nerds).</p>

<p>And now I just got a message from him, “I just got a message from my customer Manager thanking me, one simple index improved the time to load one of the main pages from 30s to ~1s”.</p>

<p>Money saved, stress saved, and the simplicity wins for all. When trying to solve a problem, try to consider what would be a small change that could maybe solve this situation, that may be a great or even the best solution.</p>

<h2 id="source">Source</h2>
<p><a href="https://www.amazon.com.br/Rework-Jason-Fried/dp/0307463745">Throw Less at the Problem</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Book review Patterns of Distributed Systems which ones NunDB uses</title><link href="http://blog.freira.dev/@mateusfreira-2024-08-25-book-review-patterns-of-distributed-systems-which-ones-nundb-uses/" rel="alternate" type="text/html" title="Book review Patterns of Distributed Systems which ones NunDB uses" /><published>2024-08-25T07:23:43+00:00</published><updated>2024-08-25T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2024-08-25-book-review-patterns-of-distributed-systems-which-ones-nundb-uses</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2024-08-25-book-review-patterns-of-distributed-systems-which-ones-nundb-uses/"><![CDATA[<p>In software Naming things is hard, and a pattern is giving a problem a name, I love the quote from the book, “A Pattern Language” “Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.” Christopher Alexander.</p>

<p>The new generation of programmers seems not to like software patterns, or Design Patterns for that matter, maybe because they are related to object orientation or bureaucracy. Yet, there is great value when we can all agree on a name for a problem, that means when I say let’s implement “Heartbeat” on this system, I don’t need to explain the entire problem before everyone in the conversation is thinking about the same thing, and it improves <em>communication</em> a lot.</p>

<p>Reading this book was great and gave me the opportunity to think about the solutions I implemented for the problems I found on the way while implementing NunDB. At first, I thought that there would be little to no match to my implementations, but I could find many of them in my code base: Segmented log, Leader and Follower, Replicated Log, Idempotent Receiver, and others. And a few that I am planning to implement for a while and now I have a name to give them, like “Majority Quorum” for writes.</p>

<p>The rest of this post may follow a different standard and are more like comments and bookmarks of where or how NunDB implemented the pattern, so there is no need to read them in order you can read the ones that may get your attention.</p>

<h2 id="segmented-log-chapter-4">Segmented log (Chapter 4)</h2>
<p>NunDB implements segmented log to divide oplog into 10 smaller files, making it simpler to manipulate and manage files. Also improving issues with disk space and performance. <a href="https://github.com/mateusfreira/nun-db/pull/102/files#diff-1ecd79b0edbd75ca1397db1803ca91cf12d19c7459ef558f828da0d836fae710R751">Here</a> is where we implemented it.</p>

<h2 id="leader-and-follower-chapter-6">Leader and Follower (Chapter 6)</h2>
<p>NunDB implements leader election to ensure writes goes to a single central node, called primary. <a href="https://github.com/mateusfreira/nun-db/blob/75ce2ae72ddec6cf0dd31c885804c63524fc2fa3/src/lib/election_ops.rs#L92">Here</a> is the implementation. though NunDB started as a single primary node, there has been implementations to move it to a multi-primary database.</p>

<ul>
  <li>Having multiple primaries will allow it to scale it horizontally in reads and writes.</li>
</ul>

<p>The idea is to have one leader per shard? Or per database or key? This is yet to be defined. Or not to have leader at all the deal with conflicts just like our arbiter feature.</p>

<h2 id="heartbeat-chapter-7">Heartbeat (Chapter 7)</h2>

<ul>
  <li>NunDB still not implemented this but it is on the plan, today we failed a replication connection from the replicas and it would be easy to implement it.</li>
</ul>

<p>Today, we expect an event to try to access the other node. Only then will we disconnect it. It is being a while I want to implement this feature in NunDB so today I decided to create an <a href="https://github.com/mateusfreira/nun-db/issues/104">issue</a> to implement it, I will probably soon be working on it.</p>

<h2 id="majority-quorum-chapter-8">Majority Quorum (Chapter 8)</h2>

<ul>
  <li>NunDB does not implement majority quorum so to speak, we do have something pretty close <a href="https://github.com/mateusfreira/nun-db/blob/75ce2ae72ddec6cf0dd31c885804c63524fc2fa3/src/lib/bo.rs#L1022">Here</a>, where we only remove the transaction from the pending list when it has been acknowledged by all replicas. This can be used to create similar logic to majority quorum transactions.</li>
</ul>

<p><img src="https://notes-blog-prints.us-east-1.linodeobjects.com/test/1722470282717-Screenshot%202024-07-31%20at%208.57.48%E2%80%AFPM.png" alt="" /></p>

<p>All the consensus algorithms are based on the majority quorum principle Raft, Zab, and Paxos.</p>

<h2 id="replicated-log-chapter-12">Replicated Log (Chapter 12)</h2>
<p>NunDB uses in it <a href="https://github.com/mateusfreira/nun-db/blob/75ce2ae72ddec6cf0dd31c885804c63524fc2fa3/src/lib/replication_ops.rs#L1">Here</a>. This is a very common patter, we implemented it based on learning from databases like MongoDB but also using minor optimizations focused on performance. Worth reading the post about the implementation in <a href="https://blog.freira.dev/@mateusfreira-a-fast-to-sync-search-and-space-optimized-replication-algorithm-written-in-rust-the-Nun-db-data-replication-model/">A fast-to-sync/search and space-optimized replication algorithm written in rust, The Nun-db data replication model</a></p>

<h2 id="single-update-queue-chapter-13">Single Update Queue (Chapter 13)</h2>
<p>NunDB uses with a single thread to replicate and one thread for each node coded <a href="https://github.com/mateusfreira/nun-db/blob/75ce2ae72ddec6cf0dd31c885804c63524fc2fa3/src/lib/replication_ops.rs#L417">here</a>. <a href="https://github.com/mateusfreira/nun-db/blob/master/src/lib/replication_ops.rs#L726">Here</a> we guarantee that there is only one thread per node using channels so many thread can send messages and only one thread can process them.</p>

<!-- Read about [Riak](https://riak.com/index.html)? -->

<h2 id="idempotent-receiver-chapter-15">Idempotent Receiver (Chapter 15)</h2>

<p>NunDB uses idempotent receiver in the acknowledged operation from replica sets. When sending back an ack message to the primary, the primary stores the state of the operations and will only change the count once, even if the server sends the message multiple times.</p>

<p>We could also implement this to any client, since we hold an instance of each client. One interesting aspect of this implementation is that if an server sends a message with an id all smaller ids can be ignored as if the newer id means the client is Ok with the previous messages (this is very important to performance and save memory, today we store all ids in memory to ensure it is safe).</p>

<h2 id="follower-reads-chapter-16">Follower reads (Chapter 16)</h2>
<p>NunDB implements this by allowing clients to read from any node but only writing to the Primary node. This is by design, we guarantee that if the client watches a key, it will <em>eventually</em> receive the last value state of the key.</p>

<h2 id="version-value-chapter-17">Version Value (Chapter 17)</h2>
<p>Implemented <a href="https://github.com/mateusfreira/nun-db/blob/75ce2ae72ddec6cf0dd31c885804c63524fc2fa3/src/lib/bo.rs#L342">here</a>.
In NunDB we use value version to detect conflicts between nodes and clients (when operating offline). If there are some conflicts we must have an arbiter to solve it and the key will be on a -2 version state until this conflict is solved.</p>

<p>I like the way CouchDb solved this, creating kind of a tree, NunDB does not have that instead it go creating a list of conflicts that can later be solved by an arbiter client whenever needed.</p>

<h2 id="single-socket-channel-chapter-30">Single Socket channel (Chapter 30)</h2>
<p>To replicate from primary to secondary NunDB uses a single socket to ensure the ordering of the messages.</p>

<p>In the module <a href="https://github.com/mateusfreira/nun-db/blob/master/src/lib/replication_ops.rs#L900">replication_ops</a> we create a socket that will later be used to send the messages from primary to secondary or from primary, we later use a channel (I mean the send receiver channel class) to ensure only one thread will be handing the socket send.</p>

<h2 id="request-pipeline-chapter-32">Request Pipeline (Chapter 32)</h2>
<p>Requests do not need to wait for the response from one command to send others, this is made to ensure we can process all request in parallel, and we create an list of responses to send back to the user, in the WebSocket implementation for http requests for example has the protocol is made to be request response our trick to support multiple commands was to send all of them in the request body separated by <code class="language-plaintext highlighter-rouge">;</code>, process one by one and send all the responses in one single response.</p>

<h2 id="conclusion">Conclusion</h2>
<p>NunDB does not support data partition yet, that is why there are no mentions in the post about those chapters. I was surprised by the amount of patterns that I found in NunDB while reading this book, most of them I learned while exploring other source code or reading books about data processing but I did not have a name to give them.
I would not say this book is a must read if you are implementing a distributed system, there are others that I think will help you more (Like for example Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems).</p>

<p>It may be a great start though, if I had read this book before writing NunDB I may have identified some of the problems I had in the implementation and giving it a proper name.</p>

<h2 id="where-to-find-the-book">Where to find the book?</h2>
<p><a href="https://www.amazon.com.br/Patterns-Distributed-Systems-Addison-Wesley-Signature-ebook/dp/B0CCD3F8BH/">Amazon</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">What Makes a Great Software Engineering Team?</title><link href="http://blog.freira.dev/@mateusfreira-2024-07-29-what-makes-a-good-software-team/" rel="alternate" type="text/html" title="What Makes a Great Software Engineering Team?" /><published>2024-07-29T07:23:43+00:00</published><updated>2024-07-29T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2024-07-29-what-makes-a-good-software-team</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2024-07-29-what-makes-a-good-software-team/"><![CDATA[<p>The people!</p>

<p>A technically strong team; Working on a testable outcomes; With short feedback cycles is the <strong>recipe</strong> for success in software!</p>

<p>I truly believe in that; though I am not the original author, I heard <a href="https://x.com/unclebobmartin">Uncle Bob</a> say that many times, too, and read it in good books in different forms.</p>

<p><a href="https://x.com/ThePrimeagen">@ThePrimeagen</a> seems to agree with that statement as well partially. The only occasion we have chatted on Twitter seems to have resulted from the conversation.</p>

<p><img src="https://notes-blog-prints.us-east-1.linodeobjects.com/test/1721775679899-Screenshot%202024-07-23%20at%207.52.04%E2%80%AFPM.png" alt="" /></p>

<p>Since this seems to be an settled matter, maybe the more interesting questions are how can we create strong team?</p>

<p><em>1. Can we build strong teams from scratch?</em> In fact, I have done this at least once. Around 2013, I led and built a team of junior developers who are now principals, staff, and engineering managers in various companies worldwide.</p>

<p>At that time, we hired talented young people and would battle-test them in challenging situations at a large ERP company (Teknisa), which led to the formation of a great team.</p>

<p>It took three years to assemble that team, hiring about ten people per year and promoting the most passionate and talented individuals. Three characteristics stood out in those individuals other than technical excellence: Ownership, Accountability, and Communication.</p>

<p>Finding that level of patience in today’s industry is hard. There are few opportunities to train individuals, and today’s market (at least the USA market) is only looking to hire senior developers.</p>

<p><em>2. Can we hire only experienced developers and assemble a strong team?</em> That could be an option; the problem here is the cost. To put part of my 2013 team together again today would cost over 1M USD (for a team of ~5 people) a year only in salary, and to keep all of them excited, the thing we are working at would have to be quite challenging. This is possible, but it does require a multi-million dollar problem to justify the cost.</p>

<p><em>3. Can we strengthen an existing team of talented individuals and help most of them become top engineers?</em> This may be the way to go. It may be the perfect balance between cost and results. Since I started working for USA companies around 2016, I usually joined already-formed teams or hired senior developers and trained them to master their weaknesses.</p>

<p>Acting as a mentor and as an example, creating a writing culture, attacking the most critical problems documenting the solutions and the process, setting up the right patterns to attack any problem are my strategies for achieving that propose.</p>

<p>My intention in this post is more to document the questions than to propose answers. I documented 3 possibilities to create strong teams. I am always learning and researching new ways to improve my teams and myself You can be sure I will share in this blog what I have learned in the future, thanks!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Are developers welcome to work from coffee shops?</title><link href="http://blog.freira.dev/@mateusfreira-2024-07-10-are-developers-welcome-to-work-from-coffee-shops/" rel="alternate" type="text/html" title="Are developers welcome to work from coffee shops?" /><published>2024-07-10T07:23:43+00:00</published><updated>2024-07-10T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2024-07-10-are-developers-welcome-to-work-from-coffee-shops</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2024-07-10-are-developers-welcome-to-work-from-coffee-shops/"><![CDATA[<p>It depends! I don’t think we are welcome in  Big Cities any more in Coffee shops but there are alternatives.</p>

<p>During the last holiday (4th of July), I visited a coffee shop in Belo Horizonte, and I was planning to work for a couple of hours from there. I ended up going back to my house because I did not feel welcome to work from there. It does not seem like this is only happening in Brazil in <a href="https://www.euronews.com/travel/2024/05/15/laptop-squatters-cafes-in-europe-are-fed-up-with-space-hogging-digital-nomads">Europe</a> I have seen people complaining more than once.</p>

<p>The situation is quite different in small cities, though. When I lived in small cities like Luz-MG and Paraiso-MG, where business owners seemed to enjoy having people working there. We would spend 10 or 20 USD and work for 2 or 3 hours, usually very productive hours. People would often ask me about the work and what was I doing and show interest and even offer WIFI (most of the time I don’t ask for WIFI because I prefer to work from my 4G connections).</p>

<p>In big cities like Belo Horizonte, the owners don’t even make Wi-Fi available anymore, and I can only interpret that as not welcoming remote workers. I don’t blame them; in big cities, people often take advantage of these owners by buying coffee and working there for many hours, which ends up not being worth it for the coffee shops.</p>

<p>In small cities, it is common for coffee shops to be nearly empty for long periods of the day, so the owners are happy to have people working there, spending money, and keeping the places moving. In big cities, the problem is the opposite. They are usually full, and the owners want to keep the tables moving, so they don’t want people working using the tables that could be serving the next customer.</p>

<h2 id="where-should-we-work-from-then">Where should we work from then?</h2>

<p>The alternative is to work from co-working spaces made for that purpose, where remote workers will be much more welcome. In BH, there are many alternatives, such as <a href="https://www.wework.com/pt-BR">WeWork</a>, <a href="https://www.regus.com.br/">Regus</a>, and <a href="https://impacthub.com/locations/belo-horizonte/">Impact Hub</a>. I have worked in all of those places, and they are great places to work from. The cost is not that high, usually between 10 and 20 USD per day, and more offer free coffee (An awful coffee, but it is free).</p>

<p><img src="https://us-east-1.linodeobjects.com/notes-blog-prints/test/1720608426978-we-work.png" alt="" /></p>

<h2 id="conclusion">Conclusion</h2>

<p>I love to change the place where I work and I think it improves my productivity when I move to different places. Nevertheless, I don’t want to be on a place where I am not welcome or that people think I am taking advantage of them. That is why I also choose to live in smaller cities where life it a calmer and where people doing business are more friendly and welcoming.</p>

<p>Most business happens in Big cities, and I understand why people want to live there if their jobs require going to the office multiple times a day. But for remote workers, we have options. Small cities sometimes offer a better quality of life, a cheaper cost of living, and fewer grampy coffee shop owners. Maybe try that the next time you visit a place.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[$desc]]></summary></entry><entry><title type="html">Code Coverage for Rust Projects with GitHub Actions</title><link href="http://blog.freira.dev/@mateusfreira-2024-06-15-code-coverage-for-rust-projects-with-github-actions/" rel="alternate" type="text/html" title="Code Coverage for Rust Projects with GitHub Actions" /><published>2024-06-15T07:23:43+00:00</published><updated>2024-06-15T07:23:43+00:00</updated><id>http://blog.freira.dev/@mateusfreira/2024-06-15-code-coverage-for-rust-projects-with-github-actions</id><content type="html" xml:base="http://blog.freira.dev/@mateusfreira-2024-06-15-code-coverage-for-rust-projects-with-github-actions/"><![CDATA[<p>I particularly don’t like using the code coverage as a metric to drive the tests I write. Nevertheless, there is a lot of value in knowing what parts of your system are covered by tests or not.</p>

<p>Rust projects have great test tools that are out of the box, like `cargo test, ‘ but do not include a code coverage tool. In this post, I will show how I introduced it to my project <a href="https://github.com/mateusfreira/nun-db">NunDb</a>.</p>

<h2 id="the-tarpaulin-tool">The tarpaulin tool</h2>

<p>Tarpaulin is the tool I chose; tarpaulin is not in a stable version yet, so make sure to make a version that works for your case. Read more about it in the <a href="https://github.com/xd009642/tarpaulin">tarpaulin repo</a>.</p>

<h2 id="install-tarpaulin">Install tarpaulin</h2>

<pre class="code" data-lang="bash">
cargo install cargo-tarpaulin
</pre>

<p>In my case I had to install the nightly version of the tool, so I had to run the following:</p>

<pre class="code" data-lang="bash">
cargo +nightly install cargo-tarpaulin
</pre>

<p>By the time I am writing this post, the latest version of tarpaulin is <code class="language-plaintext highlighter-rouge">v0.30.0</code>.</p>

<h2 id="running-it-locally">Running it locally</h2>

<p>Starting from the simplest case, to run all the tests, run the next command in the base of your project:</p>

<pre class="code" data-lang="bash">
cargo tarpaulin
</pre>

<p>That may work for your case, but it did not work in my case, I have many tests that are not well suited to run in parallel because they write to disk (NunDb is a database and all tests run in the default config saving to the same place), so I had to run the tests with only one thread, like this:</p>

<pre class="code" data-lang="bash">
cargo tarpaulin -- --test-threads=1
</pre>

<h2 id="ignoring-performance-tests">Ignoring performance tests</h2>

<p>It still did not run all tests successfully. As tarpaulin has to calculate the coverage, which slows down the tests quite a bit. Therefore, I had to skip some performance tests by adding <code class="language-plaintext highlighter-rouge">#[cfg(not(tarpaulin))]</code> in the tests I wanted to skip, like the following:</p>

<pre class="code" data-lang="rust">
    #[test]
    #[cfg(not(tarpaulin))]
    fn restore_should_be_fast() {
    // ...
    }
</pre>

<h2 id="checking-the-e2e-tests">Checking the e2e tests</h2>

<p>That was progress, but my E2E tests were still not working because in order to run all tests for NunDb, I had to run multiple instances of the database and kill the process at the end of each test. To support that, You have to enable the ` –engine llvm` flag in the tarpaulin command since the default engine “relies on the sigtrap signal to catch when the instrumentation points are hit” <a href="https://github.com/xd009642/tarpaulin?tab=readme-ov-file#nuances-with-llvm-coverage">read more here</a>.</p>

<p>Additionally, to report the code coverage from the running process called in my E2E tests, I had to add the <code class="language-plaintext highlighter-rouge">--follow-exec</code> flag.</p>

<p>Here is the final command I used to run the tests:</p>

<pre class="code" data-lang="bash">
cargo tarpaulin --engine llvm --follow-exec -- --test-threads=1
</pre>

<p>All tests were running locally as expected now \o/.</p>

<p>By default, tarpaulin will force you to clean the build, which is most likely what you want for CI, but it slows down quite a bit for testing locally, so you may want to add the flag <code class="language-plaintext highlighter-rouge">--skip-clean</code> to speed it up when running locally.</p>

<p>It would look like the following:</p>

<pre class="code" data-lang="bash">
cargo tarpaulin --engine llvm --follow-exec --skip-clean -- --test-threads=1
</pre>

<h2 id="running-it-on-github-actions">Running it on GitHub Actions</h2>

<p>At this point, I was happy locally. Let’s start the work to get it to run on GitHub Actions.</p>

<p>The first step is to create a <code class="language-plaintext highlighter-rouge">.github/workflows/coverage.yml.</code> That file will be used to run the tests and push the result to Codecov.</p>

<p>For that, you will need three steps:</p>

<h4 id="1-checkout-the-repository">1. Checkout the repository</h4>
<p>This is the most straightforward step. You need to add the following lines to your workflow file:</p>
<pre class="code" data-lang="yaml">
      - name: Checkout repository
        uses: actions/checkout@v2
</pre>
<h4 id="2-run-the-tests-with-tarpaulin--where-you-can-pass-the-flags-you-want">2. Run the tests with tarpaulin  (where you can pass the flags you want)</h4>
<p>This one is a little bit more complex, first I set the environment variables I need to run the tests, <code class="language-plaintext highlighter-rouge">TIME_TO_START</code> and <code class="language-plaintext highlighter-rouge">NUN_ELECTION_TIMEOUT</code> and I also use the command we came up with before:</p>

<pre class="code" data-lang="yaml">
      - name: Generate code coverage
        env:
          TIME_TO_START: 4
          NUN_ELECTION_TIMEOUT: 3000
        run: |
          mkdir dbs&amp;&amp;cargo +nightly tarpaulin --follow-exec --engine llvm --verbose --all-features --workspace --timeout 120 --out xml -- --test-threads=1
</pre>
<h4 id="3-upload-the-results-to-codecov-needs-setup-in-the-codecov-website-prior">3. Upload the results to Codecov (Needs setup in the Codecov website prior)</h4>

<p>Now we are close, it is time to upload the result to Codecov. For that you will need to add the following lines to your workflow file:</p>

<pre class="code" data-lang="yaml">
      - name: Upload to codecov.io
        uses: codecov/codecov-action@v2
        with:
          token: $ # not required for public repos
          fail_ci_if_error: true
</pre>

<p>To get the <code class="language-plaintext highlighter-rouge">CODECOV_TOKEN,</code> go to the Codecov website, authenticate with your GitHub account, find your repo in the list, and click on <em>Configure</em>; on the next page, you will see the token to be copy pasted into the GitHub Secrets.</p>

<p><img src="https://notes-blog-prints.us-east-1.linodeobjects.com/test/1718454660550-Screenshot%202024-06-15%20at%209.30.55%E2%80%AFAM.png" alt="" /></p>

<p>To set up the secret in GitHub, go to your repository, click on <em>Settings -&gt; Secrets and variables -&gt; Actions</em>, and add a new secret.</p>

<p><img src="https://notes-blog-prints.us-east-1.linodeobjects.com/test/1718454783807-Screenshot%202024-06-15%20at%209.33.00%E2%80%AFAM.png" alt="" /></p>

<p>The final file should look like this:</p>

<pre class="code" data-lang="yaml">
name: Code Coverage
on:
  push:
    branches:
      - master
  pull_request:
jobs:
  coverage:
    name: coverage
    runs-on: ubuntu-latest
    container:
      image: xd009642/tarpaulin:develop-nightly
      options: --security-opt seccomp=unconfined
    steps:
      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Generate code coverage
        env:
          TIME_TO_START: 4
          NUN_ELECTION_TIMEOUT: 3000
        run: |
          mkdir dbs&amp;&amp;cargo +nightly tarpaulin --follow-exec --engine llvm --verbose --all-features --workspace --timeout 120 --out xml -- --test-threads=1
      - name: Upload to codecov.io
        uses: codecov/codecov-action@v2
        with:
          token: $ # not required for public repos
          fail_ci_if_error: true
</pre>

<p>Now, when you push code, you should see the tests running and the coverage being uploaded to Codecov.</p>

<p><img src="https://notes-blog-prints.us-east-1.linodeobjects.com/test/1718455074429-Screenshot%202024-06-15%20at%209.37.38%E2%80%AFAM.png" alt="GitHub UI" /></p>

<p><img src="https://notes-blog-prints.us-east-1.linodeobjects.com/test/1718455168767-Screenshot%202024-06-15%20at%209.39.23%E2%80%AFAM.png" alt="Codecov UI" /></p>

<h3 id="adding-the-badge-to-the-readme">Adding the badge to the README</h3>
<p>In your Codecov project page, you will find a link to <em>Settings</em> and then <em>Badge</em>; there, you will find the markdown to add to your README file.</p>

<p>Something like this:</p>
<pre class="code" data-lang="markdown">
[![codecov](https://codecov.io/YOUR_REPO/branch/master/graph/badge.svg?token=YOUR_TOKEN)](https://codecov.io/gh/YOUR_REPO)
</pre>

<h2 id="conclusion">Conclusion</h2>

<p>Adding cover coverage to your project can help you monitor the modules your automated tests are neglecting. Keep in mind that a single number does not define the quality of your project. Enjoy the coding and use the tools for what they are good for.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[I particularly don’t like using the code coverage as a metric to drive the tests I write. Nevertheless, there is a lot of value in knowing what parts of your system are covered by tests or not.]]></summary></entry></feed>