<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Criteo Tech Community</title>
    <description>The latest articles on Forem by Criteo Tech Community (@criteo_tech_community).</description>
    <link>https://forem.com/criteo_tech_community</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3522319%2F0f038b9e-c47d-4766-8407-a9701132243c.png</url>
      <title>Forem: Criteo Tech Community</title>
      <link>https://forem.com/criteo_tech_community</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/criteo_tech_community"/>
    <language>en</language>
    <item>
      <title>Why And How We Organize Coding Dojos</title>
      <dc:creator>Criteo Tech Community</dc:creator>
      <pubDate>Wed, 17 Sep 2025 07:01:56 +0000</pubDate>
      <link>https://forem.com/criteo_tech_community/why-and-how-we-organize-coding-dojos-3ile</link>
      <guid>https://forem.com/criteo_tech_community/why-and-how-we-organize-coding-dojos-3ile</guid>
      <description>&lt;h4&gt;
  
  
  Author: Guillaume Turri-Werth
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AB2V6eSTbusozQ8Xl" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AB2V6eSTbusozQ8Xl" alt="Two men looking at a monitor with code lines." width="1024" height="683"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Flipsnack on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you are looking for a way to both have fun and improve your coding skills (or those of your team), I have some good news: &lt;strong&gt;we have open-sourced a repo that contains material to organize coding dojos! 🎉 👇&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/criteo/coding-dojo" rel="noopener noreferrer"&gt;GitHub - criteo/coding-dojo: Some content to organize some coding dojos&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sure, there is already a lot of such material available online, but this one is still original. I’ll explain why in a minute. Before that, I need to explain how we proceed with coding dojo at Criteo, and share the good practices that help us, in our setup, organize regular coding dojos, and keep the momentum for several years. But even before that, I probably should explain what coding dojos are.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codingdojo.org/practices/WhatIsCodingDojo/" rel="noopener noreferrer"&gt;A lot has been said&lt;/a&gt; on &lt;a href="https://se-radio.net/2024/08/se-radio-629-emily-bache-on-katas-and-the-importance-of-practice/" rel="noopener noreferrer"&gt;this topic already&lt;/a&gt;, but I should at least ensure that people who are not yet familiar with this topic get up to speed. If you are already knowledgeable about it, you can skip the first part.&lt;/p&gt;

&lt;h3&gt;
  
  
  What coding dojos are
&lt;/h3&gt;

&lt;p&gt;Coding dojos are basically a practice to improve developer skills.&lt;/p&gt;

&lt;p&gt;In its most basic form it is pretty straightforward: you decide on simple a topic (for instance: implementing a simplified &lt;a href="https://en.wikipedia.org/wiki/Brainfuck" rel="noopener noreferrer"&gt;brainfuck&lt;/a&gt;interpreter, a &lt;a href="https://en.wikipedia.org/wiki/Mastermind_(board_game)" rel="noopener noreferrer"&gt;master-mind&lt;/a&gt; solver, a &lt;a href="https://codingdojo.org/kata/RomanCalculator/" rel="noopener noreferrer"&gt;roman calculator&lt;/a&gt;, …), you work on it for up to a couple of hours, and afterwards you throw away (or archive) what you did -because what matters is the journey, not the destination.&lt;/p&gt;

&lt;p&gt;That’s basically it. Then you can adapt the practical details to what works for you. You can, for instance, practice alone, in pairs, or in a group. You can do it at home, at work with teammates, or outside of work with peers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A_wVv2gULXR0e4C6C" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A_wVv2gULXR0e4C6C" alt="The sentence: “Practice makes perfect” on Scrabble letters" width="1024" height="768"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Brett Jordan on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Coding dojos can serve different purposes (and are hence suitable regardless of the background of the participants):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting familiar with software engineer practices -&lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;TDD&lt;/a&gt;, pair programming, refactoring, …&lt;/li&gt;
&lt;li&gt;Experimenting with unfamiliar tech stacks, such as doing a dojo in Scala as a C# engineer.&lt;/li&gt;
&lt;li&gt;Discovering good practices from your teammates, such as features in your IDE that you may not be aware of.&lt;/li&gt;
&lt;li&gt;Coaching juniors -who can be inspired by your code wizard skills.&lt;/li&gt;
&lt;li&gt;Developing relationships with people you don't currently work with directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And above all: &lt;strong&gt;coding dojos are fun! 💻&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Our ritual
&lt;/h3&gt;

&lt;p&gt;To make it more concrete, and to explain how we managed to keep the momentum during several years, I’ll give some more practical clues about how we proceed at Criteo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A2BxSfM590GbSOvIK" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2A2BxSfM590GbSOvIK" alt="A notebook with a list of checkboxes" width="1024" height="681"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Glenn Carstens-Peters on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Before the dojo
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;We have a public Slack channel that anyone can join, dedicated to the organization of coding dojos.&lt;/li&gt;
&lt;li&gt;We organize the dojos between 12:45 and 14:00, ensuring that many of us can attend - since we usually don’t have meetings at that time -and also because evening sessions don't work for parents. In practice:&lt;/li&gt;
&lt;li&gt;We have lunch between 12h and 12h30~12h45.&lt;/li&gt;
&lt;li&gt;And then we code together until 14h. (&lt;em&gt;Keep this timing in mind, it may have some importance later 😄)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The responsibility of the organization of the next dojo is split between two roles: one that we call the &lt;em&gt;Master of Ceremony&lt;/em&gt; and one that we call the &lt;em&gt;Master of Dojo&lt;/em&gt;. Those roles are assigned to volunteers. Ideally, they change every time.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;Master of Ceremony&lt;/em&gt; oversees the logistics. In particular, they are responsible for booking a meeting room with a big screen, on which we can connect a laptop. At some point, that person was also in charge of ordering the lunch -it may sound like a detail, but it’s an important one, as we observed that having a budget for food really boosted participation!&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;Master of Dojo&lt;/em&gt; decides on which topic we will work and the stack we will use. They are also in charge of setting up a small project with no implementation and an empty test suite, but which at least builds (so we don’t waste several minutes with that boilerplate during the session).&lt;/li&gt;
&lt;li&gt;We set up checklists for both roles, making it less intimidating to take on those responsibilities. It is also a way to document details that ensure those roles are perfectly fulfilled -for instance, that the &lt;em&gt;Master of Ceremony&lt;/em&gt; orders some vegetarian dishes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  During the dojo
&lt;/h4&gt;

&lt;p&gt;In general, we use the format called “&lt;a href="https://johnrooksby.org/papers/XP2014_rooksby_dojo.pdf" rel="noopener noreferrer"&gt;Randori&lt;/a&gt;” — a type of &lt;a href="https://en.wikipedia.org/wiki/Team_programming#Mob_programming" rel="noopener noreferrer"&gt;mob programming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In practice, we do iterations of 5 minutes. During an iteration, a single person has the keyboard and contributes to implementing the solution. The other participants follow on the screen and give advice. At the end of the iteration, the next person takes the keyboard and continues the code where the previous participant ended the iteration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2ACKmcu0W29nfsK_c4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2ACKmcu0W29nfsK_c4" alt="A person looking at a screen with code" width="1024" height="683"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by charlesdeluvio on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We continue like this for roughly 1h15~1h30. It is a bit short, but it fits our constraints. We try to keep between 5 and 10 minutes at the end to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Debrief (&lt;em&gt;what did we learn? What went well? What ended up being poor decisions and how we could have proceeded differently, …&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Get volunteers for the roles of &lt;em&gt;Master of Ceremony&lt;/em&gt; and &lt;em&gt;Master of Dojo&lt;/em&gt; for the next session&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The good practices we identified
&lt;/h3&gt;

&lt;p&gt;Launching a coding dojo initiative at work is easy, and it's exciting to be enthusiastic about it. However, we often lose momentum after a couple of months 😫. Unfortunately, we've been there a couple of times. We then managed to relaunch coding dojos and to keep the momentum alive for several years 🎉&lt;/p&gt;

&lt;p&gt;Here are the practices that work well in our case.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We organize dojos on a &lt;strong&gt;&lt;em&gt;regular basis&lt;/em&gt;&lt;/strong&gt;. For instance, in the past, it was every other Tuesday. Now it is more flexible as our guideline is just to ensure we organize one per month. Anything works as long as it’s not “&lt;em&gt;the next dojo occurs whenever someone is motivated enough to organize it&lt;/em&gt;” 😄&lt;/li&gt;
&lt;li&gt;If the &lt;strong&gt;&lt;em&gt;duration&lt;/em&gt;&lt;/strong&gt; is too short (say, less than 1h), we don’t have time to do anything interesting. If it is too long (say, more than 2h), it is hard to keep participants focused and interested. In practice, we do roughly 1h15 so people can go back to work at 2 PM. It’s a bit short, and that’s why we came up with the trick that… we’ll reveal just after 😊 (but if in your setup you can do up to 2h long dojos, it’s probably better)&lt;/li&gt;
&lt;li&gt;As mentioned previously, we &lt;strong&gt;&lt;em&gt;split the responsibility&lt;/em&gt;&lt;/strong&gt; of the organization. We achieve this by applying two tricks: defining two roles to organize a given session. It ensures it is not overwhelming; And we try to have different volunteers take those roles during successive sessions. That way, we have more people who know how that works, and we hence reduce the bus factor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AbVihflw94Hm2Np-f" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F0%2AbVihflw94Hm2Np-f" alt="Green darts on the target" width="1024" height="576"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Photo by Afif Ramdhasuma on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Another advantage of changing the people in charge of preparing a topic is that, over the years, we have had an interesting variety of topics. Including some interesting exotic ones (such as implementing an in-memory filesystem with a &lt;a href="https://en.wikipedia.org/wiki/Filesystem_in_Userspace" rel="noopener noreferrer"&gt;FUSE&lt;/a&gt;, experimenting with &lt;a href="https://en.wikipedia.org/wiki/Behavior-driven_development" rel="noopener noreferrer"&gt;BDD&lt;/a&gt; with &lt;a href="https://cucumber.io/" rel="noopener noreferrer"&gt;Cucumber&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/Mutation_testing" rel="noopener noreferrer"&gt;mutation testing&lt;/a&gt; with &lt;a href="https://pitest.org/" rel="noopener noreferrer"&gt;Pitest&lt;/a&gt;, or even creating music with code with &lt;a href="https://sonic-pi.net/" rel="noopener noreferrer"&gt;Sonic Pi&lt;/a&gt;, …)&lt;/p&gt;

&lt;h3&gt;
  
  
  The resources we appreciate… and why we rolled out our own
&lt;/h3&gt;

&lt;p&gt;If the &lt;em&gt;Master of Dojo&lt;/em&gt; is inspired, it can invent topics on its own: as long as it can be explained in at most a couple of minutes to participants, it’s probably ok. And for times where it lacks imagination, we can fall back on some of those resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://codingdojo.org/kata/" rel="noopener noreferrer"&gt;Coding Dojo&lt;/a&gt;: this website contains a catalog of such topics&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cyber-dojo.org/" rel="noopener noreferrer"&gt;cyber-dojo&lt;/a&gt;: This is a platform that provides tooling to do dojos remotely and collaboratively. We do not use this platform (because we already have a setup that works for us), but the neat part is that it also contains a catalog of topics&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/emilybache/GildedRose-Refactoring-Kata" rel="noopener noreferrer"&gt;Gilded Rose&lt;/a&gt;: This is a pretty nice exercise to practice refactoring. It contains a code base with several &lt;a href="https://martinfowler.com/bliki/CodeSmell.html" rel="noopener noreferrer"&gt;code smells&lt;/a&gt;. The goal is to add a feature to that code base, but to do so, the user is encouraged to refactor (and hence add tests) beforehand&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Orange-OpenSource/dojo-elephant-carpaccio" rel="noopener noreferrer"&gt;Elephant Carpaccio&lt;/a&gt;: a dojo to practice breaking a task into tiny slices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All this content could keep us busy for years… and it did!&lt;/p&gt;

&lt;p&gt;But lately, we felt that for our 1h15 dojos (which is &lt;em&gt;short&lt;/em&gt;), it was sometimes frustrating to spend “too much” time writing tests. I mean, sure, practicing TDD makes a lot of sense. But having a chance to practice other skills than just writing tests is nice too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl510zdpkbck8m7b1qcbd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl510zdpkbck8m7b1qcbd.png" alt="The classical TDD workflow as: Red tests, then Green tests, then Refactor and start all over again." width="701" height="285"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;TDD Workflow&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, we experimented with another approach: what if the &lt;em&gt;Master of Dojo&lt;/em&gt; was also in charge of writing a test suite &lt;strong&gt;&lt;em&gt;before&lt;/em&gt;&lt;/strong&gt; the dojo? This way, we can comment all tests beforehand. During the session, we uncomment them one by one and write the code to turn them green before uncommenting the next one.&lt;/p&gt;

&lt;p&gt;We gave that approach a try a couple of times… and it was great! 😃 Not only does it save time, but it also leads to more fluid sessions -because it ensures there is no ambiguity with what we try to implement.&lt;/p&gt;

&lt;p&gt;I mean, of course, it is interesting to have more classic topics once in a while (to keep practicing writing tests). But it turns out that with this approach, we are still practicing a kind of TDD -“red test, green test, refactor”. The only difference is that the participants do not write the tests. 🙂&lt;/p&gt;

&lt;h3&gt;
  
  
  What we open-sourced
&lt;/h3&gt;

&lt;p&gt;Since it takes a bit of time to set up a topic with an existing test suite, and since we appreciate this approach, we figured out we might as well share the content prepared by our &lt;em&gt;Masters of Dojo&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And that’s what we released on GitHub: a set of topics on which we worked, along with their test suite. All you need to do is clone the repository, select a topic, open the corresponding project in your IDE, and follow the instructions in the associated &lt;em&gt;README&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/criteo/coding-dojo/?tab=readme-ov-file" rel="noopener noreferrer"&gt;GitHub - criteo/coding-dojo: Some content to organize some coding dojos&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now we have only a handful of topics (mostly in C#, and a bit in Java), but we will keep adding the content we will produce.&lt;/p&gt;

&lt;p&gt;Of course, we would also gladly accept pull requests that would either add topics or add support for an existing one in another language.&lt;/p&gt;

&lt;p&gt;We hope you enjoy the content, and we would be very interested in any feedback or suggestions you might have! 👋&lt;/p&gt;




</description>
      <category>programming</category>
      <category>tdd</category>
      <category>codingdojo</category>
      <category>kata</category>
    </item>
    <item>
      <title>Importance of Graceful Shutdown in Kubernetes</title>
      <dc:creator>Criteo Tech Community</dc:creator>
      <pubDate>Wed, 10 Sep 2025 07:01:46 +0000</pubDate>
      <link>https://forem.com/criteo_tech_community/importance-of-graceful-shutdown-in-kubernetes-2ikb</link>
      <guid>https://forem.com/criteo_tech_community/importance-of-graceful-shutdown-in-kubernetes-2ikb</guid>
      <description>&lt;h4&gt;
  
  
  Author: &lt;a href="https://www.linkedin.com/in/alikhil/" rel="noopener noreferrer"&gt;Alik Khilazhev&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Have you ever deployed a new version of your app in Kubernetes and noticed errors briefly spiking during rollout? Many teams do not even realize this is happening, especially if they are not closely monitoring their error rates during deployments.&lt;/p&gt;

&lt;p&gt;There is a common misconception in the Kubernetes world that bothers me. The official Kubernetes &lt;a href="https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and most guides claim that “if you want zero downtime upgrades, just use rolling update mode on deployments”. I have learned the hard way that this simply it is not true — rolling updates alone are &lt;strong&gt;NOT enough&lt;/strong&gt; for true zero-downtime deployments.&lt;/p&gt;

&lt;p&gt;And it is not just about deployments. Your pods can be terminated for many other reasons: scaling events, node maintenance, preemption, resource constraints, and more. Without proper graceful shutdown handling, any of these events can lead to dropped requests and frustrated users.&lt;/p&gt;

&lt;p&gt;In this post, I will share what I have learned about implementing proper graceful shutdown in Kubernetes. I will show you exactly what happens behind the scenes, provide working code examples, and back everything with real test results that clearly demonstrate the difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: Hidden Errors During Pod Termination
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7nzx91zhZcYDMuZtsfEn_Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2A7nzx91zhZcYDMuZtsfEn_Q.png" alt="A funny picture of a Kubernetes pod gracefully shutting down created by ChatGPT" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;ChatGPT: draw funny picture of Kubernetes pod gracefully shutting down&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you are running services on Kubernetes, you have probably noticed that even with rolling updates (where Kubernetes gradually replaces pods), you might still see errors during deployment. This is especially annoying when you are trying to maintain “zero-downtime” systems.&lt;/p&gt;

&lt;p&gt;When Kubernetes needs to terminate a pod (for any reason), it follows this sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sends a SIGTERM signal to your container&lt;/li&gt;
&lt;li&gt;Waits for a grace period (30 seconds by default)&lt;/li&gt;
&lt;li&gt;If the container does not exit after the grace period, it gets brutal and sends a SIGKILL signal&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problem? Most applications do not properly handle that SIGTERM signal. They just die immediately, dropping any in-flight requests. In the real world, while most API requests complete in 100–300ms, there are often those long-running operations that take 5–15 seconds or more. Think about processing uploads, generating reports, or running complex database queries. When these longer operations get cut off, that’s when users really feel the pain.&lt;/p&gt;
&lt;h4&gt;
  
  
  When Does Kubernetes Terminate Pods?
&lt;/h4&gt;

&lt;p&gt;Rolling updates are just one scenario where your pods might be terminated. Here are other common situations that can lead to pod terminations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Horizontal Pod Autoscaler Events&lt;/strong&gt; : When HPA scales down during low-traffic periods, some pods get terminated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Pressure&lt;/strong&gt; : If your nodes are under resource pressure, the Kubernetes scheduler might decide to evict certain pods.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node Maintenance&lt;/strong&gt; : During cluster upgrades, node draining causes many pods to be evicted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spot/Preemptible Instances&lt;/strong&gt; : If you are using cost-saving node types like spot instances, these can be reclaimed with minimal notice.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these scenarios follow the same termination process, so implementing proper graceful shutdown handling protects you from errors in all of these cases — not just during upgrades.&lt;/p&gt;
&lt;h4&gt;
  
  
  Let’s Test It: Basic vs. Graceful Service
&lt;/h4&gt;

&lt;p&gt;Instead of just talking about theory, I built a small lab to demonstrate the difference between proper and improper shutdown handling. I created two nearly identical Go services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Basic Service&lt;/strong&gt; : A standard HTTP server with no special shutdown handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graceful Service&lt;/strong&gt; : The same service but with proper SIGTERM handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Process requests that take about 4 seconds to complete (intentionally configured for easier demonstration)&lt;/li&gt;
&lt;li&gt;Run in the same Kubernetes cluster with identical configurations&lt;/li&gt;
&lt;li&gt;Serve the same endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I specifically chose a 4-second processing time to make the problem obvious. While this might seem long compared to typical 100–300ms API calls, it perfectly simulates those problematic long-running operations that occur in real-world applications. The only difference between the services is how they respond to termination signals.&lt;/p&gt;

&lt;p&gt;To test them, I wrote a simple k6 script that hammers both services with requests while triggering rolling restart of service’s deployment. Here is what happened:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Service: The Error-Prone One&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checks_total.......................: 695 11.450339/s
checks_succeeded...................: 97.98% 681 out of 695
checks_failed......................: 2.01% 14 out of 695

✗ status is 200
  ↳ 97% — ✓ 681 / ✗ 14

http_req_failed....................: 2.01% 14 out of 696
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Graceful Service: The Reliable One&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checks_total.......................: 750 11.724824/s
checks_succeeded...................: 100.00% 750 out of 750
checks_failed......................: 0.00% 0 out of 750

✓ status is 200

http_req_failed........... ........: 0.00% 0 out of 751
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The results speak for themselves. The basic service dropped 14 requests during the update (that is 2% of all traffic), while the graceful service handled everything perfectly without a single error.&lt;/p&gt;

&lt;p&gt;You might think “2% it is not that bad” — but if you are doing several deployments per day and have thousands of users, that adds up to a lot of errors. Plus, in my experience, these errors tend to happen at the worst possible times.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, How Do We Fix It? The Graceful Shutdown Recipe
&lt;/h3&gt;

&lt;p&gt;After digging into this problem and testing different solutions, I have put together a simple recipe for proper graceful shutdown. While my examples are in Go, the fundamental principles apply to any language or framework you are using.&lt;/p&gt;

&lt;p&gt;Here are the key ingredients:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Listen for SIGTERM Signals
&lt;/h4&gt;

&lt;p&gt;First, your app needs to catch that SIGTERM signal instead of ignoring it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Set up channel for shutdown signals
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)

// Block until we receive a shutdown signal
&amp;lt;-stop
log.Println("Shutdown signal received")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This part is easy — you are just telling your app to wake up when Kubernetes asks it to shut down.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Track Your In-Flight Requests
&lt;/h4&gt;

&lt;p&gt;You need to know when it is safe to shut down, so keep track of ongoing requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Create a request counter
var inFlightRequests atomic.Int64

http.HandleFunc("/process", func(w http.ResponseWriter, r *http.Request) {
    // Increment counter when request starts
    inFlightRequests.Add(1)
    // do not forget to decrement when done!
    defer inFlightRequests.Add(-1)

    // Your normal request handling...
    time.Sleep(4 * time.Second) // Simulating long-running work
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This counter lets you check if there are still requests being processed before shutting down. It is especially important for those long-running operations that users have already waited several seconds for — the last thing they want is to see an error right before completion!&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Separate Your Health Checks
&lt;/h4&gt;

&lt;p&gt;Here is a commonly overlooked trick — you need different health check endpoints for liveness and readiness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Track shutdown state
var isShuttingDown atomic.Bool

// Readiness probe - returns 503 when shutting down
http.HandleFunc("/ready", func(w http.ResponseWriter, r *http.Request) {
    if isShuttingDown.Load() {
        w.WriteHeader(http.StatusServiceUnavailable)
        fmt.Fprintf(w, "Shutting down, not ready")
        return
    }

    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "Ready for traffic")
})

// Liveness probe - always returns 200 (we are still alive!)
http.HandleFunc("/alive", func(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(http.StatusOK)
    fmt.Fprintf(w, "I'm alive")
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation is crucial. The readiness probe tells Kubernetes to stop sending new traffic, while the liveness probe says “do not kill me yet, I’m still working!”&lt;/p&gt;

&lt;h4&gt;
  
  
  4. The Shutdown Dance
&lt;/h4&gt;

&lt;p&gt;Now for the most important part — the shutdown sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Step 1: Mark service as shutting down
isShuttingDown.Store(true)

// Step 2: Let Kubernetes notice the readiness probe failing
time.Sleep(5 * time.Second)

// Step 3: Wait for in-flight requests to finish
for inFlightRequests.Load() &amp;gt; 0 {
    time.Sleep(1 * time.Second)
}

// Step 4: Finally, shut down the server gracefully
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

if err := server.Shutdown(ctx); err != nil {
    log.Fatalf("Forced shutdown: %v", err)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ve found this sequence to be optimal. First, we mark ourselves as “not ready” but keep running. We pause to give Kubernetes time to notice and update its routing. Then we patiently wait until all in-flight requests finish before actually shutting down the server.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Configure Kubernetes Correctly
&lt;/h4&gt;

&lt;p&gt;Do not forget to adjust your Kubernetes configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Use different probes for liveness and readiness
livenessProbe:
  httpGet:
    path: /alive # Always returns OK
    port: 8080
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready # Returns 503 during shutdown
    port: 8080
  periodSeconds: 3
  failureThreshold: 2

# Give pods enough time to shut down gracefully
terminationGracePeriodSeconds: 30 # Stops routing traffic after 2 failed checks (6 seconds)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Kubernetes to wait up to 30 seconds for your app to finish processing requests before forcefully terminating it.&lt;/p&gt;

&lt;h3&gt;
  
  
  TL; DR; Quick Tips
&lt;/h3&gt;

&lt;p&gt;If you are in a hurry, here are the key takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Catch SIGTERM Signals&lt;/strong&gt; : Do not let your app be surprised when Kubernetes wants it to shut down.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track In-Flight Requests&lt;/strong&gt; : Know when it is safe to exit by counting active requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split Your Health Checks&lt;/strong&gt; : Use separate endpoints for liveness (am I running?) and readiness (can I take traffic?).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fail Readiness First&lt;/strong&gt; : As soon as shutdown begins, start returning “not ready” on your readiness endpoint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait for Requests&lt;/strong&gt; : Do not just shut down — wait for all active requests to complete first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Built-In Shutdown&lt;/strong&gt; : Most modern web frameworks have graceful shutdown options; use them!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure Terminaton Grace Period&lt;/strong&gt; : Give your pods enough time to complete the shutdown sequence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test Under Load&lt;/strong&gt; : You will not catch these issues in simple tests — you need realistic traffic patterns.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Wrap Up: Is It Worth the Extra Code?
&lt;/h3&gt;

&lt;p&gt;You might be wondering if adding all this extra code is really worth it. After all, we’re only talking about a 2% error rate during pod termination events.&lt;/p&gt;

&lt;p&gt;From my experience working with high-traffic services, I would say absolutely yes — for three reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User Experience&lt;/strong&gt; : Even small error rates look bad to users. Nobody wants to see “Something went wrong” messages, especially after waiting 10+ seconds for a long-running operation to complete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cascading Failures&lt;/strong&gt; : Those errors can cascade through your system, especially if services depend on each other. Long-running requests often touch multiple critical systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Confidence&lt;/strong&gt; : With proper graceful shutdown, you can deploy more frequently without worrying about causing problems.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The good news is that once you have implemented this pattern once, it is easy to reuse across your services. You can even create a small library or template for your organization.&lt;/p&gt;

&lt;p&gt;In production environments where I have implemented these patterns, we have gone from seeing a spike of errors with every deployment to deploying multiple times per day with zero impact on users. That is a win in my book!&lt;/p&gt;

&lt;p&gt;If you want to dive deeper into this topic, I recommend checking out the article &lt;a href="https://learnk8s.io/graceful-shutdown" rel="noopener noreferrer"&gt;Graceful shutdown and zero downtime deployments in Kubernetes&lt;/a&gt; from &lt;a href="http://learnk8s.io/" rel="noopener noreferrer"&gt;LearnKube — the Kubernetes training company&lt;/a&gt; . It provides additional technical details about graceful shutdown in Kubernetes, though it does not emphasize the critical role of readiness probes in properly implementing the pattern as we have discussed here.&lt;/p&gt;

&lt;p&gt;For those interested in seeing the actual code I used in my testing lab, I’ve published it on &lt;a href="https://github.com/alikhil/gracefull-shutdown-lab" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; with instructions for running the demo yourself.&lt;/p&gt;

&lt;p&gt;Have you implemented graceful shutdown in your services? Did you encounter any other edge cases I didn’t cover? 👀&lt;/p&gt;

&lt;p&gt;Let me know in the comments how this pattern has worked for you! 👇&lt;/p&gt;




</description>
      <category>devops</category>
      <category>softwaredevelopment</category>
      <category>kubernetes</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
