<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Kiesse_</title>
    <subtitle>Never stray from the way.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://nskm.xyz/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://nskm.xyz"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-28T00:00:00+00:00</updated>
    <id>https://nskm.xyz/atom.xml</id>
    <entry xml:lang="en">
        <title>An agent in my workflow</title>
        <published>2026-07-28T00:00:00+00:00</published>
        <updated>2026-07-28T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/claude-code-workflow/"/>
        <id>https://nskm.xyz/posts/claude-code-workflow/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/claude-code-workflow/">&lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;claWd.webp&quot; alt=&quot;claWd&quot; title=&quot;claWd&quot;&#x2F;&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Last week, I was asked how &lt;a href=&quot;https:&#x2F;&#x2F;code.claude.com&#x2F;docs&#x2F;en&#x2F;overview&quot;&gt;Claude Code&lt;&#x2F;a&gt; actually improved my productivity, past the pitch of &lt;em&gt;&quot;it writes code for you.&quot;&lt;&#x2F;em&gt; I didn&#x27;t have a sharp answer on the spot. Turns out the honest answer isn&#x27;t about writing code faster, it&#x27;s about writing the thing that does the task once, instead of re-explaining the same task every time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;claude-code-workflow&#x2F;#what-it-is&quot;&gt;What it is&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;claude-code-workflow&#x2F;#how-it-fits-your-workflow&quot;&gt;How it fits your workflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;claude-code-workflow&#x2F;#a-practical-example&quot;&gt;A practical example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;claude-code-workflow&#x2F;#when-it-s-not-a-good-fit&quot;&gt;When it&#x27;s not a good fit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;claude-code-workflow&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;what-it-is&quot;&gt;What it is&lt;&#x2F;h2&gt;
&lt;p&gt;An agentic coding tool is an interactive cli tool. You run it, from a project directory, and it can manage your &lt;em&gt;workflow&lt;&#x2F;em&gt;, directly from your terminal: reads files, greps for symbols, edits code, runs your test suite, commits changes... All of this through natural language instructions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-it-fits-your-workflow&quot;&gt;How it fits your workflow&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t hand the agent a vague goal and walk away. You point it at a concrete, bounded task: add a migration, patch a flaky test, trace where a &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;6.0&#x2F;topics&#x2F;tasks&#x2F;&quot;&gt;Django task&lt;&#x2F;a&gt; raises an exception. Your agent works best when your &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;Git&lt;&#x2F;a&gt; repository already carries conventions it can follow: an existing test pattern, a linter it can run against its own output, some pre-commits rules. Without that scaffolding, it tends to invent its own conventions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-practical-example&quot;&gt;A practical example&lt;&#x2F;h2&gt;
&lt;p&gt;Say you want to open a &lt;a href=&quot;https:&#x2F;&#x2F;support.atlassian.com&#x2F;bitbucket-cloud&#x2F;docs&#x2F;create-a-pull-request&#x2F;&quot;&gt;pull request on Bitbucket&lt;&#x2F;a&gt; once your branch is ready. The blunt way: just ask Claude Code to do it. Assuming the right credentials are already sitting in environment variables, it can go read &lt;a href=&quot;https:&#x2F;&#x2F;developer.atlassian.com&#x2F;cloud&#x2F;bitbucket&#x2F;rest&#x2F;intro&#x2F;&quot;&gt;Bitbucket&#x27;s REST API documentation&lt;&#x2F;a&gt; itself, ask you for whatever inputs it&#x27;s missing: title, description, destination branch. Then, fire off the right &lt;code&gt;curl&lt;&#x2F;code&gt; calls directly in the terminal. No code gets written. API driven by hand, once.&lt;&#x2F;p&gt;
&lt;p&gt;That works, but it doesn&#x27;t scale: opening a PR is something you&#x27;ll do again for the &lt;em&gt;next&lt;&#x2F;em&gt; ticket. So instead of asking for the same ad hoc sequence of &lt;code&gt;curl&lt;&#x2F;code&gt; calls every time, you ask for a reusable capability instead. A &lt;code&gt;create_pull_request&lt;&#x2F;code&gt; Python helper Claude Code writes once, and a matching &lt;a href=&quot;https:&#x2F;&#x2F;code.claude.com&#x2F;docs&#x2F;en&#x2F;skills&quot;&gt;Claude Code skill&lt;&#x2F;a&gt; that wraps it, something you (or another agent session) can invoke by name instead of re-explaining the task from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;This helper is meant to be reused unsupervised: so it should default to a dry run, nothing ships by accident when it&#x27;s called from a script, a hook, or another agent&#x27;s loop:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;subprocess
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;requests
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;API_ROOT = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;api.bitbucket.org&#x2F;2.0&#x2F;repositories&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;{os.environ[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;BB_WORKSPACE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create_pull_request(
&lt;&#x2F;span&gt;&lt;span&gt;    title: str,
&lt;&#x2F;span&gt;&lt;span&gt;    description: str,
&lt;&#x2F;span&gt;&lt;span&gt;    repo: str,
&lt;&#x2F;span&gt;&lt;span&gt;    destination: str = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;develop&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    confirm: bool = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    source = subprocess.run(
&lt;&#x2F;span&gt;&lt;span&gt;        [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;git&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rev-parse&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;--abbrev-ref&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;HEAD&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;        capture_output=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        text=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        check=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ).stdout.strip()
&lt;&#x2F;span&gt;&lt;span&gt;    payload = {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: title,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;description&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: description,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;source&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;branch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: source}},
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;destination&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;branch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: destination}},
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if not &lt;&#x2F;span&gt;&lt;span&gt;confirm:
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;DRY RUN: &lt;&#x2F;span&gt;&lt;span&gt;{source}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; -&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;{destination}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;{title}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    response = requests.post(
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{API_ROOT}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;{repo}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;pullrequests&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        auth=(os.environ[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;BB_USER&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;], os.environ[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;BB_API_TOKEN&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]),
&lt;&#x2F;span&gt;&lt;span&gt;        json=payload,
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    pr = response.json()
&lt;&#x2F;span&gt;&lt;span&gt;    print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Created PR #&lt;&#x2F;span&gt;&lt;span&gt;{pr[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;id&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;{pr[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;links&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;html&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;href&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;-&#x2F;snippets&#x2F;6019187&quot;&gt;matching skill&lt;&#x2F;a&gt; enforces the same gate one level up, in the conversation itself, before &lt;code&gt;confirm&lt;&#x2F;code&gt; ever gets set.&lt;&#x2F;p&gt;
&lt;p&gt;What matters here isn&#x27;t the API call. It&#x27;s the shift from &lt;em&gt;&quot;do this task&quot;&lt;&#x2F;em&gt; to &lt;em&gt;&quot;build the thing that does this task&quot;&lt;&#x2F;em&gt;. Every future PR reuses the same tested default instead of re-deriving the correct call, and its safety behavior, from scratch each time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-it-s-not-a-good-fit&quot;&gt;When it&#x27;s not a good fit&lt;&#x2F;h2&gt;
&lt;p&gt;Coding agents &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;&quot;&gt;automate&lt;&#x2F;a&gt; the &lt;em&gt;execution&lt;&#x2F;em&gt; of well-understood tasks. Every time something becomes well-understood enough to prompt, it gets automated. Judgment, &lt;em&gt;your job&lt;&#x2F;em&gt;, is the ability to make good decisions under incomplete information, time pressure, and conflicting constraints:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Developing opinions about system design that survive &lt;em&gt;&quot;but the LLM suggested X&quot;&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Being able to evaluate tradeoffs LLMs do not surface (org politics, migration risk, team capability)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;So, back to the original question. The gain isn&#x27;t lines of code written per hour. The distinction, &lt;em&gt;task vs. capability&lt;&#x2F;em&gt;, is doing more for your output than any single agent feature. To dig deeper on the subject, here are some interesting links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.claude.com&#x2F;en&#x2F;docs&#x2F;claude-code&#x2F;cli-reference&quot;&gt;Claude Code CLI reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=A7WFt2JQ5sg&quot;&gt;Zero Token Architecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=1P1hJ36rxM0&quot;&gt;Software engineering isn&#x27;t writing code&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=owmJyKVu5f8&quot;&gt;Engineering practices that make coding agents work&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ITIL 4... as fast as possible</title>
        <published>2026-07-12T00:00:00+00:00</published>
        <updated>2026-07-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/itil-4-again/"/>
        <id>https://nskm.xyz/posts/itil-4-again/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/itil-4-again/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;service-request.jpg&quot; alt=&quot;Lord have mercy&quot; title=&quot;what?!&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post do not reflect the views&#x2F;positions of no affiliated group.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Unto Caesar what is Caesar&#x27;s: Claude helped beautify all the diagrams used in this article.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;My hierarchy asked me to take the &lt;strong&gt;ITIL v4 Foundation&lt;&#x2F;strong&gt; certification. I have had a genuinely hard time seeing how this exam would help me do my job better. It has been due for days, and I kept pushing it back; now I am against the wall: tomorrow, July 13th, is the final deadline.&lt;&#x2F;p&gt;
&lt;p&gt;This certification is apparently requested by companies all over the world. Yet nobody around me has ever mentioned ITIL. Maybe I don&#x27;t have the right friends. Shoutout to &quot;GeekStation... 🍸🍹🍺🧋🧃🥤&quot; &lt;em&gt;lol&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;From where I stand, I doubt the exam will bring much to me or to the company I work for to be honest. But skepticism is only worth something once it has been put to the test. So I will sit the exam, honestly try to pass it, and find out whether I am wrong.&lt;&#x2F;p&gt;
&lt;p&gt;This will not be an article. This is a constellation of diagrams. The long-form write-up lives in &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;&quot;&gt;the first article&lt;&#x2F;a&gt; written some weeks ago. This one is the picture book. I hope it helps you memorize as much as it helps me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-actors&quot;&gt;The actors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#value-creation&quot;&gt;Value creation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#service-management&quot;&gt;Service management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-7-guiding-principles&quot;&gt;The 7 guiding principles&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-4-dimensions&quot;&gt;The 4 dimensions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-service-value-system&quot;&gt;The service value system&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-service-value-chain&quot;&gt;The service value chain&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#service-relationships&quot;&gt;Service relationships&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#continual-improvement&quot;&gt;Continual improvement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-34-practices&quot;&gt;The 34 practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#what-kind-of-ticket-is-this&quot;&gt;What kind of ticket is this?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;#the-toy-exam&quot;&gt;The toy exam&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-actors&quot;&gt;The actors&lt;&#x2F;h2&gt;
&lt;p&gt;Who is in the room? Customer, user, sponsor, provider.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-actors-wrapper&quot;&gt;
&lt;style&gt;
.itil4-actors-wrapper {
    --bg:      #0d1117;
    --bg2:     #161b22;
    --bg3:     #21262d;
    --border:  #30363d;
    --text:    #e6edf3;
    --muted:   #8b949e;
    --blue:    #8296ab;
    --blue-d:  #64788f;
    --green:   #8fa98f;
    --purple:  #9b8fab;
    --orange:  #ab9179;
    --yellow:  #a89a70;
    font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
    background: var(--bg);
    color: var(--text);
    padding: 28px 20px 20px;
    margin: 30px 0;
}
.itil4-actors-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

.act-header { text-align: center; margin-bottom: 22px; }
.act-header h2 { font-size: 1.2rem; font-weight: 700; color: var(--blue); text-transform: uppercase; letter-spacing: 0.05em; }
.act-header p  { color: var(--muted); font-size: 0.8rem; margin-top: 5px; }

&#x2F;* ── 3-column main layout ── *&#x2F;
.act-main {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 12px;
    align-items: center;
}

&#x2F;* ── lane (provider &#x2F; consumer) ── *&#x2F;
.act-lane {
    border: 1px solid var(--border);
    overflow: hidden;
}
.act-lane-header {
    padding: 7px 12px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    text-align: center;
}
.act-lane-header.provider { background: rgba(130,150,171,0.15); color: var(--blue); }
.act-lane-header.consumer { background: rgba(155,143,171,0.15); color: var(--purple); }
.act-lane-body { padding: 10px; display: flex; flex-direction: column; gap: 0; background: var(--bg2); }

&#x2F;* ── nodes ── *&#x2F;
.act-node {
    border: 1px solid var(--border);
    padding: 9px 12px;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.1s;
    background: var(--bg3);
}
.act-node:hover  { border-color: var(--blue); transform: translateX(2px); }
.act-node.active { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(130,150,171,0.2); }
.act-node .nd-icon  { font-size: 1.1rem; }
.act-node .nd-name  { font-size: 0.78rem; font-weight: 700; color: var(--text); margin-top: 3px; }
.act-node .nd-role  { font-size: 0.68rem; color: var(--muted); margin-top: 2px; line-height: 1.4; }

&#x2F;* chain arrow between nodes in a lane *&#x2F;
.act-chain-arrow {
    text-align: center;
    color: var(--muted);
    font-size: 0.9rem;
    padding: 2px 0;
    line-height: 1;
}

&#x2F;* ── centre exchange column ── *&#x2F;
.act-exchange {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 110px;
    padding: 0 4px;
}

.act-flow-row {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.7rem;
    color: var(--muted);
    white-space: nowrap;
}
.act-flow-arrow { font-size: 1rem; }
.act-flow-label { font-size: 0.65rem; color: var(--muted); text-align: center; }

.act-value-box {
    border: 1px solid var(--green);
    padding: 9px 10px;
    text-align: center;
    background: rgba(143,169,143,0.06);
    cursor: pointer;
    transition: border-color 0.15s;
}
.act-value-box:hover { border-color: #a3bda3; }
.act-value-box.active { box-shadow: 0 0 0 2px rgba(143,169,143,0.25); }
.act-value-box .vb-eq   { font-size: 0.8rem; font-weight: 700; color: var(--green); }
.act-value-box .vb-sub  { font-size: 0.65rem; color: var(--muted); margin-top: 3px; line-height: 1.4; }

.act-cocreate {
    font-size: 0.62rem;
    color: var(--muted);
    text-align: center;
    font-style: italic;
    padding: 0 4px;
}

&#x2F;* ── info panel ── *&#x2F;
.act-panel {
    margin-top: 16px;
    background: var(--bg3);
    border: 1px solid var(--border);
    padding: 14px 16px;
    font-size: 0.84rem;
    min-height: 72px;
}
.act-panel .ap-title { font-weight: 700; color: var(--blue); margin-bottom: 5px; font-size: 0.88rem; }
.act-panel .ap-desc  { color: var(--text); line-height: 1.6; }
.act-panel .ap-hint  { color: var(--muted); font-style: italic; font-size: 0.78rem; }
.act-panel .ap-tags  { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.act-panel .ap-tag   { font-size: 0.7rem; background: var(--bg2); border: 1px solid var(--border); padding: 2px 8px; color: var(--orange); }

@media (max-width: 580px) {
    .act-main { grid-template-columns: 1fr; }
    .act-exchange { flex-direction: row; flex-wrap: wrap; justify-content: center; min-width: unset; }
    .act-flow-row { font-size: 0.65rem; }
}
&lt;&#x2F;style&gt;

&lt;div class=&quot;act-header&quot;&gt;
    &lt;h2&gt;Who does what: for whom&lt;&#x2F;h2&gt;
    &lt;p&gt;Click any node to see its ITIL 4 definition&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;act-main&quot;&gt;

    &lt;!-- LEFT: Service Provider lane --&gt;
    &lt;div class=&quot;act-lane&quot;&gt;
        &lt;div class=&quot;act-lane-header provider&quot;&gt;Service Provider&lt;&#x2F;div&gt;
        &lt;div class=&quot;act-lane-body&quot;&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;resource&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;▦&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Resource&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Raw input to build with&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ assembles into&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;product&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;▣&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Product&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Configured for value delivery&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ packaged as&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;service&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;✦&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Service&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Enables consumer outcomes&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ described in&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;offering&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;▤&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Service Offering&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Formal promise to the consumer&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- CENTRE: exchange --&gt;
    &lt;div class=&quot;act-exchange&quot;&gt;
        &lt;div class=&quot;act-flow-row&quot;&gt;
            &lt;span class=&quot;act-flow-arrow&quot; style=&quot;color:#8296ab&quot;&gt;→&lt;&#x2F;span&gt;
            &lt;span class=&quot;act-flow-label&quot;&gt;delivers&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;act-value-box&quot; data-act=&quot;value&quot;&gt;
            &lt;div class=&quot;vb-eq&quot;&gt;Utility × Warranty&lt;&#x2F;div&gt;
            &lt;div class=&quot;vb-sub&quot;&gt;= Value&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;act-cocreate&quot;&gt;co-created&lt;br&gt;by both sides&lt;&#x2F;div&gt;

        &lt;div class=&quot;act-flow-row&quot;&gt;
            &lt;span class=&quot;act-flow-label&quot;&gt;requires&lt;&#x2F;span&gt;
            &lt;span class=&quot;act-flow-arrow&quot; style=&quot;color:#9b8fab&quot;&gt;←&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- RIGHT: Service Consumer lane --&gt;
    &lt;div class=&quot;act-lane&quot;&gt;
        &lt;div class=&quot;act-lane-header consumer&quot;&gt;Service Consumer&lt;&#x2F;div&gt;
        &lt;div class=&quot;act-lane-body&quot;&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;sponsor&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;¤&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Sponsor&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Authorizes the budget&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ funds&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;customer&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;◎&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Customer&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Defines requirements &amp;amp; owns outcomes&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ specifies for&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;user&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;○&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;User&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Uses the service day-to-day&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ feeds back to&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;stakeholder&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;⊕&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Stakeholder&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Any party with an interest&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;&#x2F;div&gt;&lt;!-- &#x2F;act-main --&gt;

&lt;div class=&quot;act-panel&quot; id=&quot;act-panel&quot;&gt;
    &lt;div class=&quot;ap-hint&quot;&gt;← Click any node to see its definition&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function () {
    const defs = {
        resource: {
            title: &quot;Resource&quot;,
            desc: &quot;Any component that can be used to deliver value: people, infrastructure, capital, information, or time. Resources are the raw inputs that the service provider assembles into something useful.&quot;,
            tags: [&quot;People&quot;, &quot;Infrastructure&quot;, &quot;Capital&quot;, &quot;Information&quot;]
        },
        product: {
            title: &quot;Product&quot;,
            desc: &quot;A configuration of resources designed to offer value to a consumer. A product is what the service provider builds. It may not be directly visible to the consumer, but it&#x27;s what the service is built on top of.&quot;,
            tags: [&quot;Configuration of resources&quot;, &quot;Provider-facing&quot;, &quot;Foundation of a service&quot;]
        },
        service: {
            title: &quot;Service&quot;,
            desc: &quot;A means of enabling value co-creation by facilitating outcomes that customers want to achieve, without the customer having to manage specific costs and risks. The key insight: value is not delivered, it is co-created.&quot;,
            tags: [&quot;Enables outcomes&quot;, &quot;Removes customer risk&quot;, &quot;Co-created with consumer&quot;]
        },
        offering: {
            title: &quot;Service Offering&quot;,
            desc: &quot;A formal description of one or more services, designed to address the needs of a target consumer group. It&#x27;s the official &#x27;promise&#x27; from provider to consumer: what&#x27;s included, what&#x27;s not, and at what terms.&quot;,
            tags: [&quot;Goods&quot;, &quot;Access to resources&quot;, &quot;Service actions&quot;, &quot;Terms &amp; conditions&quot;]
        },
        sponsor: {
            title: &quot;Sponsor&quot;,
            desc: &quot;The person who authorizes the budget for the consumption of a service. The sponsor may be the customer, or a separate person (e.g., a CFO who approves a service contract that the IT team actually uses).&quot;,
            tags: [&quot;Authorizes budget&quot;, &quot;May differ from Customer&quot;, &quot;Financial accountability&quot;]
        },
        customer: {
            title: &quot;Customer&quot;,
            desc: &quot;The person who defines the requirements for a service and takes responsibility for the outcomes of service consumption. The customer decides what is needed and judges whether the service delivered value.&quot;,
            tags: [&quot;Defines requirements&quot;, &quot;Owns outcomes&quot;, &quot;Negotiates SLAs&quot;, &quot;May also be Sponsor&quot;]
        },
        user: {
            title: &quot;User&quot;,
            desc: &quot;The person who uses services in their day-to-day work. Users interact directly with the service and often experience it differently from what the customer specified or the sponsor funded. This gap is why XLAs matter.&quot;,
            tags: [&quot;Day-to-day usage&quot;, &quot;Direct experience&quot;, &quot;Source of XLA signals&quot;, &quot;May differ from Customer&quot;]
        },
        stakeholder: {
            title: &quot;Stakeholder&quot;,
            desc: &quot;Any person who has an interest in an organization, product, service, practice, or other entity. Stakeholders include everyone on both sides: providers, consumers, regulators, partners, suppliers, and even the public in some contexts.&quot;,
            tags: [&quot;Broad category&quot;, &quot;Provider side&quot;, &quot;Consumer side&quot;, &quot;Regulators &amp; partners&quot;]
        },
        value: {
            title: &quot;Value = Utility × Warranty&quot;,
            desc: &quot;Value is subjective, contextual, and co-created. It cannot be delivered unilaterally by the provider. Utility is fitness for purpose (does the service do what the customer needs?). Warranty is fitness for use (is it available, secure, and reliable enough?). A zero on either factor collapses the value entirely.&quot;,
            tags: [&quot;Utility = fit for purpose&quot;, &quot;Warranty = fit for use&quot;, &quot;Co-created&quot;, &quot;Subjective &amp; contextual&quot;]
        }
    };

    const panel = document.getElementById(&#x27;act-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-actors-wrapper [data-act]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function () {
            const key = this.dataset.act;
            const d = defs[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-actors-wrapper [data-act]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tags = d.tags.map(t =&gt; `&lt;span class=&quot;ap-tag&quot;&gt;${t}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;ap-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ap-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ap-tags&quot;&gt;${tags}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;value-creation&quot;&gt;Value creation&lt;&#x2F;h2&gt;
&lt;p&gt;A service is a trade: it supports outcomes and removes costs and risks, while introducing new ones. Value is what&#x27;s left when the scale settles.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-vc-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-vc-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-vc-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .vc-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .vc-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .vc-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- The scale --- *&#x2F;
        .vc-scale {
            display: flex;
            align-items: stretch;
            justify-content: center;
            gap: 10px;
            max-width: 680px;
            margin: 0 auto;
        }

        .vc-pan {
            flex: 1;
            padding: 12px;
            display: flex;
            flex-direction: column;
            gap: 8px;
            min-width: 0;
        }
        .vc-pan-minus {
            border: 1px solid rgba(171,125,121,0.4);
            background: rgba(171,125,121,0.04);
        }
        .vc-pan-plus {
            border: 1px solid rgba(143,169,143,0.4);
            background: rgba(143,169,143,0.04);
        }
        .vc-pan-title {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.06em;
            padding-bottom: 4px;
        }
        .vc-pan-minus .vc-pan-title { color: var(--red); }
        .vc-pan-plus .vc-pan-title { color: var(--green); }

        .vc-item {
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 9px 11px;
            text-align: center;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
        }
        .vc-item:hover { transform: translateY(-1px); }
        .vc-item .item-name {
            font-size: 0.74rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.03em;
            line-height: 1.3;
        }
        .vc-item .item-sub {
            font-size: 0.66rem;
            color: var(--muted);
            margin-top: 2px;
            line-height: 1.35;
        }
        .vc-pan-minus .vc-item .item-name { color: var(--red); }
        .vc-pan-minus .vc-item:hover, .vc-pan-minus .vc-item.active { border-color: var(--red); }
        .vc-pan-plus .vc-item .item-name { color: var(--green); }
        .vc-pan-plus .vc-item:hover, .vc-pan-plus .vc-item.active { border-color: var(--green); }
        .vc-item.active { box-shadow: 0 0 0 2px rgba(130,150,171,0.25); }

        &#x2F;* --- Pivot &amp; value --- *&#x2F;
        .vc-pivot {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 6px;
            flex-shrink: 0;
        }
        .vc-value {
            width: 92px;
            height: 92px;
            background: var(--bg2);
            border: 2px solid var(--blue-dim);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            padding: 6px;
        }
        .vc-value:hover { transform: translateY(-1px); border-color: var(--blue); }
        .vc-value.active {
            border-color: var(--blue);
            box-shadow: 0 0 0 2px rgba(130,150,171,0.25);
        }
        .vc-value .val-icon { font-size: 1.05rem; }
        .vc-value .val-name {
            font-size: 0.8rem;
            font-weight: 700;
            color: var(--blue);
            text-transform: uppercase;
        }
        .vc-value .val-sub {
            font-size: 0.58rem;
            color: var(--muted);
            line-height: 1.3;
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .vc-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .vc-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .vc-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .vc-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .vc-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .vc-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .vc-footnote {
            margin-top: 14px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
            padding: 0 8px;
        }

        @media (max-width: 620px) {
            .vc-scale { flex-direction: column; align-items: center; }
            .vc-pan { width: 100%; }
            .vc-pivot { order: 3; }
            .vc-pan-minus { order: 2; }
            .vc-pan-plus { order: 1; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;vc-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: Value Creation&lt;&#x2F;h2&gt;
        &lt;p&gt;A service is a trade: value is what&#x27;s left when the scale settles. Click any element&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;vc-scale&quot;&gt;
        &lt;!-- What the service brings --&gt;
        &lt;div class=&quot;vc-pan vc-pan-plus&quot;&gt;
            &lt;div class=&quot;vc-pan-title&quot;&gt;+ What the service brings&lt;&#x2F;div&gt;
            &lt;div class=&quot;vc-item&quot; data-vc=&quot;supported&quot;&gt;
                &lt;div class=&quot;item-name&quot;&gt;Supported outcomes&lt;&#x2F;div&gt;
                &lt;div class=&quot;item-sub&quot;&gt;Results the consumer can now achieve&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;vc-item&quot; data-vc=&quot;costrm&quot;&gt;
                &lt;div class=&quot;item-name&quot;&gt;Costs removed&lt;&#x2F;div&gt;
                &lt;div class=&quot;item-sub&quot;&gt;Expenses the consumer no longer carries&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;vc-item&quot; data-vc=&quot;riskrm&quot;&gt;
                &lt;div class=&quot;item-name&quot;&gt;Risks removed&lt;&#x2F;div&gt;
                &lt;div class=&quot;item-sub&quot;&gt;Threats the provider now absorbs&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;!-- Pivot --&gt;
        &lt;div class=&quot;vc-pivot&quot;&gt;
            &lt;div class=&quot;vc-value&quot; data-vc=&quot;value&quot;&gt;
                &lt;span class=&quot;val-icon&quot;&gt;◆&lt;&#x2F;span&gt;
                &lt;div class=&quot;val-name&quot;&gt;Value&lt;&#x2F;div&gt;
                &lt;div class=&quot;val-sub&quot;&gt;the net result,&lt;br&gt;as perceived&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;!-- What the service costs --&gt;
        &lt;div class=&quot;vc-pan vc-pan-minus&quot;&gt;
            &lt;div class=&quot;vc-pan-title&quot;&gt;− What the service costs&lt;&#x2F;div&gt;
            &lt;div class=&quot;vc-item&quot; data-vc=&quot;affected&quot;&gt;
                &lt;div class=&quot;item-name&quot;&gt;Affected outcomes&lt;&#x2F;div&gt;
                &lt;div class=&quot;item-sub&quot;&gt;Results negatively impacted&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;vc-item&quot; data-vc=&quot;costin&quot;&gt;
                &lt;div class=&quot;item-name&quot;&gt;Costs introduced&lt;&#x2F;div&gt;
                &lt;div class=&quot;item-sub&quot;&gt;New expenses the consumer takes on&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;vc-item&quot; data-vc=&quot;riskin&quot;&gt;
                &lt;div class=&quot;item-name&quot;&gt;Risks introduced&lt;&#x2F;div&gt;
                &lt;div class=&quot;item-sub&quot;&gt;New threats the consumer accepts&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;vc-info-panel&quot; id=&quot;vc-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click an element above to see how it weighs on the scale&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;vc-footnote&quot;&gt;
        Exam classic, output vs outcome: an &lt;em&gt;output&lt;&#x2F;em&gt; is what the service produces
        (a report); an &lt;em&gt;outcome&lt;&#x2F;em&gt; is what the consumer achieves thanks to it
        (a decision made). Services are judged on outcomes.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        supported: {
            title: &quot;Supported outcomes&quot;,
            desc: &quot;The results the consumer can achieve thanks to the service: the reason they came. Not to be confused with outputs: the service produces outputs (a backup file, a report), but the consumer pays for outcomes (data that survives a disk failure, a decision made on time).&quot;,
            items: [&quot;Outcome ≠ output&quot;, &quot;Defined by the consumer, not the provider&quot;, &quot;Example: samples tracked reliably, results delivered on time&quot;]
        },
        costrm: {
            title: &quot;Costs removed&quot;,
            desc: &quot;Expenses the consumer no longer has to carry because the service exists: running their own servers, hiring specialists, maintaining licenses. &#x27;You don&#x27;t have to buy and operate all this yourself&#x27; is half the sales pitch of every service.&quot;,
            items: [&quot;Infrastructure they don&#x27;t buy&quot;, &quot;Staff they don&#x27;t hire&quot;, &quot;Operations they don&#x27;t run&quot;]
        },
        riskrm: {
            title: &quot;Risks removed&quot;,
            desc: &quot;Threats the provider absorbs on the consumer&#x27;s behalf: hardware failure, security patching, availability, compliance upkeep. The consumer trades an unpredictable risk for a predictable fee, which is also the logic of insurance.&quot;,
            items: [&quot;Hardware failure → provider&#x27;s problem&quot;, &quot;Security &amp; patching handled&quot;, &quot;Availability guaranteed by SLA&quot;]
        },
        affected: {
            title: &quot;Affected outcomes&quot;,
            desc: &quot;Results that the service impacts negatively: the fine print. A hosted tool may constrain workflows that used to be flexible; a standardized process may slow down the edge case that mattered to one team. Honest value assessment counts these too.&quot;,
            items: [&quot;Lost flexibility&quot;, &quot;Constrained workflows&quot;, &quot;Edge cases no longer served&quot;]
        },
        costin: {
            title: &quot;Costs introduced&quot;,
            desc: &quot;New expenses the consumer takes on to use the service: the subscription itself, training people, migrating data, integrating with existing systems. A service whose introduced costs exceed its removed costs is a bad trade regardless of features.&quot;,
            items: [&quot;Subscription &#x2F; license fees&quot;, &quot;Training &amp; onboarding&quot;, &quot;Migration &amp; integration effort&quot;]
        },
        riskin: {
            title: &quot;Risks introduced&quot;,
            desc: &quot;New threats accepted by consuming the service: vendor lock-in, provider outages taking you down with them, your data living in someone else&#x27;s hands. These don&#x27;t disappear because the brochure doesn&#x27;t mention them. They go on the scale.&quot;,
            items: [&quot;Vendor lock-in&quot;, &quot;Provider outage = your outage&quot;, &quot;Data custody &amp; breach exposure&quot;]
        },
        value: {
            title: &quot;Value: the net result&quot;,
            desc: &quot;Value is the perceived benefits, usefulness, and importance of the service once both pans are weighed, and &#x27;perceived&#x27; is the operative word: the consumer does the weighing, not the provider. Value = Utility × Warranty, it is subjective, contextual, and co-created. If the scale doesn&#x27;t tip toward the plus side in the consumer&#x27;s eyes, there is no value, whatever the provider&#x27;s metrics say.&quot;,
            items: [&quot;Perceived by the consumer&quot;, &quot;Utility × Warranty&quot;, &quot;Net of outcomes, costs, and risks&quot;]
        }
    };

    const panel = document.getElementById(&#x27;vc-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-vc-wrapper [data-vc]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.vc;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-vc-wrapper [data-vc]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;service-management&quot;&gt;Service management&lt;&#x2F;h2&gt;
&lt;p&gt;The whole discipline in one sentence: &quot;capabilities enabling value, for customers, in the form of services.&quot;&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-svcdef-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svcdef-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-svcdef-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svcdef-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .svcdef-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .svcdef-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- Flow rows --- *&#x2F;
        .svcdef-row {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            flex-wrap: nowrap;
        }

        .svcdef-node {
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 12px 14px;
            text-align: center;
            width: 150px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
        }
        .svcdef-node:hover { transform: translateY(-1px); }
        .svcdef-node .node-icon { font-size: 1.3rem; margin-bottom: 4px; }
        .svcdef-node .node-name {
            font-size: 0.8rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .svcdef-node .node-sub {
            font-size: 0.68rem;
            color: var(--muted);
            margin-top: 3px;
            line-height: 1.4;
        }
        .svcdef-node.active { box-shadow: 0 0 0 2px rgba(130,150,171,0.25); }

        &#x2F;* one accent per component *&#x2F;
        .node-capabilities { background: rgba(155,143,171,0.08); }
        .node-capabilities:hover, .node-capabilities.active { border-color: var(--purple); }
        .node-capabilities .node-name { color: var(--purple); }

        .node-value { background: rgba(130,150,171,0.12); }
        .node-value:hover, .node-value.active { border-color: var(--blue); }
        .node-value .node-name { color: var(--blue); }

        .node-customers { background: rgba(143,169,143,0.08); }
        .node-customers:hover, .node-customers.active { border-color: var(--green); }
        .node-customers .node-name { color: var(--green); }

        .node-services { background: rgba(171,145,121,0.08); }
        .node-services:hover, .node-services.active { border-color: var(--orange); }
        .node-services .node-name { color: var(--orange); }

        .node-products { background: rgba(168,154,112,0.08); }
        .node-products:hover, .node-products.active { border-color: var(--yellow); }
        .node-products .node-name { color: var(--yellow); }

        .node-resources { background: rgba(171,125,121,0.08); }
        .node-resources:hover, .node-resources.active { border-color: var(--red); }
        .node-resources .node-name { color: var(--red); }

        &#x2F;* --- Labeled arrows --- *&#x2F;
        .svcdef-link {
            display: flex;
            flex-direction: column;
            align-items: center;
            min-width: 84px;
            flex-shrink: 0;
        }
        .svcdef-link .link-label {
            font-size: 0.66rem;
            color: var(--muted);
            font-style: italic;
            text-align: center;
            line-height: 1.3;
            margin-bottom: 2px;
        }
        .svcdef-link .link-arrow {
            color: var(--blue);
            font-size: 1.3rem;
            line-height: 1;
        }

        &#x2F;* vertical connector between the two rows *&#x2F;
        .svcdef-vlink {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            margin: 6px 0;
        }
        .svcdef-vlink .link-label {
            font-size: 0.66rem;
            color: var(--muted);
            font-style: italic;
        }
        .svcdef-vlink .link-arrow {
            color: var(--blue);
            font-size: 1.3rem;
            line-height: 1;
        }

        &#x2F;* --- The definition sentence, color-coded --- *&#x2F;
        .svcdef-sentence {
            margin-top: 22px;
            text-align: center;
            font-size: 0.9rem;
            line-height: 1.8;
            color: var(--muted);
            border: 1px dashed var(--border);
            padding: 12px 16px;
        }
        .svcdef-sentence .w { font-weight: 600; }
        .w-capabilities { color: var(--purple); }
        .w-value { color: var(--blue); }
        .w-customers { color: var(--green); }
        .w-services { color: var(--orange); }
        .w-products { color: var(--yellow); }
        .w-resources { color: var(--red); }

        &#x2F;* --- Footnote --- *&#x2F;
        .svcdef-footnote {
            margin-top: 14px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
            padding: 0 8px;
        }
        .itil4-svcdef-wrapper .fn-mark { color: var(--yellow); font-style: normal; }

        &#x2F;* --- Info panel --- *&#x2F;
        .svcdef-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .svcdef-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .svcdef-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svcdef-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .svcdef-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .svcdef-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        @media (max-width: 640px) {
            .svcdef-row { flex-direction: column; }
            .svcdef-link { min-width: 0; }
            .svcdef-link .link-arrow { transform: rotate(90deg); }
            .svcdef-node { width: 100%; max-width: 260px; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svcdef-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: What is Service Management?&lt;&#x2F;h2&gt;
        &lt;p&gt;The definition, drawn. Click any component to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Row 1: capabilities enable value for customers --&gt;
    &lt;div class=&quot;svcdef-row&quot;&gt;
        &lt;div class=&quot;svcdef-node node-capabilities&quot; data-def=&quot;capabilities&quot;&gt;
            &lt;div class=&quot;node-icon&quot;&gt;△&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-name&quot;&gt;Capabilities&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Knowledge · people · technology&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-link&quot;&gt;
            &lt;div class=&quot;link-label&quot;&gt;enable&lt;&#x2F;div&gt;
            &lt;div class=&quot;link-arrow&quot;&gt;→&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-node node-value&quot; data-def=&quot;value&quot;&gt;
            &lt;div class=&quot;node-icon&quot;&gt;◆&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-name&quot;&gt;Value&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Perceived usefulness&lt;br&gt;Utility × Warranty&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-link&quot;&gt;
            &lt;div class=&quot;link-label&quot;&gt;for&lt;&#x2F;div&gt;
            &lt;div class=&quot;link-arrow&quot;&gt;→&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-node node-customers&quot; data-def=&quot;customers&quot;&gt;
            &lt;div class=&quot;node-icon&quot;&gt;◎&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-name&quot;&gt;Customers&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Who co-create value with the provider&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Vertical connector: value delivered in the form of services --&gt;
    &lt;div class=&quot;svcdef-vlink&quot;&gt;
        &lt;span class=&quot;link-label&quot;&gt;delivered in the form of&lt;&#x2F;span&gt;
        &lt;span class=&quot;link-arrow&quot;&gt;↓&lt;&#x2F;span&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Row 2: services, made of products, configurations of resources --&gt;
    &lt;div class=&quot;svcdef-row&quot;&gt;
        &lt;div class=&quot;svcdef-node node-services&quot; data-def=&quot;services&quot;&gt;
            &lt;div class=&quot;node-icon&quot;&gt;✦&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-name&quot;&gt;Services&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;A means of enabling value co-creation&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-link&quot;&gt;
            &lt;div class=&quot;link-label&quot;&gt;bundle one&lt;br&gt;or more&lt;&#x2F;div&gt;
            &lt;div class=&quot;link-arrow&quot;&gt;→&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-node node-products&quot; data-def=&quot;products&quot;&gt;
            &lt;div class=&quot;node-icon&quot;&gt;▣&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-name&quot;&gt;Products&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Designed to offer value to a consumer&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-link&quot;&gt;
            &lt;div class=&quot;link-label&quot;&gt;a configuration&lt;br&gt;of&lt;&#x2F;div&gt;
            &lt;div class=&quot;link-arrow&quot;&gt;→&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcdef-node node-resources&quot; data-def=&quot;resources&quot;&gt;
            &lt;div class=&quot;node-icon&quot;&gt;▦&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-name&quot;&gt;Resources&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;People · infrastructure · capital · information&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- The definition, color-coded to match the nodes --&gt;
    &lt;div class=&quot;svcdef-sentence&quot;&gt;
        Service management: a set of specialized organizational
        &lt;span class=&quot;w w-capabilities&quot;&gt;capabilities&lt;&#x2F;span&gt;&lt;span class=&quot;fn-mark&quot;&gt;*&lt;&#x2F;span&gt; for enabling
        &lt;span class=&quot;w w-value&quot;&gt;value&lt;&#x2F;span&gt; for
        &lt;span class=&quot;w w-customers&quot;&gt;customers&lt;&#x2F;span&gt; in the form of
        &lt;span class=&quot;w w-services&quot;&gt;services&lt;&#x2F;span&gt;, each service built from
        &lt;span class=&quot;w w-products&quot;&gt;products&lt;&#x2F;span&gt;, and each product a configuration of
        &lt;span class=&quot;w w-resources&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span class=&quot;fn-mark&quot;&gt;*&lt;&#x2F;span&gt;.
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;svcdef-info-panel&quot; id=&quot;svcdef-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a component above to see its definition and role&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svcdef-footnote&quot;&gt;
        &lt;span class=&quot;fn-mark&quot;&gt;*&lt;&#x2F;span&gt; The resources vs capabilities pair is formal ITIL v3 vocabulary
        (both were &quot;service assets&quot;). ITIL 4 kept &lt;em&gt;capabilities&lt;&#x2F;em&gt; in the definition of service
        management but folded the concept into &lt;em&gt;practices&lt;&#x2F;em&gt;: &quot;sets of organizational resources
        designed for performing work&quot;. The distinction still holds: a resource is what you have and
        can buy; a capability is what you can do with it, and must be built.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        capabilities: {
            title: &quot;Capabilities&quot;,
            desc: &quot;The specialized organizational abilities that make service management possible: the knowledge accumulated by the organization, the people who hold and apply it, and the technology that amplifies both. Capabilities are what transform raw resources into something valuable. Without them, resources just sit there.&quot;,
            items: [&quot;Knowledge: accumulated know-how, runbooks, experience&quot;, &quot;People: skills, roles, culture&quot;, &quot;Technology: tools and platforms that amplify both&quot;]
        },
        value: {
            title: &quot;Value&quot;,
            desc: &quot;The perceived usefulness, importance, and benefits of something. Value = Utility (fit for purpose: does it do the right thing?) × Warranty (fit for use: does it do it reliably?). A zero on either side collapses the product. Value is subjective, contextual, and always co-created with the customer. The provider alone cannot produce it.&quot;,
            items: [&quot;Utility: fit for purpose&quot;, &quot;Warranty: fit for use&quot;, &quot;Subjective, contextual, co-created&quot;]
        },
        customers: {
            title: &quot;Customers&quot;,
            desc: &quot;The people who define the requirements for a service and own the outcomes. Value does not exist in the abstract: it is value for someone. The customer decides what they need, the user interacts with it daily, and the sponsor pays for it: three roles that may or may not be the same person.&quot;,
            items: [&quot;Customer: defines requirements, owns outcomes&quot;, &quot;User: uses the service day-to-day&quot;, &quot;Sponsor: authorizes the budget&quot;]
        },
        services: {
            title: &quot;Services&quot;,
            desc: &quot;A means of enabling value co-creation by facilitating the outcomes customers want to achieve, without them having to manage the associated costs and risks. A service is how value reaches the customer, the delivery vehicle. One service typically bundles one or more products.&quot;,
            items: [&quot;Facilitates customer outcomes&quot;, &quot;Offloads costs and risks from the customer&quot;, &quot;Described formally in a service offering&quot;]
        },
        products: {
            title: &quot;Products&quot;,
            desc: &quot;A configuration of an organization&#x27;s resources, designed to offer value to a consumer. A product is not a single thing. It is an arrangement: servers, software, data, and people configured together so that a service can be delivered on top of it.&quot;,
            items: [&quot;A configuration, not a component&quot;, &quot;Designed around consumer value&quot;, &quot;One or more products underpin a service&quot;]
        },
        resources: {
            title: &quot;Resources&quot;,
            desc: &quot;Any component used to deliver value, the raw material of service management. On their own, resources produce nothing: it takes capabilities to configure them into products and deliver them as services. This is the loop back to the start of the diagram.&quot;,
            items: [&quot;People&quot;, &quot;Infrastructure &amp; applications&quot;, &quot;Capital &amp; financial assets&quot;, &quot;Information &amp; data&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svcdef-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svcdef-wrapper [data-def]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.def;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svcdef-wrapper [data-def]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-7-guiding-principles&quot;&gt;The 7 guiding principles&lt;&#x2F;h2&gt;
&lt;p&gt;7 recommendations that apply to every decision, in every circumstance.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-gp-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-gp-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            --cyan: #7d9ba3;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-gp-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .gp-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .gp-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .gp-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- Principles grid --- *&#x2F;
        .gp-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
            gap: 10px;
            max-width: 720px;
            margin: 0 auto;
        }

        .gp-item {
            display: flex;
            align-items: center;
            gap: 12px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 10px 12px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
        }
        .gp-item:hover { transform: translateY(-1px); border-color: var(--accent); }
        .gp-item.active {
            border-color: var(--accent);
            box-shadow: 0 0 0 2px rgba(130,150,171,0.25);
        }

        .gp-badge {
            width: 46px;
            height: 46px;
            border: 2px solid var(--accent);
            background: var(--bg2);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
            line-height: 1;
        }
        .gp-badge .gp-num {
            font-size: 0.6rem;
            font-weight: 700;
            color: var(--accent);
        }
        .gp-badge .gp-icon { font-size: 1.05rem; margin-top: 1px; }

        .gp-item .gp-name {
            font-size: 0.8rem;
            font-weight: 700;
            color: var(--accent);
            text-transform: uppercase;
            letter-spacing: 0.03em;
            line-height: 1.3;
        }
        .gp-item .gp-sub {
            font-size: 0.7rem;
            color: var(--muted);
            margin-top: 3px;
            line-height: 1.4;
        }

        .gp-1 { --accent: var(--purple); }
        .gp-2 { --accent: var(--blue); }
        .gp-3 { --accent: var(--green); }
        .gp-4 { --accent: var(--orange); }
        .gp-5 { --accent: var(--yellow); }
        .gp-6 { --accent: var(--cyan); }
        .gp-7 { --accent: var(--red); }

        &#x2F;* --- Info panel --- *&#x2F;
        .gp-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .gp-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .gp-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .gp-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .gp-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .gp-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .gp-footnote {
            margin-top: 14px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
            padding: 0 8px;
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;gp-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: The 7 Guiding Principles&lt;&#x2F;h2&gt;
        &lt;p&gt;Universal recommendations that apply to every decision, at every level. Click one to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;gp-grid&quot;&gt;
        &lt;div class=&quot;gp-item gp-1&quot; data-gp=&quot;p1&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;◎&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Focus on value&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;Every action should trace back to a benefit for a stakeholder&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;gp-item gp-2&quot; data-gp=&quot;p2&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;⌖&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Start where you are&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;Assess what already works before designing something new&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;gp-item gp-3&quot; data-gp=&quot;p3&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;↻&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Progress iteratively with feedback&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;Small increments, real feedback, adjust&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;gp-item gp-4&quot; data-gp=&quot;p4&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;⇄&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Collaborate and promote visibility&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;Make work visible; involve the right people early&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;gp-item gp-5&quot; data-gp=&quot;p5&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;⊕&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Think and work holistically&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;Services are systems: consider the whole, not just your part&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;gp-item gp-6&quot; data-gp=&quot;p6&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;6&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;◦&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Keep it simple and practical&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;If a step adds no value, eliminate it&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;gp-item gp-7&quot; data-gp=&quot;p7&quot;&gt;
            &lt;div class=&quot;gp-badge&quot;&gt;&lt;span class=&quot;gp-num&quot;&gt;7&lt;&#x2F;span&gt;&lt;span class=&quot;gp-icon&quot;&gt;✱&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div&gt;
                &lt;div class=&quot;gp-name&quot;&gt;Optimize and automate&lt;&#x2F;div&gt;
                &lt;div class=&quot;gp-sub&quot;&gt;Fix the process first, then automate what remains&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;gp-info-panel&quot; id=&quot;gp-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a principle above to see what it means in practice&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;gp-footnote&quot;&gt;
        Unlike practices, the guiding principles are not optional and not situational:
        they apply to every component of the SVS, in every circumstance,
        and cannot be overridden by management or policy.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        p1: {
            title: &quot;1. Focus on value&quot;,
            desc: &quot;Every activity should link back to value for stakeholders. Before starting anything, ask: who benefits, and how? If you can&#x27;t answer that, stop. Value is defined by the consumer, not the provider. A technically impressive deliverable nobody asked for is waste.&quot;,
            items: [&quot;Ask &#x27;who benefits?&#x27; before every task&quot;, &quot;Value = Utility × Warranty&quot;, &quot;Includes the user experience, not just the output&quot;]
        },
        p2: {
            title: &quot;2. Start where you are&quot;,
            desc: &quot;Never assume you need to start from scratch. Assess what already works before designing something new. Most organizations already have something useful. The goal is to build on it, not erase it. Measure the current state directly (observe, don&#x27;t assume).&quot;,
            items: [&quot;Baseline before redesigning&quot;, &quot;Reuse what works&quot;, &quot;Direct observation over assumptions&quot;]
        },
        p3: {
            title: &quot;3. Progress iteratively with feedback&quot;,
            desc: &quot;Don&#x27;t design the perfect solution upfront. Deliver in small increments, gather real feedback, adjust. Each iteration should produce tangible results. This is the same philosophy behind Agile sprints and DevOps continuous delivery.&quot;,
            items: [&quot;Small increments over big-bang&quot;, &quot;Feedback loops at every step&quot;, &quot;Same logic as Agile sprints &amp; CI&#x2F;CD&quot;]
        },
        p4: {
            title: &quot;4. Collaborate and promote visibility&quot;,
            desc: &quot;Work done in silos fails. Decisions made without the right people in the room fail. Make work visible (kanban boards, incident dashboards, change calendars) and involve stakeholders early, not at the end. Hidden work and hidden agendas are the enemy.&quot;,
            items: [&quot;Kanban boards &amp; dashboards&quot;, &quot;Involve stakeholders early&quot;, &quot;No hidden work, no silos&quot;]
        },
        p5: {
            title: &quot;5. Think and work holistically&quot;,
            desc: &quot;Services are systems. A change to one component can have unexpected effects elsewhere. Consider end-to-end impact across all four dimensions (people, technology, partners, processes), not just the piece in front of you.&quot;,
            items: [&quot;End-to-end view of the service&quot;, &quot;Covers all 4 dimensions&quot;, &quot;No component works in isolation&quot;]
        },
        p6: {
            title: &quot;6. Keep it simple and practical&quot;,
            desc: &quot;If a process step doesn&#x27;t add value, eliminate it. If a tool creates more overhead than it saves, reconsider. Complexity is the enemy of reliability. Use the minimum number of steps needed to accomplish the objective. Outcome-based thinking beats process theater.&quot;,
            items: [&quot;Eliminate valueless steps&quot;, &quot;KISS: keep it simple and stupid&quot;, &quot;Complexity kills reliability&quot;]
        },
        p7: {
            title: &quot;7. Optimize and automate&quot;,
            desc: &quot;First optimize the process: eliminate waste, reduce friction. Then automate what remains. Automating a broken process gives you broken results, faster. The order matters: optimization before automation, always.&quot;,
            items: [&quot;Optimize first, automate second&quot;, &quot;Automating a mess = a faster mess&quot;, &quot;Reserve humans for judgment calls&quot;]
        }
    };

    const panel = document.getElementById(&#x27;gp-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-gp-wrapper [data-gp]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.gp;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-gp-wrapper [data-gp]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-4-dimensions&quot;&gt;The 4 dimensions&lt;&#x2F;h2&gt;
&lt;p&gt;Neglect any one of them and the project fails.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-4dim-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-4dim-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-4dim-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .dim4-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .dim4-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .dim4-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- PESTLE boundary --- *&#x2F;
        .dim4-pestle-frame {
            position: relative;
            border: 1px dashed var(--yellow);
            padding: 34px 26px;
            margin: 0 auto;
            max-width: 720px;
        }
        .dim4-pestle-tag {
            position: absolute;
            background: var(--bg);
            color: var(--yellow);
            font-size: 0.7rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.06em;
            padding: 2px 8px;
            cursor: pointer;
            transition: color 0.2s;
        }
        .dim4-pestle-tag:hover, .dim4-pestle-tag.active { color: var(--text); }
        .pestle-p  { top: -0.7em; left: 8%; }
        .pestle-ec { top: -0.7em; right: 8%; }
        .pestle-en { top: 50%; left: 0; transform: translate(-50%, -50%) rotate(-90deg); }
        .pestle-s  { top: 50%; right: 0; transform: translate(50%, -50%) rotate(90deg); }
        .pestle-l  { bottom: -0.7em; left: 8%; }
        .pestle-t  { bottom: -0.7em; right: 8%; }

        &#x2F;* --- 2x2 dimensions grid --- *&#x2F;
        .dim4-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 10px;
            position: relative;
        }

        .dim4-cell {
            border: 1px solid var(--border);
            padding: 16px 14px;
            min-height: 130px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
        }
        .dim4-cell:hover { transform: translateY(-1px); }
        .dim4-cell .dim-icon { font-size: 1.3rem; margin-bottom: 5px; }
        .dim4-cell .dim-name {
            font-size: 0.8rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            line-height: 1.3;
        }
        .dim4-cell .dim-sub {
            font-size: 0.72rem;
            color: var(--muted);
            margin-top: 4px;
            line-height: 1.4;
        }

        &#x2F;* one accent per dimension, mirroring the other itil4 diagrams *&#x2F;
        .dim-people   { background: rgba(155,143,171,0.08); }
        .dim-people:hover, .dim-people.active { border-color: var(--purple); }
        .dim-people .dim-name { color: var(--purple); }

        .dim-tech     { background: rgba(130,150,171,0.08); text-align: right; }
        .dim-tech:hover, .dim-tech.active { border-color: var(--blue); }
        .dim-tech .dim-name { color: var(--blue); }

        .dim-partners { background: rgba(171,145,121,0.08); display: flex; flex-direction: column; justify-content: flex-end; }
        .dim-partners:hover, .dim-partners.active { border-color: var(--orange); }
        .dim-partners .dim-name { color: var(--orange); }

        .dim-streams  { background: rgba(143,169,143,0.08); display: flex; flex-direction: column; justify-content: flex-end; text-align: right; }
        .dim-streams:hover, .dim-streams.active { border-color: var(--green); }
        .dim-streams .dim-name { color: var(--green); }

        .dim4-cell.active { box-shadow: 0 0 0 2px rgba(130,150,171,0.25); }

        &#x2F;* --- central value hexagon --- *&#x2F;
        .dim4-value {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 168px;
            height: 148px;
            clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
            background: var(--bg2);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            cursor: pointer;
            border: none;
            transition: transform 0.1s;
            z-index: 2;
        }
        &#x2F;* hexagonal border: a slightly bigger hexagon behind *&#x2F;
        .dim4-value::before {
            content: &quot;&quot;;
            position: absolute;
            inset: -2px;
            clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
            background: var(--blue-dim);
            z-index: -1;
        }
        .dim4-value:hover { transform: translate(-50%, -50%) scale(1.03); }
        .dim4-value .val-sub {
            font-size: 0.62rem;
            color: var(--muted);
            text-transform: uppercase;
            letter-spacing: 0.06em;
        }
        .dim4-value .val-name {
            font-size: 1.1rem;
            font-weight: 700;
            color: var(--text);
            margin: 3px 0;
        }
        .dim4-value .val-eq {
            font-size: 0.66rem;
            color: var(--blue);
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .dim4-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .dim4-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .dim4-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .dim4-info-panel .panel-fail {
            margin-top: 8px;
            font-size: 0.78rem;
            color: var(--red);
            font-style: italic;
        }
        .dim4-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .dim4-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .dim4-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .dim4-legend {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-top: 16px;
            font-size: 0.75rem;
            color: var(--muted);
            justify-content: center;
        }
        .dim4-legend-item { display: flex; align-items: center; gap: 5px; }
        .dim4-legend-dot {
            width: 8px; height: 8px;
            display: inline-block;
        }

        @media (max-width: 600px) {
            .dim4-grid { grid-template-columns: 1fr; }
            .dim4-cell, .dim-tech, .dim-streams { text-align: left; min-height: 0; justify-content: flex-start; }
            .dim4-value {
                position: static;
                transform: none;
                margin: 10px auto;
                order: 3;
            }
            .dim4-value:hover { transform: scale(1.03); }
            .pestle-en { left: -0.5em; transform: translate(-30%, -50%) rotate(-90deg); }
            .pestle-s  { right: -0.5em; transform: translate(30%, -50%) rotate(90deg); }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;dim4-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: The Four Dimensions Model&lt;&#x2F;h2&gt;
        &lt;p&gt;Click a dimension, the value hexagon, or a PESTLE factor to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;dim4-pestle-frame&quot;&gt;
        &lt;span class=&quot;dim4-pestle-tag pestle-p&quot;  data-dim=&quot;political&quot;&gt;Political&lt;&#x2F;span&gt;
        &lt;span class=&quot;dim4-pestle-tag pestle-ec&quot; data-dim=&quot;economic&quot;&gt;Economic&lt;&#x2F;span&gt;
        &lt;span class=&quot;dim4-pestle-tag pestle-en&quot; data-dim=&quot;environmental&quot;&gt;Environmental&lt;&#x2F;span&gt;
        &lt;span class=&quot;dim4-pestle-tag pestle-s&quot;  data-dim=&quot;social&quot;&gt;Social&lt;&#x2F;span&gt;
        &lt;span class=&quot;dim4-pestle-tag pestle-l&quot;  data-dim=&quot;legal&quot;&gt;Legal&lt;&#x2F;span&gt;
        &lt;span class=&quot;dim4-pestle-tag pestle-t&quot;  data-dim=&quot;technological&quot;&gt;Technological&lt;&#x2F;span&gt;

        &lt;div class=&quot;dim4-grid&quot;&gt;
            &lt;div class=&quot;dim4-cell dim-people&quot; data-dim=&quot;people&quot;&gt;
                &lt;div class=&quot;dim-icon&quot;&gt;◉&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-name&quot;&gt;Organizations&lt;br&gt;&amp;amp; People&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-sub&quot;&gt;Structure · culture · roles · skills&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;dim4-cell dim-tech&quot; data-dim=&quot;tech&quot;&gt;
                &lt;div class=&quot;dim-icon&quot;&gt;▣&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-name&quot;&gt;Information&lt;br&gt;&amp;amp; Technology&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-sub&quot;&gt;Data · knowledge · tools · infrastructure&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;dim4-cell dim-partners&quot; data-dim=&quot;partners&quot;&gt;
                &lt;div class=&quot;dim-icon&quot;&gt;⇄&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-name&quot;&gt;Partners&lt;br&gt;&amp;amp; Suppliers&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-sub&quot;&gt;Vendors · contracts · integrations&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;dim4-cell dim-streams&quot; data-dim=&quot;streams&quot;&gt;
                &lt;div class=&quot;dim-icon&quot;&gt;⇉&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-name&quot;&gt;Value Streams&lt;br&gt;&amp;amp; Processes&lt;&#x2F;div&gt;
                &lt;div class=&quot;dim-sub&quot;&gt;Workflows · activities · procedures&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;dim4-value&quot; data-dim=&quot;value&quot;&gt;
                &lt;div class=&quot;val-sub&quot;&gt;Products &amp;amp; Services&lt;&#x2F;div&gt;
                &lt;div class=&quot;val-name&quot;&gt;Value&lt;&#x2F;div&gt;
                &lt;div class=&quot;val-eq&quot;&gt;Utility × Warranty&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;dim4-info-panel&quot; id=&quot;dim4-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a dimension above to see what it covers, and how ignoring it makes projects fail&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;dim4-legend&quot;&gt;
        &lt;div class=&quot;dim4-legend-item&quot;&gt;&lt;span class=&quot;dim4-legend-dot&quot; style=&quot;background:#9b8fab&quot;&gt;&lt;&#x2F;span&gt; Organizations &amp;amp; People&lt;&#x2F;div&gt;
        &lt;div class=&quot;dim4-legend-item&quot;&gt;&lt;span class=&quot;dim4-legend-dot&quot; style=&quot;background:#8296ab&quot;&gt;&lt;&#x2F;span&gt; Information &amp;amp; Technology&lt;&#x2F;div&gt;
        &lt;div class=&quot;dim4-legend-item&quot;&gt;&lt;span class=&quot;dim4-legend-dot&quot; style=&quot;background:#ab9179&quot;&gt;&lt;&#x2F;span&gt; Partners &amp;amp; Suppliers&lt;&#x2F;div&gt;
        &lt;div class=&quot;dim4-legend-item&quot;&gt;&lt;span class=&quot;dim4-legend-dot&quot; style=&quot;background:#8fa98f&quot;&gt;&lt;&#x2F;span&gt; Value Streams &amp;amp; Processes&lt;&#x2F;div&gt;
        &lt;div class=&quot;dim4-legend-item&quot;&gt;&lt;span class=&quot;dim4-legend-dot&quot; style=&quot;background:#a89a70&quot;&gt;&lt;&#x2F;span&gt; PESTLE external factors&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        people: {
            title: &quot;1. Organizations &amp; People&quot;,
            desc: &quot;How the organization is structured and how its people work: org charts, culture, roles and responsibilities, required skills and competencies, leadership styles. A perfect tool operated by an untrained, unmotivated, or siloed team delivers nothing.&quot;,
            fail: &quot;Classic failure mode: “We deployed the tool but nobody knows how to use it.”&quot;,
            items: [&quot;Org structure &amp; governance&quot;, &quot;Culture &amp; leadership&quot;, &quot;Roles &amp; responsibilities&quot;, &quot;Skills, training &amp; staffing&quot;]
        },
        tech: {
            title: &quot;2. Information &amp; Technology&quot;,
            desc: &quot;The information and knowledge needed to manage services, plus the technologies that support them: databases, monitoring, CMDBs, AI&#x2F;automation, security controls. Also asks how information is exchanged, protected, and kept compliant.&quot;,
            fail: &quot;Classic failure mode: “The system works but we can&#x27;t query the data we need.”&quot;,
            items: [&quot;Data &amp; knowledge management&quot;, &quot;Tools &amp; platforms&quot;, &quot;Infrastructure &amp; applications&quot;, &quot;Security &amp; compliance of information&quot;]
        },
        partners: {
            title: &quot;3. Partners &amp; Suppliers&quot;,
            desc: &quot;No organization delivers services alone. This dimension covers every external relationship: cloud providers, software vendors, outsourced support, consultants, plus the contracts, SLAs, and integration points that bind them.&quot;,
            fail: &quot;Classic failure mode: “Our vendor went down and we had no fallback.”&quot;,
            items: [&quot;Vendor &amp; contract management&quot;, &quot;Service integration (SIAM)&quot;, &quot;Sourcing strategy: build vs buy&quot;, &quot;Dependency &amp; exit planning&quot;]
        },
        streams: {
            title: &quot;4. Value Streams &amp; Processes&quot;,
            desc: &quot;How work actually flows through the organization: the value streams that turn demand into value, and the processes, activities, and procedures inside them. This is where waste, handoffs, and bottlenecks hide.&quot;,
            fail: &quot;Classic failure mode: “Everyone&#x27;s busy but nothing ships.”&quot;,
            items: [&quot;Value stream mapping&quot;, &quot;Process definition &amp; workflows&quot;, &quot;Handoffs &amp; approvals&quot;, &quot;Waste elimination (Lean)&quot;]
        },
        value: {
            title: &quot;Value: through Products &amp; Services&quot;,
            desc: &quot;The center of the model. Every product or service must be considered from all four dimensions at once. Neglecting any one of them is one of the most reliable ways to make a project fail. Value = Utility (fit for purpose) × Warranty (fit for use): a zero on either side collapses the product.&quot;,
            items: [&quot;Utility: does it do the right thing?&quot;, &quot;Warranty: does it do it reliably?&quot;, &quot;Value is subjective, contextual, co-created&quot;]
        },
        political: {
            title: &quot;PESTLE: Political&quot;,
            desc: &quot;Government policies, political stability, and public-sector mandates that constrain how services are designed and where data may live.&quot;,
            items: [&quot;Data sovereignty laws&quot;, &quot;Public sector procurement rules&quot;]
        },
        economic: {
            title: &quot;PESTLE: Economic&quot;,
            desc: &quot;Budget cycles, cost pressures, exchange rates, and market conditions that shape what the organization can afford to build or buy.&quot;,
            items: [&quot;Cloud cost optimization&quot;, &quot;License negotiation&quot;, &quot;Budget freezes&quot;]
        },
        social: {
            title: &quot;PESTLE: Social&quot;,
            desc: &quot;User expectations, demographics, and workforce trends that change what “good service” means.&quot;,
            items: [&quot;Remote work adoption&quot;, &quot;Digital literacy gaps&quot;, &quot;Consumer-grade UX expectations&quot;]
        },
        technological: {
            title: &quot;PESTLE: Technological&quot;,
            desc: &quot;Emerging technologies, the vendor landscape, and the threat landscape: the fastest-moving external factor.&quot;,
            items: [&quot;AI integration&quot;, &quot;Cloud migration&quot;, &quot;Security threats&quot;]
        },
        legal: {
            title: &quot;PESTLE: Legal&quot;,
            desc: &quot;Compliance requirements and regulations that services must satisfy by design, not as an afterthought.&quot;,
            items: [&quot;GDPR&quot;, &quot;HIPAA&quot;, &quot;Sector-specific regulations&quot;]
        },
        environmental: {
            title: &quot;PESTLE: Environmental&quot;,
            desc: &quot;Sustainability constraints and green IT concerns, from energy consumption to hardware lifecycle.&quot;,
            items: [&quot;Data center energy&quot;, &quot;Hardware lifecycle &amp; e-waste&quot;]
        }
    };

    const panel = document.getElementById(&#x27;dim4-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-4dim-wrapper [data-dim]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.dim;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-4dim-wrapper [data-dim]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            const failHtml = d.fail ? `&lt;div class=&quot;panel-fail&quot;&gt;${d.fail}&lt;&#x2F;div&gt;` : &#x27;&#x27;;
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                ${failHtml}
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-service-value-system&quot;&gt;The service value system&lt;&#x2F;h2&gt;
&lt;p&gt;How an organization turns opportunity and demand into value.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-svslayers-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svslayers-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-svslayers-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svsl-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .svsl-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .svsl-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        .svsl-layout {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
        }

        &#x2F;* --- Input &#x2F; Output circles --- *&#x2F;
        .svsl-io {
            width: 96px;
            height: 96px;
            background: var(--bg3);
            border: 1px solid var(--border);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            flex-shrink: 0;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            padding: 8px;
        }
        .svsl-io:hover { transform: translateY(-1px); }
        .svsl-io.active, .svsl-io:hover { border-color: var(--blue); }
        .svsl-io .io-icon { font-size: 1.2rem; }
        .svsl-io .io-name {
            font-size: 0.68rem;
            font-weight: 600;
            margin-top: 3px;
            line-height: 1.3;
        }
        .svsl-io.io-value { border-color: var(--blue-dim); }
        .svsl-io.io-value .io-name { color: var(--blue); font-size: 0.8rem; }

        .svsl-arrow {
            color: var(--blue);
            font-size: 1.4rem;
            flex-shrink: 0;
        }

        &#x2F;* --- Nested layers --- *&#x2F;
        .svsl-layer {
            padding: 10px 12px;
            display: flex;
            flex-direction: column;
            gap: 8px;
        }
        .layer-outer {
            background: rgba(155,143,171,0.10);
            border: 1px solid rgba(155,143,171,0.35);
            flex: 1;
            max-width: 440px;
        }
        .layer-mid {
            background: rgba(171,145,121,0.10);
            border: 1px solid rgba(171,145,121,0.35);
        }
        .layer-core {
            background: rgba(130,150,171,0.15);
            border: 1px solid var(--blue-dim);
            padding: 18px 14px;
            text-align: center;
            cursor: pointer;
            transition: transform 0.1s, box-shadow 0.2s;
        }
        .layer-core:hover { transform: translateY(-1px); }
        .layer-core .core-name {
            font-size: 0.85rem;
            font-weight: 700;
            color: var(--blue);
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .layer-core .core-sub {
            font-size: 0.68rem;
            color: var(--muted);
            margin-top: 4px;
        }

        &#x2F;* --- Layer labels --- *&#x2F;
        .svsl-label {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.06em;
            cursor: pointer;
            padding: 4px 10px;
            transition: background 0.2s;
        }
        .svsl-label:hover, .svsl-label.active { background: rgba(255,255,255,0.06); }
        .label-guiding    { color: var(--purple); }
        .label-governance { color: var(--orange); }
        .label-practices  { color: var(--orange); }
        .label-ci         { color: var(--green); }

        .svsl-label.active, .layer-core.active, .svsl-io.active {
            box-shadow: 0 0 0 2px rgba(130,150,171,0.25);
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .svsl-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .svsl-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .svsl-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svsl-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .svsl-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .svsl-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .svsl-legend {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-top: 16px;
            font-size: 0.75rem;
            color: var(--muted);
            justify-content: center;
        }
        .svsl-legend-item { display: flex; align-items: center; gap: 5px; }
        .svsl-legend-dot {
            width: 8px; height: 8px;
            display: inline-block;
        }

        @media (max-width: 600px) {
            .svsl-layout { flex-direction: column; }
            .svsl-arrow { transform: rotate(90deg); }
            .layer-outer { max-width: 100%; width: 100%; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svsl-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: Service Value System (SVS)&lt;&#x2F;h2&gt;
        &lt;p&gt;Opportunity and demand go in, value comes out. Click any layer to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svsl-layout&quot;&gt;
        &lt;!-- Input --&gt;
        &lt;div class=&quot;svsl-io&quot; data-svs=&quot;input&quot;&gt;
            &lt;span class=&quot;io-icon&quot;&gt;▹&lt;&#x2F;span&gt;
            &lt;div class=&quot;io-name&quot;&gt;Opportunity&lt;br&gt;&#x2F; Demand&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svsl-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;

        &lt;!-- Nested layers --&gt;
        &lt;div class=&quot;svsl-layer layer-outer&quot;&gt;
            &lt;div class=&quot;svsl-label label-guiding&quot; data-svs=&quot;guiding&quot;&gt;Guiding Principles&lt;&#x2F;div&gt;

            &lt;div class=&quot;svsl-layer layer-mid&quot;&gt;
                &lt;div class=&quot;svsl-label label-governance&quot; data-svs=&quot;governance&quot;&gt;Governance&lt;&#x2F;div&gt;

                &lt;div class=&quot;layer-core&quot; data-svs=&quot;svc&quot;&gt;
                    &lt;div class=&quot;core-name&quot;&gt;Service Value Chain&lt;&#x2F;div&gt;
                    &lt;div class=&quot;core-sub&quot;&gt;Plan · Engage · Design &amp;amp; Transition · Obtain&#x2F;Build · Deliver &amp;amp; Support · Improve&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;

                &lt;div class=&quot;svsl-label label-practices&quot; data-svs=&quot;practices&quot;&gt;Practices&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svsl-label label-ci&quot; data-svs=&quot;ci&quot;&gt;Continual Improvement&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svsl-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;

        &lt;!-- Output --&gt;
        &lt;div class=&quot;svsl-io io-value&quot; data-svs=&quot;value&quot;&gt;
            &lt;span class=&quot;io-icon&quot;&gt;◆&lt;&#x2F;span&gt;
            &lt;div class=&quot;io-name&quot;&gt;Value&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;svsl-info-panel&quot; id=&quot;svsl-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a layer, or an endpoint, to see its role in the SVS&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svsl-legend&quot;&gt;
        &lt;div class=&quot;svsl-legend-item&quot;&gt;&lt;span class=&quot;svsl-legend-dot&quot; style=&quot;background:#9b8fab&quot;&gt;&lt;&#x2F;span&gt; Guiding Principles&lt;&#x2F;div&gt;
        &lt;div class=&quot;svsl-legend-item&quot;&gt;&lt;span class=&quot;svsl-legend-dot&quot; style=&quot;background:#ab9179&quot;&gt;&lt;&#x2F;span&gt; Governance &amp;amp; Practices&lt;&#x2F;div&gt;
        &lt;div class=&quot;svsl-legend-item&quot;&gt;&lt;span class=&quot;svsl-legend-dot&quot; style=&quot;background:#8296ab&quot;&gt;&lt;&#x2F;span&gt; Service Value Chain&lt;&#x2F;div&gt;
        &lt;div class=&quot;svsl-legend-item&quot;&gt;&lt;span class=&quot;svsl-legend-dot&quot; style=&quot;background:#8fa98f&quot;&gt;&lt;&#x2F;span&gt; Continual Improvement&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        input: {
            title: &quot;Opportunity &#x2F; Demand&quot;,
            desc: &quot;What enters the SVS. Opportunity is the potential to add value for stakeholders or improve the organization; demand is the need or desire for products and services from consumers. The SVS exists to convert both into value. An organization that only reacts to demand and never to opportunity is standing still.&quot;,
            items: [&quot;Opportunity: options to add value&quot;, &quot;Demand: need for products &amp; services&quot;]
        },
        guiding: {
            title: &quot;7 Guiding Principles: the outermost layer&quot;,
            desc: &quot;Universal recommendations that guide organizations in all circumstances. They wrap around everything else in the SVS: no component, practice, or decision escapes them. They cannot be overridden by management or policy.&quot;,
            items: [&quot;Focus on value&quot;, &quot;Start where you are&quot;, &quot;Progress iteratively with feedback&quot;, &quot;Collaborate and promote visibility&quot;, &quot;Think and work holistically&quot;, &quot;Keep it simple and practical&quot;, &quot;Optimize and automate&quot;]
        },
        governance: {
            title: &quot;Governance&quot;,
            desc: &quot;The framework by which the organization is directed and controlled. It sits between the principles and the operational core: it translates strategy into policies and keeps the value chain accountable. Three core functions:&quot;,
            items: [&quot;Direct: set strategy, objectives, policies&quot;, &quot;Evaluate: assess performance, risk, compliance&quot;, &quot;Monitor: track adherence and verify outcomes&quot;]
        },
        svc: {
            title: &quot;Service Value Chain (SVC): the core&quot;,
            desc: &quot;The operational engine at the heart of the SVS. Six activities combined in different ways to create value streams: the specific sequences of steps for a given product or service. It is NOT linear: each value stream activates a different combination of activities.&quot;,
            items: [&quot;Plan&quot;, &quot;Engage&quot;, &quot;Design &amp; Transition&quot;, &quot;Obtain &#x2F; Build&quot;, &quot;Deliver &amp; Support&quot;, &quot;Improve&quot;]
        },
        practices: {
            title: &quot;34 Management Practices&quot;,
            desc: &quot;Sets of organizational resources designed for performing work or accomplishing an objective. They surround the value chain and give it capability. You do not need to implement all 34. Adopt what solves your actual problems.&quot;,
            items: [&quot;General Management (14): strategy, risk, knowledge...&quot;, &quot;Service Management (17): incident, change, service desk...&quot;, &quot;Technical Management (3): deployment, infrastructure, software dev&quot;]
        },
        ci: {
            title: &quot;Continual Improvement: the other outermost layer&quot;,
            desc: &quot;Like the guiding principles, continual improvement wraps around the whole system rather than being a step in it. Every component, every practice, every activity is subject to improvement, all the time. The Continual Improvement Register (CIR) tracks ideas and their status.&quot;,
            items: [&quot;7-step model: vision → baseline → target → plan → act → measure → sustain&quot;, &quot;3 axes: strategic, tactical, operational&quot;, &quot;Tools: OKR, KPI, SLA, XLA, CIR&quot;]
        },
        value: {
            title: &quot;Value: for all stakeholders&quot;,
            desc: &quot;What leaves the SVS. Value = Utility (fit for purpose) × Warranty (fit for use), and a zero on either side collapses the product. Value is subjective, contextual, and co-created: the provider alone cannot produce it. It emerges in interaction with the consumer.&quot;,
            items: [&quot;Utility: does it do the right thing?&quot;, &quot;Warranty: does it do it reliably?&quot;, &quot;Co-created with the service consumer&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svsl-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svslayers-wrapper [data-svs]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.svs;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svslayers-wrapper [data-svs]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-service-value-chain&quot;&gt;The service value chain&lt;&#x2F;h2&gt;
&lt;p&gt;6 activities that every value stream is assembled from.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-svcflow-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svcflow-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-svcflow-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svcf-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .svcf-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .svcf-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        .svcf-layout {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
        }

        &#x2F;* --- Endpoint circles (demand &#x2F; value) --- *&#x2F;
        .svcf-io {
            width: 84px;
            height: 84px;
            background: var(--bg3);
            border: 1px solid var(--border);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            text-align: center;
            flex-shrink: 0;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            padding: 6px;
        }
        .svcf-io:hover { transform: translateY(-1px); }
        .svcf-io.active, .svcf-io:hover { border-color: var(--blue); }
        .svcf-io .io-icon { font-size: 1.1rem; }
        .svcf-io .io-name {
            font-size: 0.68rem;
            font-weight: 600;
            margin-top: 2px;
            line-height: 1.25;
        }
        .svcf-io.io-value { border-color: var(--blue-dim); }
        .svcf-io.io-value .io-name { color: var(--blue); font-size: 0.78rem; }

        .svcf-arrow {
            color: var(--blue);
            font-size: 1.3rem;
            flex-shrink: 0;
        }

        &#x2F;* --- Generic rectangle node --- *&#x2F;
        .svcf-node {
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 10px 12px;
            text-align: center;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
        }
        .svcf-node:hover { transform: translateY(-1px); border-color: var(--blue); }
        .svcf-node.active {
            border-color: var(--blue);
            box-shadow: 0 0 0 2px rgba(130,150,171,0.25);
        }
        .svcf-node .node-icon { font-size: 1.15rem; display: block; margin-bottom: 3px; }
        .svcf-node .node-name {
            font-size: 0.74rem;
            font-weight: 700;
            color: var(--text);
            text-transform: uppercase;
            letter-spacing: 0.03em;
            line-height: 1.3;
        }
        .svcf-node .node-sub {
            font-size: 0.66rem;
            color: var(--muted);
            margin-top: 2px;
            line-height: 1.35;
        }

        &#x2F;* --- Engage: the interface with stakeholders --- *&#x2F;
        .svcf-engage {
            background: rgba(130,150,171,0.08);
            min-width: 96px;
            flex-shrink: 0;
        }

        &#x2F;* --- Core: Plan on top, 3 activities, Improve at the bottom --- *&#x2F;
        .svcf-core {
            display: flex;
            flex-direction: column;
            gap: 8px;
            border: 1px solid var(--border);
            padding: 10px;
            background: var(--bg);
            min-width: 0;
        }
        .svcf-span-bar {
            padding: 7px 10px;
        }
        .svcf-plan {
            background: rgba(168,154,112,0.08);
        }
        .svcf-plan:hover, .svcf-plan.active { border-color: var(--yellow); }
        .svcf-plan .node-name { color: var(--yellow); }
        .svcf-improve {
            background: rgba(143,169,143,0.08);
        }
        .svcf-improve:hover, .svcf-improve.active { border-color: var(--green); }
        .svcf-improve .node-name { color: var(--green); }
        .svcf-span-bar .node-name { font-size: 0.72rem; }
        .svcf-span-bar .node-sub { display: inline; margin-left: 6px; }

        .svcf-core-row {
            display: flex;
            gap: 8px;
        }
        .svcf-core-row .svcf-node { flex: 1; min-width: 0; }

        &#x2F;* --- Products &amp; services --- *&#x2F;
        .svcf-products {
            background: rgba(171,145,121,0.08);
            min-width: 96px;
            flex-shrink: 0;
        }
        .svcf-products:hover, .svcf-products.active { border-color: var(--orange); }
        .svcf-products .node-name { color: var(--orange); }

        .svcf-note {
            text-align: center;
            font-size: 0.75rem;
            color: var(--muted);
            margin-top: 16px;
            font-style: italic;
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .svcf-info-panel {
            margin-top: 16px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .svcf-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .svcf-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svcf-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .svcf-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .svcf-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .svcf-legend {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-top: 16px;
            font-size: 0.75rem;
            color: var(--muted);
            justify-content: center;
        }
        .svcf-legend-item { display: flex; align-items: center; gap: 5px; }
        .svcf-legend-dot {
            width: 8px; height: 8px;
            display: inline-block;
        }

        @media (max-width: 720px) {
            .svcf-layout { flex-direction: column; }
            .svcf-arrow { transform: rotate(90deg); }
            .svcf-core { width: 100%; }
            .svcf-core-row { flex-direction: column; }
            .svcf-engage, .svcf-products { min-width: 0; width: 100%; max-width: 280px; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svcf-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: Service Value Chain (SVC)&lt;&#x2F;h2&gt;
        &lt;p&gt;How demand becomes value. Click any element to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svcf-layout&quot;&gt;
        &lt;!-- Demand --&gt;
        &lt;div class=&quot;svcf-io&quot; data-svc=&quot;demand&quot;&gt;
            &lt;span class=&quot;io-icon&quot;&gt;▹&lt;&#x2F;span&gt;
            &lt;div class=&quot;io-name&quot;&gt;Demand&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcf-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;

        &lt;!-- Engage: the gateway --&gt;
        &lt;div class=&quot;svcf-node svcf-engage&quot; data-svc=&quot;engage&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;⇄&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Engage&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Stakeholders &amp;amp; needs&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcf-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;

        &lt;!-- Core: plan above, improve below --&gt;
        &lt;div class=&quot;svcf-core&quot;&gt;
            &lt;div class=&quot;svcf-node svcf-span-bar svcf-plan&quot; data-svc=&quot;plan&quot;&gt;
                &lt;span class=&quot;node-name&quot;&gt;Plan&lt;&#x2F;span&gt;
                &lt;span class=&quot;node-sub&quot;&gt;direction &amp;amp; strategy, spanning every activity&lt;&#x2F;span&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svcf-core-row&quot;&gt;
                &lt;div class=&quot;svcf-node&quot; data-svc=&quot;design&quot;&gt;
                    &lt;span class=&quot;node-icon&quot;&gt;◇&lt;&#x2F;span&gt;
                    &lt;div class=&quot;node-name&quot;&gt;Design &amp;amp;&lt;br&gt;Transition&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
                &lt;div class=&quot;svcf-node&quot; data-svc=&quot;build&quot;&gt;
                    &lt;span class=&quot;node-icon&quot;&gt;▲&lt;&#x2F;span&gt;
                    &lt;div class=&quot;node-name&quot;&gt;Obtain &#x2F;&lt;br&gt;Build&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
                &lt;div class=&quot;svcf-node&quot; data-svc=&quot;deliver&quot;&gt;
                    &lt;span class=&quot;node-icon&quot;&gt;▸&lt;&#x2F;span&gt;
                    &lt;div class=&quot;node-name&quot;&gt;Deliver &amp;amp;&lt;br&gt;Support&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svcf-node svcf-span-bar svcf-improve&quot; data-svc=&quot;improve&quot;&gt;
                &lt;span class=&quot;node-name&quot;&gt;Improve&lt;&#x2F;span&gt;
                &lt;span class=&quot;node-sub&quot;&gt;continual, spanning every activity&lt;&#x2F;span&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcf-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;

        &lt;!-- Products &amp; Services --&gt;
        &lt;div class=&quot;svcf-node svcf-products&quot; data-svc=&quot;products&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;▣&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Products &amp;amp;&lt;br&gt;Services&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svcf-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;

        &lt;!-- Value --&gt;
        &lt;div class=&quot;svcf-io io-value&quot; data-svc=&quot;value&quot;&gt;
            &lt;span class=&quot;io-icon&quot;&gt;◆&lt;&#x2F;span&gt;
            &lt;div class=&quot;io-name&quot;&gt;Value&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svcf-note&quot;&gt;⇄ The chain is non-linear: each value stream combines the six activities differently&lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;svcf-info-panel&quot; id=&quot;svcf-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click an element above to see its role in the chain&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svcf-legend&quot;&gt;
        &lt;div class=&quot;svcf-legend-item&quot;&gt;&lt;span class=&quot;svcf-legend-dot&quot; style=&quot;background:#a89a70&quot;&gt;&lt;&#x2F;span&gt; Plan: spans the chain&lt;&#x2F;div&gt;
        &lt;div class=&quot;svcf-legend-item&quot;&gt;&lt;span class=&quot;svcf-legend-dot&quot; style=&quot;background:#8296ab&quot;&gt;&lt;&#x2F;span&gt; Engage &amp;amp; core activities&lt;&#x2F;div&gt;
        &lt;div class=&quot;svcf-legend-item&quot;&gt;&lt;span class=&quot;svcf-legend-dot&quot; style=&quot;background:#8fa98f&quot;&gt;&lt;&#x2F;span&gt; Improve: spans the chain&lt;&#x2F;div&gt;
        &lt;div class=&quot;svcf-legend-item&quot;&gt;&lt;span class=&quot;svcf-legend-dot&quot; style=&quot;background:#ab9179&quot;&gt;&lt;&#x2F;span&gt; Products &amp;amp; Services&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        demand: {
            title: &quot;Demand&quot;,
            desc: &quot;What enters the chain: the need or desire for products and services from internal and external consumers. Together with opportunity, demand is the raw input the whole SVS exists to convert into value.&quot;,
            items: [&quot;User needs &amp; requests&quot;, &quot;Business requirements&quot;, &quot;Market opportunities&quot;]
        },
        engage: {
            title: &quot;Engage: the gateway&quot;,
            desc: &quot;Provides a good understanding of stakeholder needs, enables transparency, and maintains productive relationships. In the big picture, Engage sits between demand and the rest of the chain: it is the primary contact point between the organization and its customers and users.&quot;,
            items: [&quot;Service requests intake&quot;, &quot;User feedback collection&quot;, &quot;Customer communications&quot;, &quot;SLA negotiation&quot;]
        },
        plan: {
            title: &quot;Plan: spanning the whole chain&quot;,
            desc: &quot;Ensures a shared understanding of vision, current status, and direction for all four dimensions. It sits above the delivery activities because its outputs (plans, policies, portfolios, architectures) are used by every other activity.&quot;,
            items: [&quot;Capacity planning&quot;, &quot;IT strategy&quot;, &quot;Risk register updates&quot;, &quot;Architecture decisions&quot;]
        },
        design: {
            title: &quot;Design &amp; Transition&quot;,
            desc: &quot;Ensures products and services continually meet stakeholder expectations for quality, costs, and time-to-market. Includes design, testing, and transitioning services into live operation.&quot;,
            items: [&quot;Service design documents&quot;, &quot;Test plans&quot;, &quot;Release planning&quot;, &quot;Training materials&quot;]
        },
        build: {
            title: &quot;Obtain &#x2F; Build&quot;,
            desc: &quot;Ensures service components are available when and where needed, meeting agreed specifications. Covers both acquiring from suppliers and building internally.&quot;,
            items: [&quot;Software development&quot;, &quot;Infrastructure provisioning&quot;, &quot;Vendor procurement&quot;, &quot;Configuration of components&quot;]
        },
        deliver: {
            title: &quot;Deliver &amp; Support&quot;,
            desc: &quot;Ensures services are delivered and supported according to agreed specifications and stakeholder expectations. Day-to-day operations, incident management, and service fulfillment.&quot;,
            items: [&quot;Incident resolution&quot;, &quot;Service desk operations&quot;, &quot;Monitoring &amp; alerting&quot;, &quot;Fulfilling service requests&quot;]
        },
        improve: {
            title: &quot;Improve: spanning the whole chain&quot;,
            desc: &quot;Ensures continual improvement across all products, services, and practices. It sits below the delivery activities because it works in parallel with all of them: every component of the SVS is subject to improvement at all times.&quot;,
            items: [&quot;Post-incident reviews&quot;, &quot;Performance trend analysis&quot;, &quot;Process optimization&quot;, &quot;Updating the CIR&quot;]
        },
        products: {
            title: &quot;Products &amp; Services&quot;,
            desc: &quot;What the chain produces: products (configurations of resources) delivered as services to consumers. This is the tangible output that carries value to the customer. The poster places it between the chain and value itself.&quot;,
            items: [&quot;A product is a configuration of resources&quot;, &quot;A service bundles one or more products&quot;, &quot;Described in the service catalog&quot;]
        },
        value: {
            title: &quot;Value&quot;,
            desc: &quot;The end of the chain and the reason it exists. Value = Utility (fit for purpose) × Warranty (fit for use), and it is co-created with the consumer, not delivered at them. If an activity in the chain doesn&#x27;t trace back to this box, it shouldn&#x27;t be in the value stream.&quot;,
            items: [&quot;Utility: does it do the right thing?&quot;, &quot;Warranty: does it do it reliably?&quot;, &quot;Co-created with the service consumer&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svcf-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svcflow-wrapper [data-svc]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.svc;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svcflow-wrapper [data-svc]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;service-relationships&quot;&gt;Service relationships&lt;&#x2F;h2&gt;
&lt;p&gt;An org is both provider and consumer.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-srm-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-srm-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-srm-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .srm-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .srm-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .srm-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- The chain of organizations --- *&#x2F;
        .srm-chain {
            display: flex;
            align-items: stretch;
            justify-content: center;
            gap: 6px;
        }

        .srm-org {
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 12px 10px;
            text-align: center;
            width: 128px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            display: flex;
            flex-direction: column;
            justify-content: center;
        }
        .srm-org:hover { transform: translateY(-1px); border-color: var(--blue); }
        .srm-org.active {
            border-color: var(--blue);
            box-shadow: 0 0 0 2px rgba(130,150,171,0.25);
        }
        .srm-org .org-icon { font-size: 1.25rem; margin-bottom: 4px; }
        .srm-org .org-name {
            font-size: 0.78rem;
            font-weight: 700;
            color: var(--text);
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .srm-org .org-roles {
            margin-top: 6px;
            display: flex;
            flex-direction: column;
            gap: 3px;
        }
        .srm-org .org-role {
            font-size: 0.62rem;
            padding: 2px 5px;
            border: 1px solid var(--border);
            background: var(--bg2);
        }
        .role-provider { color: var(--blue); }
        .role-consumer { color: var(--orange); }

        &#x2F;* --- Relationship links --- *&#x2F;
        .srm-link {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-width: 92px;
            cursor: pointer;
            padding: 6px 4px;
            border: 1px dashed transparent;
            transition: border-color 0.2s, background 0.2s;
        }
        .srm-link:hover, .srm-link.active {
            border-color: var(--green);
            background: rgba(143,169,143,0.06);
        }
        .srm-link .link-provide, .srm-link .link-consume {
            font-size: 0.62rem;
            line-height: 1.3;
        }
        .srm-link .link-provide { color: var(--blue); }
        .srm-link .link-consume { color: var(--orange); }
        .srm-link .link-name {
            font-size: 0.64rem;
            font-weight: 700;
            color: var(--green);
            text-transform: uppercase;
            letter-spacing: 0.04em;
            margin: 3px 0;
            text-align: center;
            line-height: 1.3;
        }

        &#x2F;* --- Anatomy of one relationship --- *&#x2F;
        .srm-anatomy {
            max-width: 640px;
            margin: 26px auto 0;
            border: 1px dashed var(--green);
            padding: 14px;
        }
        .srm-anatomy-title {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 600;
            color: var(--green);
            text-transform: uppercase;
            letter-spacing: 0.08em;
            margin-bottom: 10px;
        }
        .srm-anatomy-row {
            display: flex;
            gap: 8px;
        }
        .srm-comp {
            flex: 1;
            border: 1px solid var(--border);
            padding: 10px;
            text-align: center;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            min-width: 0;
        }
        .srm-comp:hover { transform: translateY(-1px); }
        .srm-comp.active { box-shadow: 0 0 0 2px rgba(130,150,171,0.25); }
        .srm-comp .comp-name {
            font-size: 0.7rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.03em;
            line-height: 1.3;
        }
        .srm-comp .comp-sub {
            font-size: 0.64rem;
            color: var(--muted);
            margin-top: 3px;
            line-height: 1.35;
        }
        .comp-provision { background: rgba(130,150,171,0.08); }
        .comp-provision:hover, .comp-provision.active { border-color: var(--blue); }
        .comp-provision .comp-name { color: var(--blue); }
        .comp-joint { background: rgba(143,169,143,0.08); }
        .comp-joint:hover, .comp-joint.active { border-color: var(--green); }
        .comp-joint .comp-name { color: var(--green); }
        .comp-consumption { background: rgba(171,145,121,0.08); }
        .comp-consumption:hover, .comp-consumption.active { border-color: var(--orange); }
        .comp-consumption .comp-name { color: var(--orange); }

        &#x2F;* --- Info panel --- *&#x2F;
        .srm-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .srm-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .srm-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .srm-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .srm-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .srm-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .srm-legend {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-top: 16px;
            font-size: 0.75rem;
            color: var(--muted);
            justify-content: center;
        }
        .srm-legend-item { display: flex; align-items: center; gap: 5px; }
        .srm-legend-dot {
            width: 8px; height: 8px;
            display: inline-block;
        }

        .srm-footnote {
            margin-top: 14px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
            padding: 0 8px;
        }

        @media (max-width: 720px) {
            .srm-chain { flex-direction: column; align-items: center; }
            .srm-org { width: 100%; max-width: 260px; }
            .srm-link { min-width: 0; width: 100%; max-width: 260px; }
            .srm-anatomy-row { flex-direction: column; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;srm-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: Service Relationships&lt;&#x2F;h2&gt;
        &lt;p&gt;Every organization is both provider and consumer. Click an organization, a relationship, or a component&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- The chain --&gt;
    &lt;div class=&quot;srm-chain&quot;&gt;
        &lt;div class=&quot;srm-org&quot; data-srm=&quot;orga&quot;&gt;
            &lt;div class=&quot;org-icon&quot;&gt;■&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-name&quot;&gt;Organization A&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-roles&quot;&gt;
                &lt;span class=&quot;org-role role-provider&quot;&gt;Provider → B&lt;&#x2F;span&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;srm-link&quot; data-srm=&quot;relationship&quot;&gt;
            &lt;span class=&quot;link-provide&quot;&gt;provision →&lt;&#x2F;span&gt;
            &lt;span class=&quot;link-name&quot;&gt;Service&lt;br&gt;Relationship&lt;&#x2F;span&gt;
            &lt;span class=&quot;link-consume&quot;&gt;← consumption&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;srm-org&quot; data-srm=&quot;middle&quot;&gt;
            &lt;div class=&quot;org-icon&quot;&gt;■&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-name&quot;&gt;Organization B&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-roles&quot;&gt;
                &lt;span class=&quot;org-role role-consumer&quot;&gt;Consumer ← A&lt;&#x2F;span&gt;
                &lt;span class=&quot;org-role role-provider&quot;&gt;Provider → C&lt;&#x2F;span&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;srm-link&quot; data-srm=&quot;relationship&quot;&gt;
            &lt;span class=&quot;link-provide&quot;&gt;provision →&lt;&#x2F;span&gt;
            &lt;span class=&quot;link-name&quot;&gt;Service&lt;br&gt;Relationship&lt;&#x2F;span&gt;
            &lt;span class=&quot;link-consume&quot;&gt;← consumption&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;srm-org&quot; data-srm=&quot;middle&quot;&gt;
            &lt;div class=&quot;org-icon&quot;&gt;■&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-name&quot;&gt;Organization C&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-roles&quot;&gt;
                &lt;span class=&quot;org-role role-consumer&quot;&gt;Consumer ← B&lt;&#x2F;span&gt;
                &lt;span class=&quot;org-role role-provider&quot;&gt;Provider → D&lt;&#x2F;span&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;srm-link&quot; data-srm=&quot;relationship&quot;&gt;
            &lt;span class=&quot;link-provide&quot;&gt;provision →&lt;&#x2F;span&gt;
            &lt;span class=&quot;link-name&quot;&gt;Service&lt;br&gt;Relationship&lt;&#x2F;span&gt;
            &lt;span class=&quot;link-consume&quot;&gt;← consumption&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;srm-org&quot; data-srm=&quot;orgd&quot;&gt;
            &lt;div class=&quot;org-icon&quot;&gt;■&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-name&quot;&gt;Organization D&lt;&#x2F;div&gt;
            &lt;div class=&quot;org-roles&quot;&gt;
                &lt;span class=&quot;org-role role-consumer&quot;&gt;Consumer ← C&lt;&#x2F;span&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Anatomy of one relationship --&gt;
    &lt;div class=&quot;srm-anatomy&quot;&gt;
        &lt;div class=&quot;srm-anatomy-title&quot;&gt;Inside every service relationship&lt;&#x2F;div&gt;
        &lt;div class=&quot;srm-anatomy-row&quot;&gt;
            &lt;div class=&quot;srm-comp comp-provision&quot; data-srm=&quot;provision&quot;&gt;
                &lt;div class=&quot;comp-name&quot;&gt;Service Provision&lt;&#x2F;div&gt;
                &lt;div class=&quot;comp-sub&quot;&gt;What the provider does&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;srm-comp comp-joint&quot; data-srm=&quot;srmgmt&quot;&gt;
                &lt;div class=&quot;comp-name&quot;&gt;Service Relationship Management&lt;&#x2F;div&gt;
                &lt;div class=&quot;comp-sub&quot;&gt;What both do, together&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;srm-comp comp-consumption&quot; data-srm=&quot;consumption&quot;&gt;
                &lt;div class=&quot;comp-name&quot;&gt;Service Consumption&lt;&#x2F;div&gt;
                &lt;div class=&quot;comp-sub&quot;&gt;What the consumer does&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;srm-info-panel&quot; id=&quot;srm-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click an element above to see its role in the relationship model&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;srm-legend&quot;&gt;
        &lt;div class=&quot;srm-legend-item&quot;&gt;&lt;span class=&quot;srm-legend-dot&quot; style=&quot;background:#8296ab&quot;&gt;&lt;&#x2F;span&gt; Provider side: provision&lt;&#x2F;div&gt;
        &lt;div class=&quot;srm-legend-item&quot;&gt;&lt;span class=&quot;srm-legend-dot&quot; style=&quot;background:#8fa98f&quot;&gt;&lt;&#x2F;span&gt; Joint: relationship management&lt;&#x2F;div&gt;
        &lt;div class=&quot;srm-legend-item&quot;&gt;&lt;span class=&quot;srm-legend-dot&quot; style=&quot;background:#ab9179&quot;&gt;&lt;&#x2F;span&gt; Consumer side: consumption&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;srm-footnote&quot;&gt;
        Not to be confused with &lt;em&gt;relationship management&lt;&#x2F;em&gt;, one of the 14 general management
        practices: that practice lives inside a single provider, while service relationship
        management is the joint activity spanning both parties of a service relationship.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        orga: {
            title: &quot;Organization A: pure provider (in this chain)&quot;,
            desc: &quot;The upstream end of this particular chain: A only provides here. But zoom out and A is itself a consumer of other services: electricity, connectivity, hardware. No organization is only a provider; the chain is a fragment of a larger ecosystem.&quot;,
            items: [&quot;Example: a cloud vendor&quot;, &quot;Provides services to B&quot;, &quot;Consumer in other chains we don&#x27;t see here&quot;]
        },
        middle: {
            title: &quot;Organizations B &amp; C: both consumer and provider&quot;,
            desc: &quot;The normal case. B consumes A&#x27;s services and uses them to provide its own services to C: value flows through, transformed at each step. Your IT direction is exactly here: it consumes M365 from Microsoft and provides application support to the labs. Each side of that position is a distinct relationship to manage.&quot;,
            items: [&quot;Consumes upstream, provides downstream&quot;, &quot;Transforms what it consumes into what it provides&quot;, &quot;Manages (at least) two relationships at once&quot;]
        },
        orgd: {
            title: &quot;Organization D: end consumer (in this chain)&quot;,
            desc: &quot;The downstream end: D consumes C&#x27;s services to achieve its own outcomes. This is where the value the whole chain exists for is finally co-created, and if D&#x27;s outcomes aren&#x27;t met, every upstream relationship in the chain is ultimately failing.&quot;,
            items: [&quot;Example: lab technicians, field teams&quot;, &quot;Their outcomes justify the whole chain&quot;, &quot;Value is co-created here, not delivered here&quot;]
        },
        relationship: {
            title: &quot;Service Relationship&quot;,
            desc: &quot;A cooperation between a service provider and a service consumer. Not a one-way pipe: provision flows one way, consumption and feedback flow back, and the relationship itself is managed jointly. ITIL 4 defines it as containing exactly three components (see the anatomy box below).&quot;,
            items: [&quot;Service provision (provider)&quot;, &quot;Service consumption (consumer)&quot;, &quot;Service relationship management (joint)&quot;]
        },
        provision: {
            title: &quot;Service Provision: the provider&#x27;s side&quot;,
            desc: &quot;Activities performed by the provider: supplying access to resources, fulfilling agreed service actions, delivering the service per specification. This is where service management (the provider&#x27;s specialized organizational capabilities) does its work.&quot;,
            items: [&quot;Access to resources&quot;, &quot;Fulfilment of service actions&quot;, &quot;Service level management &amp; reporting&quot;]
        },
        srmgmt: {
            title: &quot;Service Relationship Management: the joint part&quot;,
            desc: &quot;Joint activities performed by provider AND consumer to ensure continual value co-creation, based on agreed and available service offerings. This is the component you cannot do alone: agreeing on offerings, negotiating expectations, exchanging feedback, reviewing outcomes. Deliver flawlessly without ever talking to the consumer, and this box is empty: SLAs met, users furious.&quot;,
            items: [&quot;Agree on service offerings&quot;, &quot;Negotiate &amp; review expectations&quot;, &quot;Exchange feedback both ways&quot;, &quot;Verify value is actually co-created&quot;]
        },
        consumption: {
            title: &quot;Service Consumption: the consumer&#x27;s side&quot;,
            desc: &quot;Activities performed by the consumer: using the provider&#x27;s resources, requesting service actions, and providing what the provider needs (information, payment, decisions). Consumption is active: a consumer who never reports, never requests, never decides, starves the relationship.&quot;,
            items: [&quot;Use of resources&quot;, &quot;Requesting service actions&quot;, &quot;Providing information &amp; payment&quot;]
        }
    };

    const panel = document.getElementById(&#x27;srm-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-srm-wrapper [data-srm]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.srm;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-srm-wrapper [data-srm]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;continual-improvement&quot;&gt;Continual improvement&lt;&#x2F;h2&gt;
&lt;p&gt;I remember a very old woman who used to say &lt;em&gt;&quot;Moins on en fait, mieux on se porte&quot;&lt;&#x2F;em&gt; lol.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-cim-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-cim-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-cim-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .cim-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .cim-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .cim-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- Step rows --- *&#x2F;
        .cim-flow {
            max-width: 620px;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            align-items: stretch;
        }

        .cim-step {
            display: flex;
            align-items: stretch;
            gap: 8px;
            cursor: pointer;
        }

        .cim-question {
            flex: 1.1;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 10px 12px;
            display: flex;
            align-items: center;
            gap: 10px;
            transition: border-color 0.2s, transform 0.1s;
        }
        .cim-step:hover .cim-question { border-color: var(--green); transform: translateY(-1px); }
        .cim-step.active .cim-question {
            border-color: var(--green);
            box-shadow: 0 0 0 2px rgba(143,169,143,0.25);
        }
        .cim-num {
            width: 26px;
            height: 26px;
            border: 2px solid var(--green);
            color: var(--green);
            font-size: 0.72rem;
            font-weight: 700;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
        }
        .cim-question .q-text {
            font-size: 0.78rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.03em;
            line-height: 1.35;
        }

        .cim-pair-arrow {
            display: flex;
            align-items: center;
            color: var(--green);
            font-size: 1.1rem;
            flex-shrink: 0;
        }

        .cim-action {
            flex: 1;
            background: rgba(143,169,143,0.07);
            border: 1px solid var(--border);
            padding: 10px 12px;
            display: flex;
            align-items: center;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.45;
            transition: border-color 0.2s;
        }
        .cim-step:hover .cim-action, .cim-step.active .cim-action { border-color: var(--green); }

        .cim-down-arrow {
            text-align: left;
            color: var(--green);
            font-size: 1rem;
            line-height: 1;
            padding: 4px 0 4px 24px;
            opacity: 0.8;
        }

        &#x2F;* --- The loop back --- *&#x2F;
        .cim-loop {
            margin-top: 4px;
            border: 1px dashed var(--green);
            padding: 10px 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            cursor: pointer;
            transition: background 0.2s, box-shadow 0.2s;
        }
        .cim-loop:hover, .cim-loop.active { background: rgba(143,169,143,0.06); }
        .cim-loop.active { box-shadow: 0 0 0 2px rgba(143,169,143,0.25); }
        .cim-loop .loop-icon { font-size: 1.1rem; color: var(--green); }
        .cim-loop .loop-text {
            font-size: 0.78rem;
            font-weight: 700;
            color: var(--green);
            text-transform: uppercase;
            letter-spacing: 0.03em;
        }
        .cim-loop .loop-sub {
            font-size: 0.7rem;
            color: var(--muted);
            font-style: italic;
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .cim-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .cim-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .cim-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .cim-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .cim-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .cim-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .cim-footnote {
            margin-top: 14px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
            padding: 0 8px;
        }

        @media (max-width: 560px) {
            .cim-step { flex-direction: column; gap: 4px; }
            .cim-pair-arrow { transform: rotate(90deg); justify-content: center; padding: 0; }
            .cim-down-arrow { text-align: center; padding-left: 0; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;cim-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: Continual Improvement&lt;&#x2F;h2&gt;
        &lt;p&gt;The 7-step model: each question paired with the action that answers it. Click a step to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;cim-flow&quot;&gt;
        &lt;div class=&quot;cim-step&quot; data-cim=&quot;s1&quot;&gt;
            &lt;div class=&quot;cim-question&quot;&gt;&lt;span class=&quot;cim-num&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;q-text&quot;&gt;What is the vision?&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-pair-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-action&quot;&gt;Business vision, mission, goals and objectives&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;cim-down-arrow&quot;&gt;↓&lt;&#x2F;div&gt;

        &lt;div class=&quot;cim-step&quot; data-cim=&quot;s2&quot;&gt;
            &lt;div class=&quot;cim-question&quot;&gt;&lt;span class=&quot;cim-num&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;q-text&quot;&gt;Where are we now?&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-pair-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-action&quot;&gt;Perform a baseline assessment&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;cim-down-arrow&quot;&gt;↓&lt;&#x2F;div&gt;

        &lt;div class=&quot;cim-step&quot; data-cim=&quot;s3&quot;&gt;
            &lt;div class=&quot;cim-question&quot;&gt;&lt;span class=&quot;cim-num&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;q-text&quot;&gt;Where do we want to be?&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-pair-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-action&quot;&gt;Define measurable targets&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;cim-down-arrow&quot;&gt;↓&lt;&#x2F;div&gt;

        &lt;div class=&quot;cim-step&quot; data-cim=&quot;s4&quot;&gt;
            &lt;div class=&quot;cim-question&quot;&gt;&lt;span class=&quot;cim-num&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;q-text&quot;&gt;How do we get there?&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-pair-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-action&quot;&gt;Define the improvement plan&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;cim-down-arrow&quot;&gt;↓&lt;&#x2F;div&gt;

        &lt;div class=&quot;cim-step&quot; data-cim=&quot;s5&quot;&gt;
            &lt;div class=&quot;cim-question&quot;&gt;&lt;span class=&quot;cim-num&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;q-text&quot;&gt;Take action&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-pair-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-action&quot;&gt;Execute the improvement actions&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;cim-down-arrow&quot;&gt;↓&lt;&#x2F;div&gt;

        &lt;div class=&quot;cim-step&quot; data-cim=&quot;s6&quot;&gt;
            &lt;div class=&quot;cim-question&quot;&gt;&lt;span class=&quot;cim-num&quot;&gt;6&lt;&#x2F;span&gt;&lt;span class=&quot;q-text&quot;&gt;Did we get there?&lt;&#x2F;span&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-pair-arrow&quot;&gt;⇄&lt;&#x2F;div&gt;
            &lt;div class=&quot;cim-action&quot;&gt;Evaluate metrics and KPIs&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;cim-down-arrow&quot;&gt;↓&lt;&#x2F;div&gt;

        &lt;div class=&quot;cim-loop&quot; data-cim=&quot;s7&quot;&gt;
            &lt;span class=&quot;loop-icon&quot;&gt;↻&lt;&#x2F;span&gt;
            &lt;span class=&quot;loop-text&quot;&gt;7. How do we keep the momentum going?&lt;&#x2F;span&gt;
            &lt;span class=&quot;loop-sub&quot;&gt;(loops back to step 1)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;cim-info-panel&quot; id=&quot;cim-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a step above to see what it involves&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;cim-footnote&quot;&gt;
        Continual improvement appears three times in ITIL 4: as a guiding principle (a mindset),
        as one of the 34 practices (with the CIR as its operational tool), and as the
        &lt;em&gt;Improve&lt;&#x2F;em&gt; activity of the service value chain. This model is how the practice
        actually runs, and reaching step 7 doesn&#x27;t mean you&#x27;re done, it means you start over.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        s1: {
            title: &quot;1. What is the vision?&quot;,
            desc: &quot;Anchor the improvement to the business strategy: vision, mission, goals, and objectives. An improvement that doesn&#x27;t serve a stakeholder&#x27;s actual goal is process theater. This step is &#x27;focus on value&#x27; applied before any work starts.&quot;,
            items: [&quot;Align with business strategy&quot;, &quot;Identify who benefits and how&quot;, &quot;Set the high-level direction&quot;]
        },
        s2: {
            title: &quot;2. Where are we now?&quot;,
            desc: &quot;Perform a baseline assessment: metrics, maturity level, user perception (measured, not assumed). Without a baseline you cannot prove anything improved. This is &#x27;start where you are&#x27;: observe the current state directly before designing anything.&quot;,
            items: [&quot;Baseline metrics &amp; KPIs&quot;, &quot;Maturity assessment&quot;, &quot;Direct observation over assumptions&quot;]
        },
        s3: {
            title: &quot;3. Where do we want to be?&quot;,
            desc: &quot;Define the target state with measurable success criteria: the gap between step 2 and step 3 is the improvement. Vague targets (&#x27;be faster&#x27;) produce vague results; measurable ones (&#x27;reduce MTTR on P1 incidents by 40% this quarter&#x27;) can actually be verified at step 6.&quot;,
            items: [&quot;Measurable targets&quot;, &quot;Gap analysis&quot;, &quot;Success criteria defined up front&quot;]
        },
        s4: {
            title: &quot;4. How do we get there?&quot;,
            desc: &quot;Build the improvement plan. ITIL recommends an iterative approach: if the full path isn&#x27;t clear, plan the first increments and refine as feedback arrives, the same logic as &#x27;progress iteratively with feedback&#x27;.&quot;,
            items: [&quot;Improvement plan&quot;, &quot;Iterative increments&quot;, &quot;Owners and timeline assigned&quot;]
        },
        s5: {
            title: &quot;5. Take action&quot;,
            desc: &quot;Execute the plan. Keep the work visible (kanban, dashboards) and deliver in increments rather than one big bang. Many improvements die here: logged in a register, planned, and never actually executed, which is why the CIR tracks status.&quot;,
            items: [&quot;Execute iteratively&quot;, &quot;Keep work visible&quot;, &quot;Track status in the CIR&quot;]
        },
        s6: {
            title: &quot;6. Did we get there?&quot;,
            desc: &quot;Evaluate metrics and KPIs against the success criteria defined at step 3. Honestly: if the target wasn&#x27;t reached, that&#x27;s a finding, not a failure. It feeds the next iteration. Measure both the SLA side (did the numbers move?) and the XLA side (did anyone notice?).&quot;,
            items: [&quot;Compare against step-3 criteria&quot;, &quot;KPIs &amp; SLAs: did the numbers move?&quot;, &quot;XLAs: did users feel it?&quot;]
        },
        s7: {
            title: &quot;7. How do we keep the momentum going?&quot;,
            desc: &quot;Embed the change so it doesn&#x27;t quietly revert: update runbooks, adjust onboarding, celebrate the win, communicate the result. Then loop back to step 1 with a new vision: the model is a cycle by design, not a checklist you finish.&quot;,
            items: [&quot;Embed the change (docs, training)&quot;, &quot;Celebrate &amp; communicate wins&quot;, &quot;Start the cycle again&quot;]
        }
    };

    const panel = document.getElementById(&#x27;cim-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-cim-wrapper [data-cim]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.cim;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-cim-wrapper [data-cim]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-34-practices&quot;&gt;The 34 practices&lt;&#x2F;h2&gt;
&lt;p&gt;The 34 practices. Adopt the ones that solve your problems and leave the rest on the shelf.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-prac-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-prac-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-prac-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .prac-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .prac-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .prac-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        &#x2F;* --- Category cards --- *&#x2F;
        .prac-cats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
            gap: 10px;
            max-width: 680px;
            margin: 0 auto;
        }
        .prac-cat {
            border: 1px solid var(--border);
            padding: 14px 12px;
            text-align: center;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
        }
        .prac-cat:hover { transform: translateY(-1px); }
        .prac-cat.active { box-shadow: 0 0 0 2px rgba(130,150,171,0.25); }
        .prac-cat .cat-count {
            font-size: 1.6rem;
            font-weight: 700;
            line-height: 1;
        }
        .prac-cat .cat-name {
            font-size: 0.76rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            margin-top: 5px;
            line-height: 1.3;
        }
        .prac-cat .cat-sub {
            font-size: 0.66rem;
            color: var(--muted);
            margin-top: 4px;
            line-height: 1.4;
        }
        .cat-general { background: rgba(155,143,171,0.08); }
        .cat-general:hover, .cat-general.active { border-color: var(--purple); }
        .cat-general .cat-count, .cat-general .cat-name { color: var(--purple); }
        .cat-service { background: rgba(130,150,171,0.08); }
        .cat-service:hover, .cat-service.active { border-color: var(--blue); }
        .cat-service .cat-count, .cat-service .cat-name { color: var(--blue); }
        .cat-technical { background: rgba(171,145,121,0.08); }
        .cat-technical:hover, .cat-technical.active { border-color: var(--orange); }
        .cat-technical .cat-count, .cat-technical .cat-name { color: var(--orange); }

        &#x2F;* --- The 7 exam practices --- *&#x2F;
        .prac-seven {
            max-width: 680px;
            margin: 22px auto 0;
            border: 1px dashed var(--green);
            padding: 14px;
        }
        .prac-seven-title {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 600;
            color: var(--green);
            text-transform: uppercase;
            letter-spacing: 0.08em;
            margin-bottom: 10px;
        }
        .prac-chips {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            justify-content: center;
        }
        .prac-chip {
            font-size: 0.72rem;
            font-weight: 600;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 6px 10px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            color: var(--text);
        }
        .prac-chip:hover { border-color: var(--green); transform: translateY(-1px); }
        .prac-chip.active {
            border-color: var(--green);
            box-shadow: 0 0 0 2px rgba(143,169,143,0.25);
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .prac-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .prac-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .prac-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .prac-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .prac-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .prac-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .prac-footnote {
            margin-top: 14px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
            padding: 0 8px;
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;prac-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: The 34 Management Practices&lt;&#x2F;h2&gt;
        &lt;p&gt;Three categories, adopt what solves your problems. Click a category or a practice&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;prac-cats&quot;&gt;
        &lt;div class=&quot;prac-cat cat-general&quot; data-prac=&quot;general&quot;&gt;
            &lt;div class=&quot;cat-count&quot;&gt;14&lt;&#x2F;div&gt;
            &lt;div class=&quot;cat-name&quot;&gt;General&lt;br&gt;Management&lt;&#x2F;div&gt;
            &lt;div class=&quot;cat-sub&quot;&gt;Adapted from general business management&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;prac-cat cat-service&quot; data-prac=&quot;service&quot;&gt;
            &lt;div class=&quot;cat-count&quot;&gt;17&lt;&#x2F;div&gt;
            &lt;div class=&quot;cat-name&quot;&gt;Service&lt;br&gt;Management&lt;&#x2F;div&gt;
            &lt;div class=&quot;cat-sub&quot;&gt;The heart of ITSM day-to-day work&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;prac-cat cat-technical&quot; data-prac=&quot;technical&quot;&gt;
            &lt;div class=&quot;cat-count&quot;&gt;3&lt;&#x2F;div&gt;
            &lt;div class=&quot;cat-name&quot;&gt;Technical&lt;br&gt;Management&lt;&#x2F;div&gt;
            &lt;div class=&quot;cat-sub&quot;&gt;Adapted from technology management&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;prac-seven&quot;&gt;
        &lt;div class=&quot;prac-seven-title&quot;&gt;The 7 practices the Foundation exam drills into&lt;&#x2F;div&gt;
        &lt;div class=&quot;prac-chips&quot;&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;ci&quot;&gt;Continual improvement&lt;&#x2F;span&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;change&quot;&gt;Change enablement&lt;&#x2F;span&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;incident&quot;&gt;Incident management&lt;&#x2F;span&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;problem&quot;&gt;Problem management&lt;&#x2F;span&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;request&quot;&gt;Service request management&lt;&#x2F;span&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;desk&quot;&gt;Service desk&lt;&#x2F;span&gt;
            &lt;span class=&quot;prac-chip&quot; data-prac=&quot;slm&quot;&gt;Service level management&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;prac-info-panel&quot; id=&quot;prac-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a category or a practice above&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;prac-footnote&quot;&gt;
        Adopt and adapt: nobody implements all 34. Identify your pain points,
        pick the practices that address them, and leave the rest on the shelf.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        general: {
            title: &quot;General management practices (14)&quot;,
            desc: &quot;Practices adopted and adapted from general business management domains. They would exist even if the organization ran no IT at all.&quot;,
            items: [&quot;Continual improvement&quot;, &quot;Risk management&quot;, &quot;Knowledge management&quot;, &quot;Project management&quot;, &quot;Supplier management&quot;, &quot;Relationship management&quot;, &quot;Information security management&quot;, &quot;Workforce &amp; talent management&quot;, &quot;…and 6 more&quot;]
        },
        service: {
            title: &quot;Service management practices (17)&quot;,
            desc: &quot;Practices developed in service management and ITSM: the operational heart of ITIL. This is where most of the practices you&#x27;d recognize from a ticketing tool live.&quot;,
            items: [&quot;Incident management&quot;, &quot;Problem management&quot;, &quot;Change enablement&quot;, &quot;Service desk&quot;, &quot;Service level management&quot;, &quot;Service request management&quot;, &quot;Service catalogue management&quot;, &quot;IT asset management&quot;, &quot;Monitoring &amp; event management&quot;, &quot;…and 8 more&quot;]
        },
        technical: {
            title: &quot;Technical management practices (3)&quot;,
            desc: &quot;Practices adapted from technology management domains for service management purposes. Only three, and easy exam points, since you can list them all:&quot;,
            items: [&quot;Deployment management&quot;, &quot;Infrastructure &amp; platform management&quot;, &quot;Software development &amp; management&quot;]
        },
        ci: {
            title: &quot;Continual improvement&quot;,
            desc: &quot;Aligns services and practices with changing needs through the ongoing improvement of everything, at every level. Operates through the 7-step model and the Continual Improvement Register (CIR).&quot;,
            items: [&quot;7-step improvement model&quot;, &quot;CIR: the improvement backlog&quot;, &quot;Also a guiding principle and an SVC activity&quot;]
        },
        change: {
            title: &quot;Change enablement&quot;,
            desc: &quot;Maximizes the number of successful changes by ensuring risks are assessed and authorized before anything ships. Three change types, three levels of ceremony.&quot;,
            items: [&quot;Standard: pre-authorized, low risk&quot;, &quot;Normal: assessed &amp; authorized (CAB)&quot;, &quot;Emergency: fast-tracked authority&quot;]
        },
        incident: {
            title: &quot;Incident management&quot;,
            desc: &quot;Restores normal service operation as fast as possible after an unplanned interruption or degradation. Priority is set by impact × urgency; escalate functionally (expertise) or hierarchically (authority).&quot;,
            items: [&quot;Goal: restore service ASAP&quot;, &quot;Priority = impact × urgency&quot;, &quot;P1 → all hands; P4 → schedule it&quot;]
        },
        problem: {
            title: &quot;Problem management&quot;,
            desc: &quot;Manages the causes of incidents. Where incident management asks &#x27;how do we restore service?&#x27;, problem management asks &#x27;why did this happen, and how do we prevent the next one?&#x27;. A documented workaround turns a problem into a known error.&quot;,
            items: [&quot;Problem = cause of incidents&quot;, &quot;Known error = analyzed + workaround&quot;, &quot;Reactive and proactive modes&quot;]
        },
        request: {
            title: &quot;Service request management&quot;,
            desc: &quot;Handles predefined, pre-approved requests: nothing is broken, nothing unexpected changes. Fulfilled per SLA from the service catalog, and the highest automation opportunity in the framework.&quot;,
            items: [&quot;Pre-approved via the catalog&quot;, &quot;Password resets, access, equipment&quot;, &quot;Optimize first, then automate&quot;]
        },
        desk: {
            title: &quot;Service desk&quot;,
            desc: &quot;The single point of contact between the provider and its users. Captures demand for incident resolution and service requests, and owns the user experience of support, whatever happens behind the curtain.&quot;,
            items: [&quot;Single point of contact&quot;, &quot;Captures &amp; triages all demand&quot;, &quot;Owns the support experience&quot;]
        },
        slm: {
            title: &quot;Service level management&quot;,
            desc: &quot;Sets clear, business-based targets for service performance and ensures delivery is properly assessed, monitored, and reported against them. Where SLAs are negotiated, and where XLAs should temper them.&quot;,
            items: [&quot;Negotiates &amp; tracks SLAs&quot;, &quot;Business-based targets, not vanity metrics&quot;, &quot;Watch the SLA vs XLA gap&quot;]
        }
    };

    const panel = document.getElementById(&#x27;prac-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-prac-wrapper [data-prac]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.prac;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-prac-wrapper [data-prac]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;what-kind-of-ticket-is-this&quot;&gt;What kind of ticket is this?&lt;&#x2F;h2&gt;
&lt;p&gt;The question every IT team answers a dozen times a day.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-tree-wrapper&quot;&gt;
&lt;style&gt;
.itil4-tree-wrapper {
    --bg:     #0d1117;
    --bg2:    #161b22;
    --bg3:    #21262d;
    --border: #30363d;
    --text:   #e6edf3;
    --muted:  #8b949e;
    --blue:   #8296ab;
    --green:  #8fa98f;
    --orange: #ab9179;
    --red:    #ab7d79;
    --yellow: #a89a70;
    --purple: #9b8fab;
    font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
    background: var(--bg);
    color: var(--text);
    padding: 28px 20px;
    margin: 30px 0;
}
.itil4-tree-wrapper * { box-sizing: border-box; margin: 0; padding: 0; }

.tree-header { text-align: center; margin-bottom: 22px; }
.tree-header h2 { font-size: 1.2rem; font-weight: 700; color: var(--blue); text-transform: uppercase; letter-spacing: 0.05em; }
.tree-header p  { color: var(--muted); font-size: 0.8rem; margin-top: 5px; }

.tree-breadcrumb {
    display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 14px;
    min-height: 24px;
}
.tree-crumb {
    font-size: 0.68rem; padding: 2px 8px;    border: 1px solid; white-space: nowrap;
}
.tree-crumb.yes { color: var(--green);  border-color: rgba(143,169,143,0.4);  background: rgba(143,169,143,0.07); }
.tree-crumb.no  { color: var(--orange); border-color: rgba(171,145,121,0.4); background: rgba(171,145,121,0.07); }

.tree-question {
    background: var(--bg2); border: 1px solid var(--border);    padding: 20px; margin-bottom: 14px;
}
.tree-q-step { font-size: 0.68rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px; }
.tree-q-text { font-size: 0.97rem; font-weight: 600; color: var(--text); line-height: 1.55; }

.tree-buttons { display: flex; gap: 10px; margin-bottom: 14px; }
.tree-btn {
    flex: 1; padding: 11px 16px; border: 1px solid;
    cursor: pointer; font-size: 0.85rem; font-weight: 700; letter-spacing: 0.02em;
    transition: opacity 0.15s, transform 0.1s; text-align: center; background: transparent;
    font-family: inherit;
}
.tree-btn:hover { opacity: 0.82; transform: translateY(-1px); }
.tree-btn.yes-btn { border-color: var(--green);  color: var(--green);  background: rgba(143,169,143,0.09); }
.tree-btn.no-btn  { border-color: var(--orange); color: var(--orange); background: rgba(171,145,121,0.09); }

.tree-result {
    background: var(--bg2); padding: 20px;
    margin-bottom: 14px; display: none;
}
.tree-result.show { display: block; }
.tree-result-badge {
    display: inline-block; padding: 3px 12px;    font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; margin-bottom: 10px; border: 1px solid;
}
.tree-result-title { font-size: 1.05rem; font-weight: 700; color: var(--text); margin-bottom: 8px; }
.tree-result-desc  { font-size: 0.84rem; color: var(--muted); line-height: 1.6; margin-bottom: 10px; }
.tree-result-tags  { display: flex; flex-wrap: wrap; gap: 5px; }
.tree-result-tag {
    font-size: 0.7rem; background: var(--bg3); border: 1px solid var(--border);
 padding: 2px 8px; color: var(--orange);
}

.tree-restart {
    display: none; background: transparent; border: 1px solid var(--border);
 padding: 9px 20px; color: var(--muted); cursor: pointer;
    font-size: 0.8rem; width: 100%; transition: border-color 0.15s, color 0.15s;
    font-family: inherit;
}
.tree-restart.show { display: block; }
.tree-restart:hover { border-color: var(--blue); color: var(--blue); }
&lt;&#x2F;style&gt;

&lt;div class=&quot;tree-header&quot;&gt;
    &lt;h2&gt;What kind of ticket is this?&lt;&#x2F;h2&gt;
    &lt;p&gt;Answer each question to classify your request&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-breadcrumb&quot; id=&quot;itil-tree-crumbs&quot;&gt;&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-question&quot; id=&quot;itil-tree-question&quot;&gt;
    &lt;div class=&quot;tree-q-step&quot;  id=&quot;itil-tree-step&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-q-text&quot;  id=&quot;itil-tree-text&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-buttons&quot; id=&quot;itil-tree-btns&quot;&gt;
    &lt;button class=&quot;tree-btn yes-btn&quot; id=&quot;itil-tree-yes&quot;&gt;Yes&lt;&#x2F;button&gt;
    &lt;button class=&quot;tree-btn no-btn&quot;  id=&quot;itil-tree-no&quot;&gt;No&lt;&#x2F;button&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-result&quot; id=&quot;itil-tree-result&quot;&gt;
    &lt;div class=&quot;tree-result-badge&quot; id=&quot;itil-tree-badge&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-result-title&quot; id=&quot;itil-tree-rtitle&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-result-desc&quot;  id=&quot;itil-tree-rdesc&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-result-tags&quot;  id=&quot;itil-tree-rtags&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;button class=&quot;tree-restart&quot; id=&quot;itil-tree-restart&quot;&gt;↺ Start over&lt;&#x2F;button&gt;

&lt;script&gt;
(function () {
    var tree = {
        q1: {
            step: &quot;Question 1 of 4&quot;,
            text: &quot;Was this unplanned or unexpected, something that wasn&#x27;t meant to happen?&quot;,
            yes: &quot;q2a&quot;, no: &quot;q2b&quot;,
            crumb: &quot;Unplanned?&quot;
        },
        q2a: {
            step: &quot;Question 2 of 4&quot;,
            text: &quot;Is the service degraded or completely unavailable right now?&quot;,
            yes: &quot;incident&quot;, no: &quot;q3a&quot;,
            crumb: &quot;Service down?&quot;
        },
        q3a: {
            step: &quot;Question 3 of 4&quot;,
            text: &quot;Has the root cause already been identified and documented?&quot;,
            yes: &quot;known_error&quot;, no: &quot;problem&quot;,
            crumb: &quot;Root cause known?&quot;
        },
        q2b: {
            step: &quot;Question 2 of 4&quot;,
            text: &quot;Do you want to add, modify, or configure something in the IT environment?&quot;,
            yes: &quot;q3b&quot;, no: &quot;service_request&quot;,
            crumb: &quot;Modify IT?&quot;
        },
        q3b: {
            step: &quot;Question 3 of 4&quot;,
            text: &quot;Is this a predefined, well-understood, low-risk action with a documented procedure?&quot;,
            yes: &quot;std_change&quot;, no: &quot;q4b&quot;,
            crumb: &quot;Predefined &amp; low-risk?&quot;
        },
        q4b: {
            step: &quot;Question 4 of 4&quot;,
            text: &quot;Does this need to bypass the normal review cycle? Is it urgent enough to fast-track?&quot;,
            yes: &quot;emerg_change&quot;, no: &quot;normal_change&quot;,
            crumb: &quot;Urgent?&quot;
        }
    };

    var results = {
        incident: {
            color: &quot;#ab7d79&quot;,
            badge: &quot;Incident&quot;,
            title: &quot;Open an Incident ticket&quot;,
            desc: &quot;An unplanned interruption or reduction in service quality. Priority = Impact × Urgency. The immediate goal is service restoration. Root cause investigation comes later, via Problem Management.&quot;,
            tags: [&quot;Respond immediately&quot;, &quot;Prioritize by impact + urgency&quot;, &quot;Log timestamp + affected service&quot;, &quot;Escalate if P1&#x2F;P2&quot;]
        },
        problem: {
            color: &quot;#a89a70&quot;,
            badge: &quot;Problem&quot;,
            title: &quot;Open a Problem ticket&quot;,
            desc: &quot;The unknown or unconfirmed cause of one or more incidents. Not urgent in the incident sense (the service may be running), but it must be investigated to prevent the next occurrence.&quot;,
            tags: [&quot;Link to related incidents&quot;, &quot;Assign for root cause analysis&quot;, &quot;5 Whys or Fishbone&quot;, &quot;Track until permanent fix&quot;]
        },
        known_error: {
            color: &quot;#ab9179&quot;,
            badge: &quot;Known Error&quot;,
            title: &quot;Log a Known Error record&quot;,
            desc: &quot;Root cause is identified. Document the workaround in the known error database so any future recurrence is resolved in minutes. The problem stays open until the permanent fix ships.&quot;,
            tags: [&quot;Document the workaround&quot;, &quot;Link to parent problem&quot;, &quot;Open a Change to permanently fix&quot;, &quot;Notify support team&quot;]
        },
        service_request: {
            color: &quot;#8296ab&quot;,
            badge: &quot;Service Request&quot;,
            title: &quot;Submit a Service Request&quot;,
            desc: &quot;A predefined, pre-approved request for something in the service catalog. Nothing is broken; this is a routine interaction. Fulfillment follows a documented procedure: no new risk assessment needed.&quot;,
            tags: [&quot;Use the service catalog&quot;, &quot;SLA starts at submission&quot;, &quot;Should eventually be automated&quot;, &quot;Log for reporting&quot;]
        },
        std_change: {
            color: &quot;#8fa98f&quot;,
            badge: &quot;Standard Change&quot;,
            title: &quot;Execute as a Standard Change&quot;,
            desc: &quot;Pre-authorized, low-risk, documented procedure with a known outcome. No CAB review required. Follow the approved process and log the change for audit purposes.&quot;,
            tags: [&quot;Pre-authorized&quot;, &quot;Follow approved procedure&quot;, &quot;Log for audit trail&quot;, &quot;No CAB required&quot;]
        },
        normal_change: {
            color: &quot;#a89a70&quot;,
            badge: &quot;Normal Change&quot;,
            title: &quot;Submit an RFC for CAB review&quot;,
            desc: &quot;A change requiring risk assessment and authorization before implementation. Prepare an RFC with impact assessment, risk matrix, rollback plan, and communication plan. Awaits Change Authority review.&quot;,
            tags: [&quot;Submit RFC&quot;, &quot;Impact + risk assessment&quot;, &quot;Tested rollback plan required&quot;, &quot;CAB review before action&quot;]
        },
        emerg_change: {
            color: &quot;#ab7d79&quot;,
            badge: &quot;Emergency Change&quot;,
            title: &quot;Initiate Emergency Change process&quot;,
            desc: &quot;Fast-tracked through emergency authority because urgency outweighs normal review time. Speed does not mean no process: document, implement, then complete the post-implementation review.&quot;,
            tags: [&quot;Emergency authority required&quot;, &quot;Implement first, document in parallel&quot;, &quot;Post-implementation review mandatory&quot;, &quot;Notify all stakeholders&quot;]
        }
    };

    var state = &quot;q1&quot;;
    var crumbs = [];

    var elCrumbs  = document.getElementById(&#x27;itil-tree-crumbs&#x27;);
    var elQ       = document.getElementById(&#x27;itil-tree-question&#x27;);
    var elStep    = document.getElementById(&#x27;itil-tree-step&#x27;);
    var elText    = document.getElementById(&#x27;itil-tree-text&#x27;);
    var elBtns    = document.getElementById(&#x27;itil-tree-btns&#x27;);
    var elResult  = document.getElementById(&#x27;itil-tree-result&#x27;);
    var elBadge   = document.getElementById(&#x27;itil-tree-badge&#x27;);
    var elRTitle  = document.getElementById(&#x27;itil-tree-rtitle&#x27;);
    var elRDesc   = document.getElementById(&#x27;itil-tree-rdesc&#x27;);
    var elRTags   = document.getElementById(&#x27;itil-tree-rtags&#x27;);
    var elRestart = document.getElementById(&#x27;itil-tree-restart&#x27;);

    function renderCrumbs() {
        elCrumbs.innerHTML = crumbs.map(function(c) {
            return &#x27;&lt;span class=&quot;tree-crumb &#x27; + c.answer + &#x27;&quot;&gt;&#x27; + c.label + &#x27; → &#x27; + (c.answer === &#x27;yes&#x27; ? &#x27;Yes&#x27; : &#x27;No&#x27;) + &#x27;&lt;&#x2F;span&gt;&#x27;;
        }).join(&#x27;&#x27;);
    }

    function renderQuestion() {
        var node = tree[state];
        elStep.textContent = node.step;
        elText.textContent = node.text;
        elQ.style.display      = &#x27;block&#x27;;
        elBtns.style.display   = &#x27;flex&#x27;;
        elResult.classList.remove(&#x27;show&#x27;);
        elRestart.classList.remove(&#x27;show&#x27;);
        renderCrumbs();
    }

    function renderResult(key) {
        var r = results[key];
        elQ.style.display    = &#x27;none&#x27;;
        elBtns.style.display = &#x27;none&#x27;;

        elBadge.textContent = r.badge;
        elBadge.style.color      = r.color;
        elBadge.style.borderColor = r.color + &#x27;66&#x27;;
        elBadge.style.background  = r.color + &#x27;18&#x27;;

        elRTitle.textContent = r.title;
        elRDesc.textContent  = r.desc;
        elRTags.innerHTML    = r.tags.map(function(t) {
            return &#x27;&lt;span class=&quot;tree-result-tag&quot;&gt;&#x27; + t + &#x27;&lt;&#x2F;span&gt;&#x27;;
        }).join(&#x27;&#x27;);

        elResult.classList.add(&#x27;show&#x27;);
        elRestart.classList.add(&#x27;show&#x27;);
        renderCrumbs();
    }

    function answer(yes) {
        var node = tree[state];
        crumbs.push({ label: node.crumb, answer: yes ? &#x27;yes&#x27; : &#x27;no&#x27; });
        var next = yes ? node.yes : node.no;
        if (results[next]) {
            renderResult(next);
        } else {
            state = next;
            renderQuestion();
        }
    }

    document.getElementById(&#x27;itil-tree-yes&#x27;).addEventListener(&#x27;click&#x27;, function() { answer(true); });
    document.getElementById(&#x27;itil-tree-no&#x27;).addEventListener(&#x27;click&#x27;,  function() { answer(false); });
    document.getElementById(&#x27;itil-tree-restart&#x27;).addEventListener(&#x27;click&#x27;, function() {
        state = &quot;q1&quot;;
        crumbs = [];
        renderQuestion();
    });

    renderQuestion();
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;the-toy-exam&quot;&gt;The toy exam&lt;&#x2F;h2&gt;
&lt;p&gt;Here are 60 &lt;em&gt;(not so hidden)&lt;&#x2F;em&gt; questions, to help you prepare the exam.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-exam-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-exam-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-exam-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .ex-title-block { text-align: center; margin-bottom: 22px; }
        .ex-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .ex-title-block p { color: var(--muted); font-size: 0.85rem; margin-top: 6px; }

        .ex-body { max-width: 640px; margin: 0 auto; }

        .ex-btn {
            display: inline-block;
            background: rgba(130,150,171,0.12);
            border: 1px solid var(--blue-dim);
            color: var(--blue);
            padding: 10px 22px;
            font-size: 0.85rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            cursor: pointer;
            transition: background 0.2s, transform 0.1s;
            font-family: inherit;
        }
        .ex-btn:hover { background: rgba(130,150,171,0.22); transform: translateY(-1px); }

        .ex-start, .ex-result { text-align: center; padding: 18px 0; }
        .ex-start p, .ex-result p { font-size: 0.85rem; color: var(--muted); line-height: 1.7; margin-bottom: 16px; }
        .ex-result .ex-score {
            font-size: 2.2rem;
            font-weight: 700;
            margin-bottom: 4px;
        }
        .ex-result .ex-verdict {
            display: inline-block;
            font-size: 0.8rem;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.06em;
            padding: 4px 14px;
            margin-bottom: 14px;
        }
        .ex-verdict.pass { color: var(--green); border: 1px solid var(--green); }
        .ex-verdict.fail { color: var(--red); border: 1px solid var(--red); }

        .ex-progress { margin-bottom: 14px; }
        .ex-progress-text {
            display: flex;
            justify-content: space-between;
            font-size: 0.72rem;
            color: var(--muted);
            margin-bottom: 5px;
        }
        .ex-progress-bar {
            height: 5px;
            background: var(--bg3);
            overflow: hidden;
        }
        .ex-progress-fill {
            height: 100%;
            background: var(--blue-dim);
            transition: width 0.25s;
        }

        .ex-question {
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 14px 16px;
            font-size: 0.9rem;
            font-weight: 600;
            line-height: 1.55;
            margin-bottom: 12px;
        }

        .ex-options { display: flex; flex-direction: column; gap: 8px; }
        .ex-option {
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 10px 14px;
            font-size: 0.82rem;
            line-height: 1.5;
            text-align: left;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            color: var(--text);
            font-family: inherit;
            width: 100%;
        }
        .ex-option:hover:not(:disabled) { border-color: var(--blue); transform: translateY(-1px); }
        .ex-option:disabled { cursor: default; opacity: 0.75; }
        .ex-option.correct {
            border-color: var(--green);
            background: rgba(143,169,143,0.1);
            opacity: 1;
        }
        .ex-option.wrong {
            border-color: var(--red);
            background: rgba(171,125,121,0.1);
            opacity: 1;
        }

        .ex-explain {
            margin-top: 12px;
            padding: 12px 14px;
            font-size: 0.8rem;
            line-height: 1.6;
        }
        .ex-explain.good { border: 1px solid var(--green); background: rgba(143,169,143,0.06); }
        .ex-explain.bad { border: 1px solid var(--red); background: rgba(171,125,121,0.06); }
        .ex-explain .ex-explain-head {
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.04em;
            font-size: 0.72rem;
            margin-bottom: 4px;
        }
        .ex-explain.good .ex-explain-head { color: var(--green); }
        .ex-explain.bad .ex-explain-head { color: var(--red); }

        .ex-nav { margin-top: 14px; text-align: right; }

        .ex-footnote {
            margin-top: 18px;
            font-size: 0.72rem;
            color: var(--muted);
            line-height: 1.6;
            text-align: center;
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;ex-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: The Toy Exam&lt;&#x2F;h2&gt;
        &lt;p&gt;60 questions, drawn at random from a bank of 200+&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;ex-body&quot; id=&quot;ex-body&quot;&gt;&lt;&#x2F;div&gt;

    &lt;div class=&quot;ex-footnote&quot;&gt;
        For reference, the real Foundation exam: 40 questions, 65% to pass (26&#x2F;40), 60 minutes,
        closed book.
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    &#x2F;&#x2F; [question, [correct, wrong, wrong, wrong], explanation]
    &#x2F;&#x2F; The correct option is ALWAYS first here; options are shuffled at render time.
    const BANK = [
        &#x2F;&#x2F; --- Key concepts: value, service, product, offering, actors, relationships ---
        [&quot;Which is the BEST definition of a service?&quot;,
         [&quot;A means of enabling value co-creation by facilitating outcomes that customers want to achieve&quot;,
          &quot;A configuration of an organization&#x27;s resources designed to offer value&quot;,
          &quot;A set of specialized organizational capabilities for enabling value&quot;,
          &quot;A formal description of one or more offerings designed for a target group&quot;],
         &quot;That is the ITIL definition of a service. The &#x27;configuration of resources&#x27; is a product; the &#x27;specialized capabilities&#x27; is service management; the &#x27;formal description&#x27; is a service offering.&quot;],
        [&quot;A product is defined as:&quot;,
         [&quot;A configuration of an organization&#x27;s resources designed to offer value to a consumer&quot;,
          &quot;Any component that must be managed in order to deliver a service&quot;,
          &quot;A tangible deliverable of an activity&quot;,
          &quot;One or more services designed for a target consumer group&quot;],
         &quot;A product is a configuration of resources. &#x27;Any component to be managed&#x27; is a configuration item; a &#x27;tangible deliverable&#x27; is an output; &#x27;services for a target group&#x27; is a service offering.&quot;],
        [&quot;Service management is defined as a set of specialized organizational capabilities for:&quot;,
         [&quot;Enabling value for customers in the form of services&quot;,
          &quot;Delivering products at the lowest possible cost&quot;,
          &quot;Managing incidents, problems, and changes&quot;,
          &quot;Ensuring compliance with policies and regulations&quot;],
         &quot;The definition centers on enabling value in the form of services, not on cost, on specific practices, or on compliance.&quot;],
        [&quot;Value is BEST described as:&quot;,
         [&quot;The perceived benefits, usefulness, and importance of something&quot;,
          &quot;The amount of money a customer pays for a service&quot;,
          &quot;The number of features a product provides&quot;,
          &quot;The uptime a provider guarantees in the SLA&quot;],
         &quot;Value is perception: benefits, usefulness, importance as judged by the stakeholder. Price, feature count, and uptime may contribute, but none of them IS value.&quot;],
        [&quot;Who creates the value of a service?&quot;,
         [&quot;The provider and the consumer, together&quot;,
          &quot;The provider alone, by delivering to specification&quot;,
          &quot;The consumer alone, by using the service&quot;,
          &quot;The sponsor, by funding the service&quot;],
         &quot;Value is co-created through active collaboration between provider and consumer. Delivering to specification without consumer engagement does not by itself produce value.&quot;],
        [&quot;&#x27;Utility&#x27; means the service is:&quot;,
         [&quot;Fit for purpose: it supports the consumer&#x27;s performance or removes constraints&quot;,
          &quot;Fit for use: available, secure, and able to handle the load&quot;,
          &quot;Cheap enough to be worth buying&quot;,
          &quot;Compliant with all applicable regulations&quot;],
         &quot;Utility is fit for purpose (what the service does). Fit for use is warranty. Cost and compliance are separate considerations.&quot;],
        [&quot;Which question belongs to WARRANTY rather than utility?&quot;,
         [&quot;Is the service available when the users need it?&quot;,
          &quot;Does the service support the task the customer needs to perform?&quot;,
          &quot;Does the service remove a constraint from the customer?&quot;,
          &quot;Does the service do the right thing?&quot;],
         &quot;Warranty is fit for use: availability, capacity, security, continuity. The other three questions all test utility: whether the service does the right thing.&quot;],
        [&quot;A service does exactly what users need but crashes every Monday morning. It has:&quot;,
         [&quot;Utility but insufficient warranty&quot;,
          &quot;Warranty but insufficient utility&quot;,
          &quot;Neither utility nor warranty&quot;,
          &quot;Both utility and warranty, since it works most of the time&quot;],
         &quot;Doing the right thing = utility present. Crashing regularly = warranty failing. Since value needs both, this service delivers little value despite its features.&quot;],
        [&quot;Which is NOT typically an aspect covered by warranty?&quot;,
         [&quot;The functionality offered by the service&quot;,
          &quot;Availability&quot;,
          &quot;Capacity&quot;,
          &quot;Security&quot;],
         &quot;Functionality is utility. Warranty covers how reliably the service performs: availability, capacity, security, and continuity.&quot;],
        [&quot;A monitoring service produces a weekly report, and thanks to it the team prevents an outage. The prevented outage is:&quot;,
         [&quot;An outcome&quot;,
          &quot;An output&quot;,
          &quot;A deliverable&quot;,
          &quot;A configuration item&quot;],
         &quot;The report is the output (what the service produces); the prevented outage is the outcome (the result the stakeholder achieves thanks to the output).&quot;],
        [&quot;An outcome is defined as:&quot;,
         [&quot;A result for a stakeholder, enabled by one or more outputs&quot;,
          &quot;A tangible or intangible deliverable of an activity&quot;,
          &quot;The net benefit after costs are subtracted&quot;,
          &quot;A measurable KPI agreed in the SLA&quot;],
         &quot;Outcome = result for a stakeholder enabled by outputs. The &#x27;deliverable of an activity&#x27; is the definition of an output, the classic trap.&quot;],
        [&quot;How can a service CONSUMER contribute to the reduction of risk?&quot;,
         [&quot;By clearly defining requirements and communicating constraints&quot;,
          &quot;By transferring all risk to the provider in the contract&quot;,
          &quot;By avoiding any contact with the provider after signing&quot;,
          &quot;By demanding penalties for every SLA breach&quot;],
         &quot;Risk reduction is collaborative: the consumer contributes by defining requirements clearly, communicating criticality and constraints, and participating actively in the relationship.&quot;],
        [&quot;Which is an example of a COST REMOVED from the consumer by a service?&quot;,
         [&quot;No longer having to buy and operate their own servers&quot;,
          &quot;The monthly subscription fee&quot;,
          &quot;The cost of training staff on the new tool&quot;,
          &quot;The cost of migrating data to the new platform&quot;],
         &quot;Removed costs are expenses the consumer no longer carries. Subscription, training, and migration are all costs INTRODUCED by the service. They sit on the other pan of the scale.&quot;],
        [&quot;Which is an example of a RISK INTRODUCED by consuming a cloud service?&quot;,
         [&quot;Vendor lock-in&quot;,
          &quot;Hardware failure of the consumer&#x27;s own servers&quot;,
          &quot;Losing in-house data-center staff to competitors&quot;,
          &quot;An earthquake destroying the consumer&#x27;s building&quot;],
         &quot;Lock-in is a new risk the consumer accepts by adopting the service. Own-hardware failure is a risk the service typically REMOVES; the others are unrelated to the service decision.&quot;],
        [&quot;In an honest value assessment, &#x27;affected outcomes&#x27; refers to:&quot;,
         [&quot;Results that the service impacts negatively, such as lost flexibility&quot;,
          &quot;Outcomes that were achieved thanks to the service&quot;,
          &quot;Outcomes that the SLA does not mention&quot;,
          &quot;Any outcome that cannot be measured&quot;],
         &quot;Affected outcomes are the fine print: results negatively impacted by adopting the service (constrained workflows, lost flexibility). They weigh on the minus pan of the value scale.&quot;],
        [&quot;A service offering may include which three components?&quot;,
         [&quot;Goods, access to resources, and service actions&quot;,
          &quot;Utility, warranty, and value&quot;,
          &quot;Products, practices, and principles&quot;,
          &quot;Incidents, problems, and changes&quot;],
         &quot;Service offerings are described in terms of goods (ownership transferred), access to resources, and service actions performed for the consumer.&quot;],
        [&quot;In a service offering, &#x27;goods&#x27; are items whose:&quot;,
         [&quot;Ownership is transferred to the consumer&quot;,
          &quot;Ownership remains with the provider&quot;,
          &quot;Use is billed per minute&quot;,
          &quot;Warranty is excluded&quot;],
         &quot;Goods (e.g. a phone handset) are transferred to the consumer, who becomes responsible for them. Access to resources is the component where ownership stays with the provider.&quot;],
        [&quot;When a consumer is granted &#x27;access to resources&#x27;:&quot;,
         [&quot;Ownership stays with the provider; the consumer uses the resource under agreed terms&quot;,
          &quot;Ownership transfers to the consumer at first use&quot;,
          &quot;The consumer may resell the resource&quot;,
          &quot;The provider loses all responsibility for the resource&quot;],
         &quot;Access is licensed or granted per agreed terms: the mobile network you use belongs to the operator, not to you.&quot;],
        [&quot;&#x27;Service actions&#x27; in a service offering are:&quot;,
         [&quot;Actions performed by the provider to address a consumer&#x27;s needs, such as user support&quot;,
          &quot;Actions performed by users when consuming the service&quot;,
          &quot;Automated scripts triggered by monitoring&quot;,
          &quot;The steps of the incident lifecycle&quot;],
         &quot;Service actions are performed by the provider (e.g. replacing a broken device, answering a support call), on the consumer&#x27;s behalf, per agreement.&quot;],
        [&quot;A telecom offer includes a handset you keep, network connectivity, and phone repair when broken. Respectively these are:&quot;,
         [&quot;Goods, access to resources, and a service action&quot;,
          &quot;Access to resources, goods, and a service action&quot;,
          &quot;Goods, a service action, and access to resources&quot;,
          &quot;Three different goods&quot;],
         &quot;The handset is transferred (goods), the network is used but never owned (access), and the repair is performed by the provider (service action).&quot;],
        [&quot;The CUSTOMER is the role that:&quot;,
         [&quot;Defines the requirements for a service and takes responsibility for the outcomes&quot;,
          &quot;Uses the service day-to-day&quot;,
          &quot;Authorizes the budget for the service&quot;,
          &quot;Delivers the service to the organization&quot;],
         &quot;Customer = requirements + outcomes. The day-to-day person is the user; the budget holder is the sponsor; the deliverer is the provider.&quot;],
        [&quot;The USER is the role that:&quot;,
         [&quot;Uses the service on a day-to-day basis&quot;,
          &quot;Approves the service budget&quot;,
          &quot;Signs the SLA with the provider&quot;,
          &quot;Owns the risk register&quot;],
         &quot;Users interact with the service daily. They may never see the budget or the SLA, which is exactly why XLAs exist.&quot;],
        [&quot;The SPONSOR is the role that:&quot;,
         [&quot;Authorizes the budget for service consumption&quot;,
          &quot;Defines the functional requirements&quot;,
          &quot;Provides first-line support&quot;,
          &quot;Manages the provider&#x27;s resources&quot;],
         &quot;The sponsor pays. Requirements belong to the customer, support to the provider.&quot;],
        [&quot;Can one person hold the customer, user, and sponsor roles simultaneously?&quot;,
         [&quot;Yes: for example a freelancer buying, configuring, and using a laptop&quot;,
          &quot;No: ITIL requires the roles to be separated&quot;,
          &quot;Only in organizations of fewer than five people&quot;,
          &quot;Only if the CAB approves it&quot;],
         &quot;The roles are hats, not headcount. In small contexts one person wears all three; in a large enterprise they are usually different people.&quot;],
        [&quot;A stakeholder is BEST defined as:&quot;,
         [&quot;Any person or organization with an interest in an organization, product, or service&quot;,
          &quot;Anyone who pays for a service&quot;,
          &quot;Any employee of the service provider&quot;,
          &quot;The regulator overseeing the industry&quot;],
         &quot;Stakeholder is the broadest term: customers, users, sponsors, employees, partners, regulators, even society can be stakeholders.&quot;],
        [&quot;ITIL defines an ORGANIZATION as:&quot;,
         [&quot;A person or group with its own functions, responsibilities, authorities, and relationships&quot;,
          &quot;A legal entity with more than 10 employees&quot;,
          &quot;Any registered company&quot;,
          &quot;A department within an enterprise&quot;],
         &quot;The definition is deliberately broad: a single person or a team can be an &#x27;organization&#x27; in ITIL terms, which is what makes provider&#x2F;consumer chains work at any scale.&quot;],
        [&quot;Which activity belongs to service CONSUMPTION?&quot;,
         [&quot;Requesting service actions to fulfil a need&quot;,
          &quot;Granting access to resources&quot;,
          &quot;Fulfilment of service actions&quot;,
          &quot;Negotiating the SLA on behalf of the provider&quot;],
         &quot;Consumption includes using resources, receiving goods, and REQUESTING service actions. Granting access and fulfilling actions are provision, the provider&#x27;s side.&quot;],
        [&quot;Which activity belongs to service PROVISION?&quot;,
         [&quot;Providing access to resources&quot;,
          &quot;Using the provider&#x27;s resources&quot;,
          &quot;Receiving the goods&quot;,
          &quot;Paying the subscription&quot;],
         &quot;Provision is the provider&#x27;s side: providing access, fulfilling service actions, service level management. The other three are consumption.&quot;],
        [&quot;A service relationship includes which three elements?&quot;,
         [&quot;Service provision, service consumption, and service relationship management&quot;,
          &quot;Utility, warranty, and value&quot;,
          &quot;Engage, deliver, and improve&quot;,
          &quot;Goods, access, and actions&quot;],
         &quot;A service relationship = provision (provider side) + consumption (consumer side) + relationship management (joint). The other options are different ITIL triads.&quot;],
        [&quot;Service relationship management consists of:&quot;,
         [&quot;Joint activities performed by provider and consumer to ensure continual value co-creation&quot;,
          &quot;Activities performed by the provider to monitor the consumer&quot;,
          &quot;The consumer&#x27;s internal vendor-evaluation process&quot;,
          &quot;The escalation procedure defined in the SLA&quot;],
         &quot;The key word is JOINT. It is the part of the relationship neither party can do alone: agreeing offerings, exchanging feedback, verifying value.&quot;],

        &#x2F;&#x2F; --- Guiding principles ---
        [&quot;Which of these is one of the 7 guiding principles?&quot;,
         [&quot;Optimize and automate&quot;,
          &quot;Maximize and outsource&quot;,
          &quot;Standardize and centralize&quot;,
          &quot;Measure and control&quot;],
         &quot;The seven are: focus on value; start where you are; progress iteratively with feedback; collaborate and promote visibility; think and work holistically; keep it simple and practical; optimize and automate.&quot;],
        [&quot;A team assesses which parts of the current monitoring setup work well before designing a replacement. Which principle?&quot;,
         [&quot;Start where you are&quot;,
          &quot;Focus on value&quot;,
          &quot;Optimize and automate&quot;,
          &quot;Think and work holistically&quot;],
         &quot;&#x27;Start where you are&#x27; says: never assume a clean slate: observe and measure the existing state, and reuse what works.&quot;],
        [&quot;Putting all in-progress work on a public kanban board mainly applies which principle?&quot;,
         [&quot;Collaborate and promote visibility&quot;,
          &quot;Keep it simple and practical&quot;,
          &quot;Progress iteratively with feedback&quot;,
          &quot;Start where you are&quot;],
         &quot;Making work visible is the visibility half of &#x27;collaborate and promote visibility&#x27;. Hidden work and hidden agendas are what this principle fights.&quot;],
        [&quot;Removing an approval step that adds no value applies which principle?&quot;,
         [&quot;Keep it simple and practical&quot;,
          &quot;Optimize and automate&quot;,
          &quot;Focus on value&quot;,
          &quot;Start where you are&quot;],
         &quot;&#x27;Keep it simple and practical&#x27;: use the minimum number of steps needed. If a step contributes nothing to any outcome, eliminate it.&quot;],
        [&quot;Why does &#x27;optimize and automate&#x27; insist on optimizing FIRST?&quot;,
         [&quot;Automating a broken process just produces broken results faster&quot;,
          &quot;Optimization is cheaper than automation&quot;,
          &quot;Automation tools require certified processes&quot;,
          &quot;Auditors require optimization evidence before tooling&quot;],
         &quot;The order matters: fix the process (remove waste and friction), then automate what remains. Automation amplifies whatever it is given, including dysfunction.&quot;],
        [&quot;Shipping a minimum viable version, gathering user reactions, then adjusting applies which principle?&quot;,
         [&quot;Progress iteratively with feedback&quot;,
          &quot;Think and work holistically&quot;,
          &quot;Collaborate and promote visibility&quot;,
          &quot;Optimize and automate&quot;],
         &quot;Small increments plus feedback loops, the same philosophy as Agile sprints and continuous delivery.&quot;],
        [&quot;Considering how a database change affects the four dimensions and every downstream service applies which principle?&quot;,
         [&quot;Think and work holistically&quot;,
          &quot;Keep it simple and practical&quot;,
          &quot;Start where you are&quot;,
          &quot;Focus on value&quot;],
         &quot;Holistic thinking treats services as systems: no component works in isolation, and end-to-end impact must be considered.&quot;],
        [&quot;Asking &#x27;who benefits from this task, and how?&#x27; before starting it applies which principle?&quot;,
         [&quot;Focus on value&quot;,
          &quot;Collaborate and promote visibility&quot;,
          &quot;Progress iteratively with feedback&quot;,
          &quot;Optimize and automate&quot;],
         &quot;&#x27;Focus on value&#x27;: everything the organization does should map, directly or indirectly, to value for stakeholders. If nobody benefits, stop.&quot;],
        [&quot;The guiding principles can be overridden by management policy when convenient.&quot;,
         [&quot;False: they are universal and enduring, and apply in all circumstances&quot;,
          &quot;True: governance sits above the principles&quot;,
          &quot;True, but only for emergency changes&quot;,
          &quot;False, except during audits&quot;],
         &quot;The principles are the one part of ITIL that applies always and everywhere; they guide decisions rather than being subject to them.&quot;],
        [&quot;How should an organization use the 7 guiding principles?&quot;,
         [&quot;Consider all of them together and apply those that are relevant to each situation&quot;,
          &quot;Pick the single principle that fits its industry&quot;,
          &quot;Apply them in numerical order, one per quarter&quot;,
          &quot;Apply them only to service management projects&quot;],
         &quot;The principles interact and complement each other; organizations should weigh all of them and apply what is relevant, not cherry-pick one or sequence them.&quot;],
        [&quot;A project team plans to replace the entire toolchain without auditing what is currently used. Which principle are they violating MOST directly?&quot;,
         [&quot;Start where you are&quot;,
          &quot;Optimize and automate&quot;,
          &quot;Collaborate and promote visibility&quot;,
          &quot;Focus on value&quot;],
         &quot;They are assuming a clean slate. &#x27;Start where you are&#x27; requires assessing the current state first: much of it may be worth keeping.&quot;],
        [&quot;Which principle warns that decisions made without the right people in the room tend to fail?&quot;,
         [&quot;Collaborate and promote visibility&quot;,
          &quot;Think and work holistically&quot;,
          &quot;Keep it simple and practical&quot;,
          &quot;Start where you are&quot;],
         &quot;The collaboration half of the principle: involve the right stakeholders early, because silo decisions produce resistance and rework.&quot;],
        [&quot;When measuring the current state, &#x27;start where you are&#x27; recommends:&quot;,
         [&quot;Direct observation and measurement rather than assumptions and reports alone&quot;,
          &quot;Trusting last year&#x27;s audit report&quot;,
          &quot;Asking the vendor for benchmark data&quot;,
          &quot;Skipping measurement if the team agrees on the problem&quot;],
         &quot;Reports and assumptions drift from reality; the principle explicitly favors going to see and measuring directly.&quot;],
        [&quot;Which principle is MOST concerned with the end-to-end customer experience rather than individual process steps?&quot;,
         [&quot;Focus on value&quot;,
          &quot;Optimize and automate&quot;,
          &quot;Start where you are&quot;,
          &quot;Progress iteratively with feedback&quot;],
         &quot;Focus on value explicitly includes the customer and user experience, not just the technical output of each step.&quot;],
        [&quot;An improvement initiative is huge and nobody knows where to start. The principles suggest:&quot;,
         [&quot;Break it into iterations, each delivering tangible results with feedback&quot;,
          &quot;Hire consultants to deliver it in one program&quot;,
          &quot;Wait until requirements are fully stable&quot;,
          &quot;Automate the current process to save time first&quot;],
         &quot;&#x27;Progress iteratively with feedback&#x27;: large efforts become manageable as increments; each iteration produces results and lessons. Automating first violates &#x27;optimize and automate&#x27;.&quot;],
        [&quot;Which two principles most directly reinforce each other when streamlining a process before scripting it?&quot;,
         [&quot;Keep it simple and practical, then optimize and automate&quot;,
          &quot;Focus on value, then start where you are&quot;,
          &quot;Collaborate and promote visibility, then think holistically&quot;,
          &quot;Progress iteratively, then focus on value&quot;],
         &quot;Simplify first (remove valueless steps), then optimize and automate what remains. The two principles form a natural sequence.&quot;],
        [&quot;Feedback loops matter in iterative work because:&quot;,
         [&quot;Each iteration&#x27;s results reveal whether the direction is still right before more is invested&quot;,
          &quot;They satisfy audit requirements&quot;,
          &quot;They replace the need for planning&quot;,
          &quot;They guarantee the project finishes faster&quot;],
         &quot;Feedback is the point of iterating: it catches wrong turns early. Iteration without feedback is just chopped-up waterfall.&quot;],
        [&quot;&#x27;Keep it simple and practical&#x27; suggests that when designing a process you should:&quot;,
         [&quot;Start with an uncomplicated approach and add steps only when genuinely needed&quot;,
          &quot;Document every conceivable exception up front&quot;,
          &quot;Design for the most complex case first&quot;,
          &quot;Copy the most complete framework available&quot;],
         &quot;Begin simple, add complexity only where it demonstrably adds value. Designing for every exception first produces process theater.&quot;],
        [&quot;Making incident dashboards visible to the whole organization primarily serves to:&quot;,
         [&quot;Enable better decision-making based on accurate, shared information&quot;,
          &quot;Shame the teams with the most incidents&quot;,
          &quot;Satisfy the CAB&#x27;s reporting needs&quot;,
          &quot;Reduce the number of incidents automatically&quot;],
         &quot;Visibility exists to inform decisions: poor visibility of workload and flow leads to decisions based on guesswork.&quot;],
        [&quot;Which principle most directly justifies developing self-service password reset?&quot;,
         [&quot;Optimize and automate&quot;,
          &quot;Start where you are&quot;,
          &quot;Think and work holistically&quot;,
          &quot;Collaborate and promote visibility&quot;],
         &quot;Frequent, repetitive, low-risk tasks are prime automation targets, after the process is optimized. Human intervention should be reserved for where it adds value.&quot;],
        [&quot;A change to one team&#x27;s deployment script breaks another team&#x27;s reporting job nobody remembered. Which principle was neglected?&quot;,
         [&quot;Think and work holistically&quot;,
          &quot;Keep it simple and practical&quot;,
          &quot;Focus on value&quot;,
          &quot;Progress iteratively with feedback&quot;],
         &quot;The failure is not seeing the service as a system with interdependencies, exactly what holistic thinking exists to prevent.&quot;],
        [&quot;According to &#x27;focus on value&#x27;, value should be defined by:&quot;,
         [&quot;The service consumer&#x27;s needs and perception&quot;,
          &quot;The provider&#x27;s engineering standards&quot;,
          &quot;The industry benchmark&quot;,
          &quot;The most senior stakeholder&quot;],
         &quot;Value is always defined from the consumer&#x27;s perspective. The provider&#x27;s opinion of its own work is not the measure.&quot;],

        &#x2F;&#x2F; --- Four dimensions &amp; PESTLE ---
        [&quot;Which is the correct list of the four dimensions of service management?&quot;,
         [&quot;Organizations &amp; people; information &amp; technology; partners &amp; suppliers; value streams &amp; processes&quot;,
          &quot;Plan, build, run, improve&quot;,
          &quot;People, process, products, partners&quot;,
          &quot;Governance, practices, principles, improvement&quot;],
         &quot;&#x27;People, process, products, partners&#x27; is the old ITIL v3 four Ps, a classic distractor. The v4 dimensions are the first list.&quot;],
        [&quot;Organizational culture, roles, and required skills belong to which dimension?&quot;,
         [&quot;Organizations and people&quot;,
          &quot;Information and technology&quot;,
          &quot;Partners and suppliers&quot;,
          &quot;Value streams and processes&quot;],
         &quot;Structure, culture, competencies, leadership: the human dimension.&quot;],
        [&quot;A contract with a cloud hosting vendor belongs to which dimension?&quot;,
         [&quot;Partners and suppliers&quot;,
          &quot;Information and technology&quot;,
          &quot;Organizations and people&quot;,
          &quot;Value streams and processes&quot;],
         &quot;Every external relationship a provider depends on (vendors, integrators, outsourcers, and their contracts) lives in partners and suppliers.&quot;],
        [&quot;How work flows through the organization, including handoffs and approvals, belongs to which dimension?&quot;,
         [&quot;Value streams and processes&quot;,
          &quot;Organizations and people&quot;,
          &quot;Partners and suppliers&quot;,
          &quot;Information and technology&quot;],
         &quot;This dimension covers how activities are organized into value streams and processes, where waste and bottlenecks hide.&quot;],
        [&quot;Databases, monitoring platforms, and the knowledge needed to manage services belong to which dimension?&quot;,
         [&quot;Information and technology&quot;,
          &quot;Value streams and processes&quot;,
          &quot;Partners and suppliers&quot;,
          &quot;Organizations and people&quot;],
         &quot;Both the information&#x2F;knowledge and the technologies that manage and deliver services sit in this dimension.&quot;],
        [&quot;What happens when one of the four dimensions is neglected?&quot;,
         [&quot;Services degrade or fail to deliver the expected value&quot;,
          &quot;Nothing, if the other three are strong&quot;,
          &quot;Governance automatically compensates&quot;,
          &quot;Only documentation quality suffers&quot;],
         &quot;The dimensions are interdependent; ignoring one (e.g. deploying a tool without training people) is one of the most reliable ways to make a project fail.&quot;],
        [&quot;PESTLE stands for:&quot;,
         [&quot;Political, economic, social, technological, legal, environmental&quot;,
          &quot;People, economy, security, technology, law, ethics&quot;,
          &quot;Plan, engage, support, transition, learn, evaluate&quot;,
          &quot;Political, ecological, strategic, technical, legal, economic&quot;],
         &quot;PESTLE is the checklist of external factors that influence all four dimensions and that the organization cannot control.&quot;],
        [&quot;A new data-protection regulation like GDPR is which PESTLE factor?&quot;,
         [&quot;Legal&quot;,
          &quot;Political&quot;,
          &quot;Social&quot;,
          &quot;Technological&quot;],
         &quot;Compliance requirements and regulations are the legal factor. Political covers broader government policy and stability: close, but the regulation itself is legal.&quot;],
        [&quot;Pressure to reduce data-center energy consumption is which PESTLE factor?&quot;,
         [&quot;Environmental&quot;,
          &quot;Economic&quot;,
          &quot;Legal&quot;,
          &quot;Social&quot;],
         &quot;Sustainability and green IT belong to the environmental factor, though an energy tax would add an economic angle.&quot;],
        [&quot;A budget freeze across the organization is which PESTLE factor?&quot;,
         [&quot;Economic&quot;,
          &quot;Political&quot;,
          &quot;Legal&quot;,
          &quot;Environmental&quot;],
         &quot;Budget cycles, cost pressure, and market conditions are economic factors constraining what the organization can build or buy.&quot;],
        [&quot;Users now expecting consumer-grade, self-service experiences from corporate IT is which PESTLE factor?&quot;,
         [&quot;Social&quot;,
          &quot;Technological&quot;,
          &quot;Economic&quot;,
          &quot;Political&quot;],
         &quot;Changing expectations, demographics, and workforce trends are social factors. They redefine what &#x27;good service&#x27; means.&quot;],
        [&quot;The four dimensions apply to:&quot;,
         [&quot;The entire SVS and every product and service&quot;,
          &quot;Only the service value chain&quot;,
          &quot;Only new services under design&quot;,
          &quot;Only the practices an organization has adopted&quot;],
         &quot;The four dimensions are perspectives on EVERYTHING in the SVS: every practice, every service, every component.&quot;],
        [&quot;Screening and security-vetting of new staff belongs primarily to which dimension?&quot;,
         [&quot;Organizations and people&quot;,
          &quot;Information and technology&quot;,
          &quot;Partners and suppliers&quot;,
          &quot;Value streams and processes&quot;],
         &quot;Staffing, competencies, and workforce concerns (including vetting) are the people dimension, even when done for security reasons.&quot;],
        [&quot;Coordinating several suppliers so the consumer experiences one seamless service (SIAM) belongs to which dimension?&quot;,
         [&quot;Partners and suppliers&quot;,
          &quot;Value streams and processes&quot;,
          &quot;Organizations and people&quot;,
          &quot;Information and technology&quot;],
         &quot;Service integration and management is the flagship concern of the partners and suppliers dimension.&quot;],
        [&quot;Deciding how information is exchanged between systems and protected in transit belongs to which dimension?&quot;,
         [&quot;Information and technology&quot;,
          &quot;Partners and suppliers&quot;,
          &quot;Value streams and processes&quot;,
          &quot;Organizations and people&quot;],
         &quot;How information is created, stored, exchanged, and protected is explicitly part of the information and technology dimension.&quot;],
        [&quot;A value stream is defined as:&quot;,
         [&quot;A series of steps an organization uses to create and deliver products and services to consumers&quot;,
          &quot;A set of interrelated activities that transform inputs into outputs&quot;,
          &quot;The financial flow from consumer to provider&quot;,
          &quot;The sequence of approvals in change enablement&quot;],
         &quot;That is the value stream definition. &#x27;Activities transforming inputs into outputs&#x27; defines a process, the sibling concept in the same dimension.&quot;],
        [&quot;A process is defined as:&quot;,
         [&quot;A set of interrelated or interacting activities that transform inputs into outputs&quot;,
          &quot;A series of steps that create and deliver products and services&quot;,
          &quot;A set of organizational resources designed for performing work&quot;,
          &quot;A documented procedure with an owner&quot;],
         &quot;Inputs → activities → outputs is the process definition. The &#x27;series of steps to deliver value&#x27; is a value stream; &#x27;organizational resources for work&#x27; is a practice.&quot;],
        [&quot;External PESTLE factors can be controlled by a well-governed organization.&quot;,
         [&quot;False: they influence the organization but are largely outside its control&quot;,
          &quot;True: governance exists precisely for this&quot;,
          &quot;True, but only for the technological factor&quot;,
          &quot;False, except for legal factors, which can be negotiated&quot;],
         &quot;PESTLE factors are the environment the organization operates in; you scan and adapt to them, you do not control them.&quot;],

        &#x2F;&#x2F; --- SVS &amp; governance ---
        [&quot;The purpose of the Service Value System is to:&quot;,
         [&quot;Ensure the organization continually co-creates value with all stakeholders through the use and management of products and services&quot;,
          &quot;Define the organizational chart of the IT department&quot;,
          &quot;Guarantee that all 34 practices are implemented&quot;,
          &quot;Replace project management frameworks&quot;],
         &quot;The SVS describes how all the components and activities of the organization work together to enable value creation.&quot;],
        [&quot;The inputs to the SVS are:&quot;,
         [&quot;Opportunity and demand&quot;,
          &quot;Incidents and requests&quot;,
          &quot;Budget and headcount&quot;,
          &quot;Utility and warranty&quot;],
         &quot;Opportunity (potential to add value) and demand (need for products and services) enter; value comes out.&quot;],
        [&quot;The output of the SVS is:&quot;,
         [&quot;Value for the organization, its customers, and other stakeholders&quot;,
          &quot;Products only&quot;,
          &quot;Completed changes&quot;,
          &quot;Reports for the governing body&quot;],
         &quot;Everything in the SVS exists to convert opportunity and demand into value for stakeholders.&quot;],
        [&quot;Which is the correct list of SVS components?&quot;,
         [&quot;Guiding principles, governance, service value chain, practices, continual improvement&quot;,
          &quot;Guiding principles, four dimensions, PESTLE, practices, value streams&quot;,
          &quot;Governance, processes, functions, roles, metrics&quot;,
          &quot;Plan, engage, design, build, deliver&quot;],
         &quot;Five components: principles, governance, SVC, practices, and continual improvement. The four dimensions are perspectives on the SVS, not components of it.&quot;],
        [&quot;Which of these is NOT a component of the SVS?&quot;,
         [&quot;The four dimensions of service management&quot;,
          &quot;Governance&quot;,
          &quot;Continual improvement&quot;,
          &quot;The service value chain&quot;],
         &quot;The four dimensions apply TO the SVS but are not one of its five components, a favorite exam trap.&quot;],
        [&quot;The three main activities of governance are:&quot;,
         [&quot;Evaluate, direct, and monitor&quot;,
          &quot;Plan, do, check&quot;,
          &quot;Design, transition, operate&quot;,
          &quot;Identify, protect, respond&quot;],
         &quot;Governance evaluates the organization, directs strategy and policy, and monitors performance and compliance.&quot;],
        [&quot;Governance in the SVS is the responsibility of:&quot;,
         [&quot;The governing body of the organization&quot;,
          &quot;The service desk manager&quot;,
          &quot;Every individual practitioner equally&quot;,
          &quot;The external auditor&quot;],
         &quot;A governing body (board, executive team) is accountable for governance, even though its effects cascade through all activities.&quot;],
        [&quot;The difference between opportunity and demand is:&quot;,
         [&quot;Opportunity is the potential to add value; demand is the need or desire for products and services&quot;,
          &quot;Opportunity comes from customers; demand comes from regulators&quot;,
          &quot;Opportunity is internal; demand is always external&quot;,
          &quot;There is no difference in ITIL 4&quot;],
         &quot;Both are SVS inputs: opportunity is what the organization COULD do to add value; demand is what consumers actually need or want.&quot;],
        [&quot;A practice is defined as:&quot;,
         [&quot;A set of organizational resources designed for performing work or accomplishing an objective&quot;,
          &quot;A sequence of activities with defined inputs and outputs&quot;,
          &quot;A documented policy approved by governance&quot;,
          &quot;A team responsible for one process&quot;],
         &quot;Practices span all four dimensions (people, information, partners, and processes), which is why v4 replaced v3&#x27;s narrower &#x27;processes&#x27; with &#x27;practices&#x27;.&quot;],
        [&quot;One key purpose of the SVS structure is to combat:&quot;,
         [&quot;Organizational silos&quot;,
          &quot;Cloud adoption&quot;,
          &quot;Outsourcing&quot;,
          &quot;Documentation overhead&quot;],
         &quot;The SVS enables flexible combinations of activities and practices, explicitly designed to counter siloed ways of working.&quot;],
        [&quot;Where do the guiding principles apply within the SVS?&quot;,
         [&quot;To every component and activity, universally&quot;,
          &quot;Only to the service value chain&quot;,
          &quot;Only during improvement initiatives&quot;,
          &quot;Only where governance delegates them&quot;],
         &quot;The principles are the outermost layer of the SVS precisely because nothing escapes them.&quot;],
        [&quot;Continual improvement in the SVS happens:&quot;,
         [&quot;At every level: the whole SVS, the practices, and individual services&quot;,
          &quot;Once a year, during planning&quot;,
          &quot;Only within the Improve activity of the SVC&quot;,
          &quot;Only when a dedicated improvement team exists&quot;],
         &quot;Improvement is embedded everywhere: the SVS component, the SVC activity, and the practice are three views of the same always-on concern.&quot;],
        [&quot;The central element of the SVS, through which all value streams flow, is:&quot;,
         [&quot;The service value chain&quot;,
          &quot;Governance&quot;,
          &quot;The service desk&quot;,
          &quot;The continual improvement register&quot;],
         &quot;The SVC is the operating model at the core of the SVS; every value stream is a path through its six activities.&quot;],
        [&quot;Governance &#x27;monitoring&#x27; refers to monitoring:&quot;,
         [&quot;The performance of the organization and its practices against policy and strategy&quot;,
          &quot;Servers and network devices&quot;,
          &quot;Employee working hours&quot;,
          &quot;Only financial indicators&quot;],
         &quot;Governance monitors organizational performance and adherence. Infrastructure monitoring belongs to the monitoring and event management practice.&quot;],
        [&quot;Demand, as an SVS input, is BEST described as:&quot;,
         [&quot;The need or desire for products and services among internal and external consumers&quot;,
          &quot;The number of tickets logged per month&quot;,
          &quot;Market pressure from competitors&quot;,
          &quot;The backlog of the development team&quot;],
         &quot;Demand is consumer need or desire. Tickets are just one visible symptom of it.&quot;],
        [&quot;An organization wants every part of the SVS to keep getting better. Which component makes this systematic?&quot;,
         [&quot;Continual improvement, supported by the continual improvement register&quot;,
          &quot;Governance, through yearly audits&quot;,
          &quot;The guiding principles alone&quot;,
          &quot;The change advisory board&quot;],
         &quot;Continual improvement is the SVS component (and practice) that makes improvement systematic rather than accidental, with the CIR as its tool.&quot;],

        &#x2F;&#x2F; --- Service value chain ---
        [&quot;Which is the correct list of the six SVC activities?&quot;,
         [&quot;Plan; improve; engage; design &amp; transition; obtain&#x2F;build; deliver &amp; support&quot;,
          &quot;Plan; do; check; act; measure; report&quot;,
          &quot;Strategy; design; transition; operation; improvement; retirement&quot;,
          &quot;Engage; build; test; release; operate; retire&quot;],
         &quot;&#x27;Strategy, design, transition, operation, improvement&#x27; is the v3 lifecycle, a deliberate distractor. The six v4 activities are the first list.&quot;],
        [&quot;The purpose of the PLAN activity is to:&quot;,
         [&quot;Ensure a shared understanding of the vision, current status, and improvement direction for all four dimensions&quot;,
          &quot;Approve individual changes&quot;,
          &quot;Restore service after incidents&quot;,
          &quot;Collect user feedback&quot;],
         &quot;Plan produces the shared direction (strategies, portfolios, architectures, policies) that all other activities consume.&quot;],
        [&quot;The purpose of the ENGAGE activity is to:&quot;,
         [&quot;Provide a good understanding of stakeholder needs, transparency, and continual engagement with all stakeholders&quot;,
          &quot;Build the components a service needs&quot;,
          &quot;Deploy new features to production&quot;,
          &quot;Set the improvement targets&quot;],
         &quot;Engage is the interface with stakeholders: needs come in, transparency goes out, relationships are maintained.&quot;],
        [&quot;The purpose of DESIGN &amp; TRANSITION is to:&quot;,
         [&quot;Ensure products and services continually meet stakeholder expectations for quality, costs, and time-to-market&quot;,
          &quot;Capture demand from users&quot;,
          &quot;Provide strategic direction&quot;,
          &quot;Handle service requests per SLA&quot;],
         &quot;Quality, cost, and time-to-market expectations are the signature phrase of design &amp; transition.&quot;],
        [&quot;The purpose of OBTAIN&#x2F;BUILD is to:&quot;,
         [&quot;Ensure service components are available when and where needed and meet agreed specifications&quot;,
          &quot;Ensure services are supported per agreed specifications&quot;,
          &quot;Ensure continual improvement of products&quot;,
          &quot;Ensure stakeholder transparency&quot;],
         &quot;Obtain&#x2F;build makes components available, whether bought from suppliers or built in-house.&quot;],
        [&quot;The purpose of DELIVER &amp; SUPPORT is to:&quot;,
         [&quot;Ensure services are delivered and supported according to agreed specifications and stakeholder expectations&quot;,
          &quot;Design new services&quot;,
          &quot;Define the service portfolio&quot;,
          &quot;Assess external PESTLE factors&quot;],
         &quot;Deliver &amp; support is day-to-day operations: running services, resolving incidents, fulfilling requests.&quot;],
        [&quot;The purpose of IMPROVE is to:&quot;,
         [&quot;Ensure continual improvement of products, services, and practices across all value chain activities&quot;,
          &quot;Approve emergency changes&quot;,
          &quot;Escalate major incidents&quot;,
          &quot;Manage supplier contracts&quot;],
         &quot;Improve works in parallel with every other activity: everything is subject to improvement, always.&quot;],
        [&quot;A user calls the service desk to report an outage. Which SVC activity captures this interaction?&quot;,
         [&quot;Engage&quot;,
          &quot;Deliver and support&quot;,
          &quot;Obtain&#x2F;build&quot;,
          &quot;Plan&quot;],
         &quot;The contact point with users is Engage; the actual restoration work then happens in deliver &amp; support. The two together form the incident value stream.&quot;],
        [&quot;Diagnosing and fixing the outage to restore service belongs to which SVC activity?&quot;,
         [&quot;Deliver and support&quot;,
          &quot;Engage&quot;,
          &quot;Design and transition&quot;,
          &quot;Improve&quot;],
         &quot;Restoring normal operation is the operational heart of deliver &amp; support.&quot;],
        [&quot;Writing the code and provisioning the servers for a new feature belongs to which activity?&quot;,
         [&quot;Obtain&#x2F;build&quot;,
          &quot;Design and transition&quot;,
          &quot;Plan&quot;,
          &quot;Engage&quot;],
         &quot;Creating or acquiring components is obtain&#x2F;build; deciding how the service should work and moving it to live is design &amp; transition.&quot;],
        [&quot;Making sure the new release meets expectations and moving it into production belongs to which activity?&quot;,
         [&quot;Design and transition&quot;,
          &quot;Obtain&#x2F;build&quot;,
          &quot;Deliver and support&quot;,
          &quot;Plan&quot;],
         &quot;Transitioning changed services into live operation while meeting quality&#x2F;cost&#x2F;time expectations is design &amp; transition.&quot;],
        [&quot;Running a post-incident review and logging lessons learned belongs to which activity?&quot;,
         [&quot;Improve&quot;,
          &quot;Deliver and support&quot;,
          &quot;Engage&quot;,
          &quot;Plan&quot;],
         &quot;Turning operational experience into improvement items is the Improve activity, typically feeding the CIR.&quot;],
        [&quot;Deciding the service portfolio and investment priorities for next year belongs to which activity?&quot;,
         [&quot;Plan&quot;,
          &quot;Engage&quot;,
          &quot;Design and transition&quot;,
          &quot;Obtain&#x2F;build&quot;],
         &quot;Portfolio decisions, strategy, and architecture set direction: that is Plan.&quot;],
        [&quot;A value stream is:&quot;,
         [&quot;A specific combination of value chain activities and practices designed for a particular scenario&quot;,
          &quot;Another name for the service value chain itself&quot;,
          &quot;The list of all 34 practices in priority order&quot;,
          &quot;The financial reporting line for a service&quot;],
         &quot;The SVC is the generic model; a value stream is a concrete path through it, e.g. &#x27;resolve a user incident&#x27; or &#x27;launch a new feature&#x27;.&quot;],
        [&quot;Is the service value chain a linear sequence?&quot;,
         [&quot;No: activities are combined in different orders with feedback loops, depending on the value stream&quot;,
          &quot;Yes: each activity must complete before the next starts&quot;,
          &quot;Yes, but only for major changes&quot;,
          &quot;No, because only three activities are mandatory&quot;],
         &quot;The SVC is explicitly non-linear: an incident stream and a new-service stream activate different combinations of the same six activities.&quot;],
        [&quot;To improve performance, value streams should be:&quot;,
         [&quot;Mapped, analyzed for waste, and continually optimized&quot;,
          &quot;Kept confidential to prevent gaming&quot;,
          &quot;Redesigned from scratch each year&quot;,
          &quot;Standardized to always use all six activities&quot;],
         &quot;Value stream mapping and waste elimination (a Lean inheritance) is how organizations find bottlenecks and non-value steps.&quot;],
        [&quot;Which activity ensures the organization has a shared understanding of its current status before committing to a direction?&quot;,
         [&quot;Plan&quot;,
          &quot;Improve&quot;,
          &quot;Engage&quot;,
          &quot;Deliver and support&quot;],
         &quot;Shared understanding of vision AND current status is Plan&#x27;s defining purpose.&quot;],
        [&quot;Which activity is the primary channel for maintaining transparency and good relationships with stakeholders?&quot;,
         [&quot;Engage&quot;,
          &quot;Plan&quot;,
          &quot;Design and transition&quot;,
          &quot;Obtain&#x2F;build&quot;],
         &quot;Engage owns the relationship surface: understanding needs, transparency, and continual stakeholder engagement.&quot;],

        &#x2F;&#x2F; --- Practices in general ---
        [&quot;How are the 34 practices distributed across categories?&quot;,
         [&quot;14 general management, 17 service management, 3 technical management&quot;,
          &quot;17 general management, 14 service management, 3 technical management&quot;,
          &quot;10 general, 20 service, 4 technical&quot;,
          &quot;14 general, 14 service, 6 technical&quot;],
         &quot;14 + 17 + 3 = 34. The swap of 14 and 17 is the most common wrong answer.&quot;],
        [&quot;Continual improvement belongs to which practice category?&quot;,
         [&quot;General management practices&quot;,
          &quot;Service management practices&quot;,
          &quot;Technical management practices&quot;,
          &quot;It is not a practice, only a principle&quot;],
         &quot;Continual improvement is one of the 14 general management practices, adapted from general business management. It is ALSO a principle-like SVS component, which is the trap.&quot;],
        [&quot;Incident management belongs to which practice category?&quot;,
         [&quot;Service management practices&quot;,
          &quot;General management practices&quot;,
          &quot;Technical management practices&quot;,
          &quot;Governance practices&quot;],
         &quot;Incident, problem, change enablement, service desk, SLM: the operational core all sits in the 17 service management practices.&quot;],
        [&quot;Deployment management belongs to which practice category?&quot;,
         [&quot;Technical management practices&quot;,
          &quot;Service management practices&quot;,
          &quot;General management practices&quot;,
          &quot;It is an SVC activity, not a practice&quot;],
         &quot;The three technical management practices: deployment management, infrastructure &amp; platform management, software development &amp; management.&quot;],
        [&quot;Why does ITIL 4 speak of &#x27;practices&#x27; instead of v3&#x27;s &#x27;processes&#x27;?&quot;,
         [&quot;A practice includes resources from all four dimensions (people, information, partners, workflows), not just activity steps&quot;,
          &quot;The word &#x27;process&#x27; is trademarked&quot;,
          &quot;Practices are optional while processes were mandatory&quot;,
          &quot;Processes only applied to technical teams&quot;],
         &quot;A process is just the workflow; a practice is the whole capability: skills, tools, suppliers, and workflows together.&quot;],
        [&quot;The purpose of monitoring and event management is to:&quot;,
         [&quot;Systematically observe services and components, and record and report selected changes of state&quot;,
          &quot;Restore service after unplanned interruptions&quot;,
          &quot;Authorize infrastructure changes&quot;,
          &quot;Maximize the number of successful releases&quot;],
         &quot;Observing and recording changes of state (events) is this practice&#x27;s job. It feeds incident management but is distinct from it.&quot;],
        [&quot;An EVENT is defined as:&quot;,
         [&quot;Any change of state that has significance for the management of a service or configuration item&quot;,
          &quot;Any unplanned interruption to a service&quot;,
          &quot;A scheduled maintenance window&quot;,
          &quot;A meeting of the change advisory board&quot;],
         &quot;Events are significant state changes: many are informational and never become incidents. The &#x27;unplanned interruption&#x27; is an incident.&quot;],
        [&quot;The purpose of release management is to:&quot;,
         [&quot;Make new and changed services and features available for use&quot;,
          &quot;Move components to live environments&quot;,
          &quot;Protect the organization&#x27;s information&quot;,
          &quot;Record and report changes of state&quot;],
         &quot;Release = available for USE. Moving components to environments is deployment management. The two are separated in ITIL 4.&quot;],
        [&quot;The difference between deployment and release is:&quot;,
         [&quot;Deployment moves components into environments; release makes functionality available to users&quot;,
          &quot;They are synonyms in ITIL 4&quot;,
          &quot;Deployment is manual, release is automated&quot;,
          &quot;Release happens before deployment&quot;],
         &quot;You can deploy code to production dark and release it later via a feature flag. ITIL 4&#x27;s split mirrors modern delivery.&quot;],
        [&quot;The purpose of service configuration management is to:&quot;,
         [&quot;Ensure accurate and reliable information about the configuration of services and their CIs is available when and where needed&quot;,
          &quot;Manage the financial value of all IT assets&quot;,
          &quot;Configure new employee laptops&quot;,
          &quot;Negotiate configuration baselines with suppliers&quot;],
         &quot;Accurate CI information, including relationships between CIs, is the heart of this practice. Financial lifecycle is IT asset management.&quot;],
        [&quot;A configuration item (CI) is:&quot;,
         [&quot;Any component that needs to be managed in order to deliver an IT service&quot;,
          &quot;Any component with a purchase price above a threshold&quot;,
          &quot;Only hardware devices&quot;,
          &quot;Any item listed in the service catalog&quot;],
         &quot;CIs are managed for service delivery: servers, software, documentation, even SLAs can be CIs.&quot;],
        [&quot;The purpose of IT asset management is to:&quot;,
         [&quot;Plan and manage the full lifecycle of all IT assets to maximize value, control costs, and manage risks&quot;,
          &quot;Keep the CMDB relationships accurate&quot;,
          &quot;Monitor asset performance in real time&quot;,
          &quot;Approve asset-related changes&quot;],
         &quot;Full lifecycle + value&#x2F;cost&#x2F;risk (and licensing, disposal decisions) is asset management; the CMDB relationship accuracy is configuration management.&quot;],
        [&quot;An IT asset is defined as:&quot;,
         [&quot;Any financially valuable component that can contribute to the delivery of an IT product or service&quot;,
          &quot;Any component that needs managing to deliver a service&quot;,
          &quot;Only components owned outright, never leased&quot;,
          &quot;Any device with a network address&quot;],
         &quot;The keyword is FINANCIALLY VALUABLE: that is what distinguishes an asset from a mere CI.&quot;],
        [&quot;The purpose of information security management is to protect information by ensuring:&quot;,
         [&quot;Confidentiality, integrity, and availability, plus authentication and non-repudiation&quot;,
          &quot;Encryption of all data at all times&quot;,
          &quot;That only managers can access sensitive data&quot;,
          &quot;Annual penetration testing&quot;],
         &quot;The CIA triad (plus authentication and non-repudiation) defines the protection goals; specific controls like encryption are means, not the purpose.&quot;],
        [&quot;The purpose of relationship management is to:&quot;,
         [&quot;Establish and nurture links between the organization and its stakeholders at strategic and tactical levels&quot;,
          &quot;Manage the joint activities of provider and consumer in a service relationship&quot;,
          &quot;Handle complaints at the service desk&quot;,
          &quot;Maintain the supplier contract database&quot;],
         &quot;Relationship management is a practice INSIDE the provider. Service relationship management (the joint activity) is a different concept; that is the trap.&quot;],
        [&quot;The purpose of supplier management is to:&quot;,
         [&quot;Ensure suppliers and their performance are managed appropriately to support seamless, quality products and services&quot;,
          &quot;Always select the cheapest supplier&quot;,
          &quot;Replace internal teams with vendors&quot;,
          &quot;Audit supplier finances annually&quot;],
         &quot;Supplier management covers sourcing strategy, contracts, and performance, aimed at seamless integration, not merely lowest cost.&quot;],
        [&quot;Which practice provides the single point of contact between the provider and its users?&quot;,
         [&quot;Service desk&quot;,
          &quot;Relationship management&quot;,
          &quot;Service level management&quot;,
          &quot;Incident management&quot;],
         &quot;The service desk is the SPOC, capturing demand for incident resolution and service requests.&quot;],
        [&quot;The purpose of service level management is to:&quot;,
         [&quot;Set clear business-based targets for service levels and ensure delivery is properly assessed, monitored, and reported&quot;,
          &quot;Resolve incidents within their SLA targets&quot;,
          &quot;Negotiate contracts with suppliers&quot;,
          &quot;Publish the service catalog&quot;],
         &quot;SLM sets and manages the targets; resolving within them is incident management&#x27;s execution. &#x27;Business-based&#x27; is the key qualifier.&quot;],
        [&quot;&#x27;Adopt and adapt&#x27; means an organization should:&quot;,
         [&quot;Implement only the practices that address its needs, and tailor them to its context&quot;,
          &quot;Adopt all 34 practices before adapting any&quot;,
          &quot;Copy the reference processes without modification&quot;,
          &quot;Rotate practices annually to stay current&quot;],
         &quot;ITIL 4 is a toolbox, not a checklist: pick what solves your problems, shape it to fit, leave the rest.&quot;],
        [&quot;Which practice keeps accurate information about the FINANCIAL value and lifecycle of components?&quot;,
         [&quot;IT asset management&quot;,
          &quot;Service configuration management&quot;,
          &quot;Service catalog management&quot;,
          &quot;Monitoring and event management&quot;],
         &quot;Money and lifecycle → asset management. Technical relationships between components → configuration management. Keeping these two straight is worth easy points.&quot;],

        &#x2F;&#x2F; --- Incident management &amp; service desk ---
        [&quot;An incident is defined as:&quot;,
         [&quot;An unplanned interruption to a service, or a reduction in the quality of a service&quot;,
          &quot;The cause, or potential cause, of one or more service interruptions&quot;,
          &quot;Any change of state significant for service management&quot;,
          &quot;A user request for something new&quot;],
         &quot;Unplanned interruption OR quality reduction = incident. The &#x27;cause&#x27; is a problem; the &#x27;change of state&#x27; is an event; the request is a service request.&quot;],
        [&quot;The purpose of incident management is to:&quot;,
         [&quot;Minimize the negative impact of incidents by restoring normal service operation as quickly as possible&quot;,
          &quot;Identify the root causes of service failures&quot;,
          &quot;Prevent all incidents from occurring&quot;,
          &quot;Authorize fixes before they are applied&quot;],
         &quot;Restore fast, minimize impact. Root causes belong to problem management; prevention of ALL incidents is not a realistic purpose.&quot;],
        [&quot;Incident priority is determined by:&quot;,
         [&quot;Impact and urgency&quot;,
          &quot;The seniority of the person reporting&quot;,
          &quot;The order in which incidents arrive&quot;,
          &quot;The cost of the affected hardware&quot;],
         &quot;Impact (extent of the effect) × urgency (how quickly it matters) = priority. First-come-first-served is explicitly what prioritization replaces.&quot;],
        [&quot;Target incident resolution times are:&quot;,
         [&quot;Agreed, documented, and communicated, typically in SLAs&quot;,
          &quot;Set individually by each technician&quot;,
          &quot;Identical for all incidents&quot;,
          &quot;Optional for internal services&quot;],
         &quot;Targets must be agreed and visible so expectations are managed. One flat target for everything defeats prioritization.&quot;],
        [&quot;How should incidents be recorded?&quot;,
         [&quot;Every incident logged and time-stamped, with quality information for diagnosis&quot;,
          &quot;Only P1 and P2 incidents deserve a record&quot;,
          &quot;Verbally, to keep the process lightweight&quot;,
          &quot;Only if the user insists on a ticket number&quot;],
         &quot;All incidents are logged and managed to target times; unlogged incidents are invisible to trends, problems, and improvement.&quot;],
        [&quot;Major incidents should be handled:&quot;,
         [&quot;Through a separate, pre-defined procedure with clear roles&quot;,
          &quot;Exactly like normal incidents but faster&quot;,
          &quot;Directly by the CAB&quot;,
          &quot;Only after a problem record is created&quot;],
         &quot;Low-impact incidents must not consume major-incident machinery, and vice versa, hence a distinct major-incident procedure, defined BEFORE it is needed.&quot;],
        [&quot;Passing an incident to a specialist team with deeper technical knowledge is:&quot;,
         [&quot;Functional escalation&quot;,
          &quot;Hierarchic escalation&quot;,
          &quot;A workaround&quot;,
          &quot;Swarming&quot;],
         &quot;Escalation for EXPERTISE is functional; escalation for AUTHORITY or visibility is hierarchic.&quot;],
        [&quot;Notifying senior management because an SLA breach is imminent is:&quot;,
         [&quot;Hierarchic escalation&quot;,
          &quot;Functional escalation&quot;,
          &quot;A known error&quot;,
          &quot;An emergency change&quot;],
         &quot;Involving management when impact or SLA risk warrants it is hierarchic escalation: it adds authority, not technical skill.&quot;],
        [&quot;&#x27;Swarming&#x27; in incident management means:&quot;,
         [&quot;Many stakeholders work together initially until it is clear who is best placed to continue&quot;,
          &quot;Assigning the incident to every team simultaneously and permanently&quot;,
          &quot;Users voting on which incident gets fixed first&quot;,
          &quot;Automatically reopening incidents that recur&quot;],
         &quot;Swarming replaces ping-pong escalation with an initial burst of collective analysis, then hands the incident to the best-placed party.&quot;],
        [&quot;Frequent, low-impact incidents with a documented fix are IDEALLY resolved by:&quot;,
         [&quot;Self-help or automated remediation&quot;,
          &quot;The major incident team&quot;,
          &quot;Hierarchic escalation&quot;,
          &quot;The change advisory board&quot;],
         &quot;Known, repeatable resolutions are prime candidates for self-service and automation, freeing humans for what needs judgment.&quot;],
        [&quot;The difference between an event and an incident is:&quot;,
         [&quot;Every incident implies something significant happened, but many events are informational and affect nothing&quot;,
          &quot;Events are always more serious than incidents&quot;,
          &quot;Incidents are detected by tools, events by users&quot;,
          &quot;There is no difference&quot;],
         &quot;An event is any significant change of state: most are routine. Only when service is interrupted or degraded does it become an incident.&quot;],
        [&quot;The difference between an incident and a problem is:&quot;,
         [&quot;The incident is the interruption itself; the problem is its cause or potential cause&quot;,
          &quot;Problems are just large incidents&quot;,
          &quot;Incidents are technical, problems are organizational&quot;,
          &quot;A problem is an incident that breached its SLA&quot;],
         &quot;Incident = symptom you restore at 2am; problem = cause you investigate to prevent the next one. Conflating them means fixing the same incident forever.&quot;],
        [&quot;When should an incident be closed?&quot;,
         [&quot;After verifying with the user that service is restored and they agree&quot;,
          &quot;As soon as the technician applies a fix&quot;,
          &quot;When the SLA timer expires&quot;,
          &quot;When the problem record is created&quot;],
         &quot;Restoration is confirmed, not assumed. Closing on &#x27;fix applied&#x27; without verification is how incidents boomerang.&quot;],
        [&quot;Matching new incidents against known errors is made possible mainly by:&quot;,
         [&quot;Good records and an accessible knowledge base&quot;,
          &quot;A bigger service desk team&quot;,
          &quot;Stricter SLAs&quot;,
          &quot;Weekly CAB meetings&quot;],
         &quot;Documented known errors and workarounds turn hours of rediagnosis into minutes of lookup, but only if incidents and problems are recorded well.&quot;],
        [&quot;Which incident is MOST clearly a P1 under a standard impact&#x2F;urgency matrix?&quot;,
         [&quot;The payroll system is down on the day salaries must be processed&quot;,
          &quot;One user&#x27;s second monitor flickers occasionally&quot;,
          &quot;A report has a cosmetic formatting error&quot;,
          &quot;A test environment is slow outside business hours&quot;],
         &quot;Highest impact (business-critical process, many people) + highest urgency (today is the deadline) = P1. The others are P3&#x2F;P4 territory.&quot;],
        [&quot;Urgency measures:&quot;,
         [&quot;How quickly the business needs the incident resolved&quot;,
          &quot;How many users are affected&quot;,
          &quot;How expensive the fix will be&quot;,
          &quot;How angry the loudest stakeholder is&quot;],
         &quot;Urgency is about time sensitivity. Number of users affected is impact, the other axis of the priority matrix.&quot;],
        [&quot;Impact measures:&quot;,
         [&quot;The extent of the effect: how many users, services, or business processes are affected&quot;,
          &quot;The time available before resolution is needed&quot;,
          &quot;The technical difficulty of the fix&quot;,
          &quot;The reputational risk to the IT director&quot;],
         &quot;Impact is breadth of effect; urgency is speed required. Priority combines the two.&quot;],
        [&quot;The purpose of the service desk practice is to:&quot;,
         [&quot;Capture demand for incident resolution and service requests, acting as the single point of contact&quot;,
          &quot;Fix every incident at first contact&quot;,
          &quot;Manage the configuration management database&quot;,
          &quot;Authorize normal changes&quot;],
         &quot;The desk is the entry point and coordinator: it captures, triages, and routes demand; it does not need to fix everything itself.&quot;],
        [&quot;Beyond technical knowledge, effective service desk staff especially need:&quot;,
         [&quot;Empathy, communication skills, and incident analysis skills&quot;,
          &quot;Certifications in every supported product&quot;,
          &quot;Administrative access to all systems&quot;,
          &quot;Sales experience&quot;],
         &quot;The desk owns the human moment of support: understanding, communicating, and prioritizing matter as much as raw technical depth.&quot;],
        [&quot;A &#x27;virtual&#x27; service desk is one where:&quot;,
         [&quot;Agents work from dispersed locations while appearing to users as a single team&quot;,
          &quot;Users only interact with chatbots&quot;,
          &quot;The desk exists only during business hours&quot;,
          &quot;Each department runs its own desk&quot;],
         &quot;Technology lets geographically dispersed agents operate as one desk. The user experience stays unified.&quot;],
        [&quot;When the service desk cannot resolve an incident, it should:&quot;,
         [&quot;Route it to the appropriate support team using defined escalation paths&quot;,
          &quot;Close it and ask the user to call back later&quot;,
          &quot;Automatically declare a major incident&quot;,
          &quot;Convert it into a service request&quot;],
         &quot;The desk coordinates: capture, triage, route, and keep the user informed. Defined routes prevent tickets wandering between teams.&quot;],
        [&quot;An incident becomes a CRISIS when:&quot;,
         [&quot;Its consequences are business-wide and require executive-level involvement&quot;,
          &quot;It breaches its SLA by more than an hour&quot;,
          &quot;More than ten users are affected&quot;,
          &quot;The service desk queue exceeds fifty tickets&quot;],
         &quot;Crisis = organization-level threat needing executive decisions. Knowing who to call should be documented before the crisis, not during it.&quot;],
        [&quot;Which of these is NOT the job of incident management?&quot;,
         [&quot;Eliminating the root cause of recurring incidents&quot;,
          &quot;Restoring service as quickly as possible&quot;,
          &quot;Prioritizing by impact and urgency&quot;,
          &quot;Keeping users informed of status&quot;],
         &quot;Root cause elimination is problem management. Incident management restores; problem management prevents.&quot;],

        &#x2F;&#x2F; --- Problem management ---
        [&quot;A problem is defined as:&quot;,
         [&quot;A cause, or potential cause, of one or more incidents&quot;,
          &quot;Any incident lasting more than four hours&quot;,
          &quot;An incident with no known workaround&quot;,
          &quot;A complaint raised by a customer&quot;],
         &quot;Problems are causes, including POTENTIAL causes identified before any incident occurs (proactive problem management).&quot;],
        [&quot;The purpose of problem management is to:&quot;,
         [&quot;Reduce the likelihood and impact of incidents by identifying actual and potential causes and managing workarounds and known errors&quot;,
          &quot;Restore service as quickly as possible&quot;,
          &quot;Assign blame for major outages&quot;,
          &quot;Authorize permanent fixes&quot;],
         &quot;Likelihood + impact reduction via cause analysis, workarounds, and known errors. Restoration is incident management; authorization is change enablement.&quot;],
        [&quot;A known error is:&quot;,
         [&quot;A problem that has been analyzed but not yet resolved&quot;,
          &quot;An incident that keeps recurring&quot;,
          &quot;A mistake made by a technician&quot;,
          &quot;A bug the vendor refuses to fix&quot;],
         &quot;Analyzed + not yet resolved = known error, typically with a documented workaround. It is a state of knowledge, not a failure.&quot;],
        [&quot;A workaround is:&quot;,
         [&quot;A solution that reduces or eliminates the impact of an incident or problem without resolving the underlying cause&quot;,
          &quot;A permanent fix deployed as an emergency change&quot;,
          &quot;Any fix applied outside business hours&quot;,
          &quot;A way to bypass the change process&quot;],
         &quot;Workarounds treat symptoms so users can work; the problem record stays open until the cause is permanently addressed.&quot;],
        [&quot;The three phases of problem management are:&quot;,
         [&quot;Problem identification, problem control, error control&quot;,
          &quot;Detection, escalation, closure&quot;,
          &quot;Reactive, proactive, predictive&quot;,
          &quot;Analysis, authorization, deployment&quot;],
         &quot;Identification finds problems; problem control analyzes and documents workarounds; error control manages known errors toward permanent resolution.&quot;],
        [&quot;Problem CONTROL includes:&quot;,
         [&quot;Analyzing problems and documenting workarounds and known errors&quot;,
          &quot;Monitoring the change schedule&quot;,
          &quot;Restoring service during a major incident&quot;,
          &quot;Approving the fix budget&quot;],
         &quot;Problem control is the analysis phase: prioritize, investigate, and produce workarounds&#x2F;known-error records.&quot;],
        [&quot;Error CONTROL includes:&quot;,
         [&quot;Managing known errors and reassessing whether a permanent fix is now justified&quot;,
          &quot;Preventing users from making mistakes&quot;,
          &quot;Correcting data-entry errors in the CMDB&quot;,
          &quot;Reviewing failed changes&quot;],
         &quot;Error control periodically re-evaluates known errors (cost of fix vs cost of living with the workaround) and triggers changes when fixing becomes worthwhile.&quot;],
        [&quot;PROACTIVE problem management is triggered by:&quot;,
         [&quot;Trend analysis, risk assessment, or pattern detection, before incidents occur&quot;,
          &quot;A major incident post-mortem&quot;,
          &quot;An SLA breach&quot;,
          &quot;A user complaint&quot;],
         &quot;Proactive mode hunts potential causes before they bite; reactive mode responds to incidents that already happened.&quot;],
        [&quot;How do problem management and incident management interact during an outage?&quot;,
         [&quot;Incident management restores service, possibly using a workaround that problem management documented&quot;,
          &quot;Problem management takes over the incident until root cause is found&quot;,
          &quot;They must not run at the same time&quot;,
          &quot;Incident management waits for root cause analysis before restoring&quot;],
         &quot;They run in parallel with different goals: restore now (incident), prevent recurrence (problem). Waiting for root cause before restoring is the anti-pattern.&quot;],
        [&quot;Problems should be prioritized based on:&quot;,
         [&quot;The risk they pose: frequency and impact of the incidents they cause&quot;,
          &quot;The order in which they were logged&quot;,
          &quot;The seniority of whoever reported them&quot;,
          &quot;Alphabetical order of affected services&quot;],
         &quot;Problem prioritization is risk-based: a cause producing frequent or severe incidents outranks a rare cosmetic one.&quot;],
        [&quot;&#x27;5 whys&#x27; and fishbone diagrams are techniques used mainly in:&quot;,
         [&quot;Root cause analysis within problem management&quot;,
          &quot;SLA negotiation&quot;,
          &quot;Capacity planning&quot;,
          &quot;Service catalog design&quot;],
         &quot;Both are structured RCA tools: 5 whys digs from symptom to systemic cause; fishbone maps contributing factors across categories.&quot;],
        [&quot;When a permanent fix for a known error requires modifying production, problem management must:&quot;,
         [&quot;Raise a change request through change enablement&quot;,
          &quot;Apply the fix directly since the cause is known&quot;,
          &quot;Wait for the next major incident&quot;,
          &quot;Transfer ownership to the service desk&quot;],
         &quot;Knowing the cause does not waive authorization. Permanent fixes ship through change enablement like any other change.&quot;],
        [&quot;After a workaround is documented, the problem record should be:&quot;,
         [&quot;Kept open until the permanent fix is implemented&quot;,
          &quot;Closed immediately&quot;,
          &quot;Converted into an incident&quot;,
          &quot;Deleted once incidents stop&quot;],
         &quot;The workaround manages symptoms; the problem remains a problem until the underlying cause is resolved (or consciously accepted).&quot;],
        [&quot;Which statement about problems and incidents is TRUE?&quot;,
         [&quot;Problems are the causes of incidents, and are managed through a distinct lifecycle&quot;,
          &quot;Every incident must have a matching problem record&quot;,
          &quot;Problems are always detected before incidents&quot;,
          &quot;Incidents and problems share one record type&quot;],
         &quot;Distinct concepts, distinct lifecycles, deliberate linkage. Not every incident warrants a problem investigation. That is a judgment of risk and recurrence.&quot;],

        &#x2F;&#x2F; --- Change enablement ---
        [&quot;The purpose of change enablement is to:&quot;,
         [&quot;Maximize the number of successful changes by ensuring risks are properly assessed, authorizing changes, and managing the change schedule&quot;,
          &quot;Minimize the number of changes deployed&quot;,
          &quot;Ensure all changes are approved by executives&quot;,
          &quot;Document changes after they happen&quot;],
         &quot;The purpose is MAXIMIZING SUCCESSFUL changes: enabling flow with assessed risk, not slowing everything down.&quot;],
        [&quot;A change is defined as:&quot;,
         [&quot;The addition, modification, or removal of anything that could have a direct or indirect effect on services&quot;,
          &quot;Any deployment to production&quot;,
          &quot;Any modification costing more than a set amount&quot;,
          &quot;A new version of the service catalog&quot;],
         &quot;Addition, modification, OR removal, and &#x27;anything that could affect services&#x27;, which is broader than code deployments.&quot;],
        [&quot;A STANDARD change is:&quot;,
         [&quot;A low-risk, well-understood, pre-authorized change with a documented procedure&quot;,
          &quot;Any change deployed during business hours&quot;,
          &quot;A change approved individually by the CAB&quot;,
          &quot;The most common change type in a crisis&quot;],
         &quot;Pre-authorized + low risk + fully documented = standard. It needs no per-instance authorization. That is the whole point.&quot;],
        [&quot;A NORMAL change is:&quot;,
         [&quot;A change that must be scheduled, assessed, and authorized before implementation&quot;,
          &quot;Any change that happens on a normal working day&quot;,
          &quot;A pre-authorized routine change&quot;,
          &quot;A change implemented without a rollback plan&quot;],
         &quot;Normal changes go through assessment and authorization appropriate to their risk, from lightweight peer review up to CAB scrutiny for major ones.&quot;],
        [&quot;An EMERGENCY change:&quot;,
         [&quot;Must be implemented as soon as possible and may defer some documentation or testing, but still requires authorization&quot;,
          &quot;Skips authorization entirely&quot;,
          &quot;Is any change requested by a director&quot;,
          &quot;Must always wait for the next CAB meeting&quot;],
         &quot;Emergency changes are expedited, not exempt: a (possibly smaller, separate) emergency change authority still authorizes them.&quot;],
        [&quot;The change authority is:&quot;,
         [&quot;The person or group who authorizes a change, assigned according to change type and risk&quot;,
          &quot;Always the CIO&quot;,
          &quot;Always the change advisory board&quot;,
          &quot;The engineer implementing the change&quot;],
         &quot;Authority is matched to the change: peer review for low-risk normal changes, CAB or executives for major ones (decentralized where practical).&quot;],
        [&quot;A risky server patch being applied for the first time should be classified as:&quot;,
         [&quot;A normal change&quot;,
          &quot;A standard change&quot;,
          &quot;An emergency change&quot;,
          &quot;Not a change, since patches are routine&quot;],
         &quot;First time + risk = assess and authorize (normal). Only after the procedure is proven and documented can it become a standard change candidate.&quot;],
        [&quot;Applying a critical security patch during an active breach is:&quot;,
         [&quot;An emergency change&quot;,
          &quot;A standard change&quot;,
          &quot;A normal change scheduled for next month&quot;,
          &quot;A service request&quot;],
         &quot;Immediate implementation needed → emergency change, with expedited assessment and its own authority.&quot;],
        [&quot;A routine antivirus definition update with a documented, proven procedure is:&quot;,
         [&quot;A standard change&quot;,
          &quot;A normal change requiring CAB review&quot;,
          &quot;An emergency change&quot;,
          &quot;An incident&quot;],
         &quot;Low risk, well understood, procedure exists → pre-authorized standard change. Sending it to the CAB every time would be process theater.&quot;],
        [&quot;The change schedule is used to:&quot;,
         [&quot;Plan changes, help avoid conflicts, assign resources, and communicate to stakeholders&quot;,
          &quot;Record incidents by date&quot;,
          &quot;Track supplier contract renewals&quot;,
          &quot;Log improvement ideas&quot;],
         &quot;The schedule is both a planning tool (collision avoidance) and a communication tool (who needs to know what is changing, when).&quot;],
        [&quot;The role of the CAB (change advisory board) is to:&quot;,
         [&quot;Advise and support the assessment and authorization of changes that warrant collective review&quot;,
          &quot;Implement all normal changes&quot;,
          &quot;Replace the change authority in all cases&quot;,
          &quot;Approve service requests&quot;],
         &quot;The CAB reviews significant changes to catch problems before they become incidents. It advises the change authority rather than executing changes.&quot;],
        [&quot;For emergency changes, the change authority:&quot;,
         [&quot;May be a separate, smaller group able to convene and decide quickly&quot;,
          &quot;Is always the full CAB&quot;,
          &quot;Is not needed&quot;,
          &quot;Must include the end users&quot;],
         &quot;Speed requires a compact, pre-identified emergency authority: full CAB ceremony would defeat the purpose.&quot;],
        [&quot;Once a change type is defined as standard, each instance:&quot;,
         [&quot;Can be implemented without further individual authorization&quot;,
          &quot;Still requires CAB review&quot;,
          &quot;Must be logged as an incident first&quot;,
          &quot;Requires the sponsor&#x27;s signature&quot;],
         &quot;Pre-authorization is granted once, for the type; instances follow the documented procedure. (They are still recorded and traceable.)&quot;],
        [&quot;When a change fails, the FIRST reference for recovery should be:&quot;,
         [&quot;The remediation&#x2F;rollback plan prepared before implementation&quot;,
          &quot;A brainstorm of the implementation team&quot;,
          &quot;The next CAB agenda&quot;,
          &quot;The supplier&#x27;s escalation hotline&quot;],
         &quot;A tested rollback plan is part of a proper change dossier. Improvising recovery at 3am is what the plan exists to prevent.&quot;],
        [&quot;Change enablement must balance:&quot;,
         [&quot;The need to realize beneficial change against the need to protect services from adverse impact&quot;,
          &quot;The interests of developers against those of operations&quot;,
          &quot;Speed of deployment against documentation volume&quot;,
          &quot;Standard changes against emergency changes&quot;],
         &quot;That tension (enable change AND protect stability) is the practice&#x27;s entire reason for existing.&quot;],
        [&quot;Where should change authority ideally be placed for low-risk changes?&quot;,
         [&quot;As close to the work as practical, e.g. peer review, to enable flow&quot;,
          &quot;At the highest executive level for accountability&quot;,
          &quot;With an external auditor&quot;,
          &quot;With the service desk&quot;],
         &quot;ITIL 4 favors decentralized authorization where risk allows: high-velocity delivery depends on it. Escalate authority only with risk.&quot;],

        &#x2F;&#x2F; --- Service request management &amp; SLM ---
        [&quot;A service request is:&quot;,
         [&quot;A pre-defined, pre-agreed request from a user that is a normal part of service delivery&quot;,
          &quot;Any ticket a user opens&quot;,
          &quot;A report that something is broken&quot;,
          &quot;A request to modify production infrastructure in a novel way&quot;],
         &quot;Pre-defined and pre-agreed is the essence: nothing is broken (incident), nothing novel is changing (change enablement).&quot;],
        [&quot;The purpose of service request management is to:&quot;,
         [&quot;Support agreed service quality by handling all pre-defined, user-initiated service requests effectively and in a user-friendly manner&quot;,
          &quot;Reduce the number of requests users submit&quot;,
          &quot;Authorize every request through the CAB&quot;,
          &quot;Convert requests into incidents for tracking&quot;],
         &quot;Effective + user-friendly handling of predefined requests, per agreed fulfilment expectations.&quot;],
        [&quot;A user asks for a second monitor. Another user reports their monitor no longer turns on. These are respectively:&quot;,
         [&quot;A service request and an incident&quot;,
          &quot;Two incidents&quot;,
          &quot;Two service requests&quot;,
          &quot;An incident and a change&quot;],
         &quot;Wanting something new&#x2F;predefined = request. Something that worked and now does not = incident. Routing these correctly is daily bread.&quot;],
        [&quot;To improve fulfilment, service request workflows should be:&quot;,
         [&quot;Standardized as much as possible, then automated where sensible&quot;,
          &quot;Handled case-by-case for personal touch&quot;,
          &quot;Reviewed individually by the CAB&quot;,
          &quot;Outsourced by default&quot;],
         &quot;Requests are the framework&#x27;s biggest automation opportunity: standardize the workflow first, then automate (optimize before automate).&quot;],
        [&quot;Some service requests, such as expensive equipment, may require:&quot;,
         [&quot;Additional approvals (for example financial or information-security approval) built into the workflow&quot;,
          &quot;Reclassification as emergency changes&quot;,
          &quot;Rejection, since requests must be free&quot;,
          &quot;A problem record&quot;],
         &quot;Pre-agreed does not mean approval-free: the approval steps are simply predefined parts of the fulfilment workflow.&quot;],
        [&quot;The purpose of service level management is to:&quot;,
         [&quot;Set clear business-based targets for service levels, and ensure delivery is properly assessed, monitored, and reported against them&quot;,
          &quot;Punish teams that breach SLAs&quot;,
          &quot;Write the service desk scripts&quot;,
          &quot;Set prices for service offerings&quot;],
         &quot;Targets must be business-based and the full loop matters: set, assess, monitor, report, review.&quot;],
        [&quot;An SLA is:&quot;,
         [&quot;A documented agreement between a service provider and a customer identifying the services required and their expected level&quot;,
          &quot;A legally mandated uptime of 99.9%&quot;,
          &quot;An internal target the provider keeps private&quot;,
          &quot;The list of penalties for outages&quot;],
         &quot;SLA = documented agreement between provider and customer about services and expected levels. Penalties and specific numbers are optional contents, not the definition.&quot;],
        [&quot;The &#x27;watermelon SLA&#x27; effect describes:&quot;,
         [&quot;Metrics that are green on the outside while the actual user experience is red inside&quot;,
          &quot;SLAs that grow larger every renewal cycle&quot;,
          &quot;Seasonal variations in service demand&quot;,
          &quot;SLAs with too many stakeholders&quot;],
         &quot;All dashboard targets met, users still miserable: the sign that SLAs measure activity, not experience or outcomes.&quot;],
        [&quot;Good service level metrics should:&quot;,
         [&quot;Relate to defined services and reflect the customer&#x27;s intended outcomes, not just single-system measures&quot;,
          &quot;Focus on the metrics easiest to collect&quot;,
          &quot;Track only technical component uptime&quot;,
          &quot;Change every month to stay fresh&quot;],
         &quot;Bundles of metrics tied to outcomes beat isolated component stats: 99.9% server uptime means little if the end-to-end journey fails.&quot;],
        [&quot;An XLA differs from an SLA in that it measures:&quot;,
         [&quot;The user&#x27;s actual experience and satisfaction rather than technical compliance&quot;,
          &quot;Experience of the provider&#x27;s own staff only&quot;,
          &quot;Exactly the same things with a newer name&quot;,
          &quot;Financial performance of the service&quot;],
         &quot;XLAs target how the service FELT, closing the watermelon gap between met targets and unhappy users.&quot;],
        [&quot;Which is a core activity of service level management?&quot;,
         [&quot;Collecting customer feedback and holding service review meetings&quot;,
          &quot;Deploying releases to production&quot;,
          &quot;Diagnosing incidents&quot;,
          &quot;Maintaining the CMDB&quot;],
         &quot;SLM engages customers: feedback, reviews, and renegotiation keep targets aligned with business needs.&quot;],
        [&quot;Who negotiates and agrees SLAs with customers?&quot;,
         [&quot;Service level management&quot;,
          &quot;The service desk&quot;,
          &quot;Incident management&quot;,
          &quot;The emergency change authority&quot;],
         &quot;The desk operates within SLAs; SLM creates and maintains them with the customer.&quot;],

        &#x2F;&#x2F; --- Continual improvement (model &amp; practice) ---
        [&quot;The first step of the continual improvement model is:&quot;,
         [&quot;What is the vision?&quot;,
          &quot;Where are we now?&quot;,
          &quot;Take action&quot;,
          &quot;Perform a gap analysis&quot;],
         &quot;The model starts by anchoring to business vision and objectives: improvements without a vision drift.&quot;],
        [&quot;In the continual improvement model, the step immediately after &#x27;Where are we now?&#x27; is:&quot;,
         [&quot;Where do we want to be?&quot;,
          &quot;Take action&quot;,
          &quot;Did we get there?&quot;,
          &quot;How do we keep the momentum going?&quot;],
         &quot;Baseline first, then target: current state → desired state → plan → action → evaluation → sustain.&quot;],
        [&quot;The purpose of a baseline assessment (&#x27;Where are we now?&#x27;) is to:&quot;,
         [&quot;Establish the measured starting point against which improvement will be proven&quot;,
          &quot;Identify who caused the current situation&quot;,
          &quot;Satisfy audit documentation requirements&quot;,
          &quot;Decide the budget for tooling&quot;],
         &quot;Without a measured baseline you cannot demonstrate that anything improved. Objective data beats assumptions.&quot;],
        [&quot;&#x27;Did we get there?&#x27; is answered by:&quot;,
         [&quot;Evaluating metrics and KPIs against the success criteria defined earlier&quot;,
          &quot;A show of hands in the retro&quot;,
          &quot;Checking whether the budget was spent&quot;,
          &quot;Confirming all actions were completed&quot;],
         &quot;Completion of actions is not success; movement of the agreed measures is. Criteria were set at &#x27;Where do we want to be?&#x27; precisely for this moment.&quot;],
        [&quot;&#x27;How do we keep the momentum going?&#x27; involves:&quot;,
         [&quot;Embedding the change, celebrating success, and starting the cycle again&quot;,
          &quot;Freezing the process to protect gains&quot;,
          &quot;Disbanding the improvement team&quot;,
          &quot;Archiving the CIR&quot;],
         &quot;Improvements revert silently unless embedded (docs, training, habits). Then the loop restarts with a new vision.&quot;],
        [&quot;The continual improvement register (CIR) is:&quot;,
         [&quot;A structured record of improvement ideas, their status, and prioritization&quot;,
          &quot;The list of all changes deployed this year&quot;,
          &quot;The archive of resolved incidents&quot;,
          &quot;A financial ledger for the improvement budget&quot;],
         &quot;The CIR is the improvement backlog: ideas captured, prioritized, tracked to outcome. An organization may keep several CIRs.&quot;],
        [&quot;Who is responsible for continual improvement?&quot;,
         [&quot;Everyone in the organization, as part of their daily work&quot;,
          &quot;Only the dedicated improvement team&quot;,
          &quot;Only senior management&quot;,
          &quot;Only the process owners&quot;],
         &quot;A dedicated team may coordinate, but the responsibility is universal: improvement is part of everyone&#x27;s job, not a department.&quot;],
        [&quot;The continual improvement PRACTICE corresponds to which SVC activity?&quot;,
         [&quot;Improve, though the practice supports all activities&quot;,
          &quot;Plan&quot;,
          &quot;Engage&quot;,
          &quot;Deliver and support&quot;],
         &quot;The Improve activity is where the practice most directly operates, but like the principle, it touches everything.&quot;],
        [&quot;What should happen to improvement ideas that are logged in the CIR?&quot;,
         [&quot;They are prioritized and the most valuable ones acted upon; not all will be executed&quot;,
          &quot;All of them must be implemented eventually&quot;,
          &quot;They expire after 90 days automatically&quot;,
          &quot;They require CAB approval to remain listed&quot;],
         &quot;The CIR is a prioritized funnel, not a promise: value and effort determine which ideas proceed.&quot;],
        [&quot;In the step &#x27;How do we get there?&#x27;, ITIL recommends:&quot;,
         [&quot;Designing the improvement as iterations, especially when the full path is unclear&quot;,
          &quot;Committing to a fixed three-year plan&quot;,
          &quot;Starting work without a plan to save time&quot;,
          &quot;Outsourcing the plan to consultants&quot;],
         &quot;When destination or route is fuzzy, plan the first increments and refine with feedback, the iterative principle applied to improvement itself.&quot;],

        &#x2F;&#x2F; --- Service relationships, misc &amp; synthesis ---
        [&quot;In a service relationship chain (A supplies B, B supplies C), organization B is:&quot;,
         [&quot;Both a service consumer (of A) and a service provider (to C)&quot;,
          &quot;Only a provider&quot;,
          &quot;Only a consumer&quot;,
          &quot;A broker with no service role&quot;],
         &quot;Most organizations sit mid-chain: consuming upstream services and transforming them into what they provide downstream.&quot;],
        [&quot;When the outcomes of the FINAL consumer in a service chain are not met:&quot;,
         [&quot;Every upstream relationship in the chain is ultimately failing its purpose&quot;,
          &quot;Only the last provider is concerned&quot;,
          &quot;The SLAs of upstream providers make it irrelevant&quot;,
          &quot;The chain should add more intermediaries&quot;],
         &quot;Value co-creation at the end of the chain is what justifies every link. Met SLAs upstream do not excuse failed outcomes downstream.&quot;],
        [&quot;Which ITIL 4 concept did the certification&#x27;s famous one-liner &#x27;co-creation of value&#x27; replace as the headline idea?&quot;,
         [&quot;Value delivered by the provider TO the customer, one-way&quot;,
          &quot;Value defined by the regulator&quot;,
          &quot;Value measured only in money&quot;,
          &quot;Value created by tools&quot;],
         &quot;v4&#x27;s headline shift: value is not delivered AT consumers, it emerges from collaboration between provider and consumer.&quot;],
        [&quot;A provider delivers exactly to specification, never talks to the consumer, and value is not achieved. ITIL 4 says:&quot;,
         [&quot;This is expected: value requires the consumer&#x27;s participation and cannot be created unilaterally&quot;,
          &quot;The provider has still created value&quot;,
          &quot;The consumer is contractually at fault&quot;,
          &quot;Value should be redefined to match the specification&quot;],
         &quot;Specification compliance without engagement is service management without relationship management, and value needs both sides.&quot;],
        [&quot;Which pairing is CORRECT?&quot;,
         [&quot;Incident: restore fast; Problem: prevent recurrence; Change: modify safely&quot;,
          &quot;Incident: prevent recurrence; Problem: restore fast; Change: modify safely&quot;,
          &quot;Incident: modify safely; Problem: restore fast; Change: prevent recurrence&quot;,
          &quot;Incident: restore fast; Problem: modify safely; Change: prevent recurrence&quot;],
         &quot;Three practices, three verbs: incidents are restored, problems are prevented from recurring, changes are made safely. Keep the verbs attached to the right nouns.&quot;],
        [&quot;A user cannot print (worked yesterday). The BEST classification is:&quot;,
         [&quot;Incident&quot;,
          &quot;Service request&quot;,
          &quot;Problem&quot;,
          &quot;Standard change&quot;],
         &quot;Something that worked and stopped = incident. If printing failures keep recurring across the fleet, a problem record would then investigate the cause.&quot;],
        [&quot;Five similar crashes this month were resolved by rebooting. What should ALSO be created besides the incident records?&quot;,
         [&quot;A problem record to investigate the underlying cause&quot;,
          &quot;An emergency change to reboot automatically every night&quot;,
          &quot;A service request for new servers&quot;,
          &quot;A new SLA with longer resolution times&quot;],
         &quot;A recurring symptom with an unexamined cause is exactly what problem management exists for. Scheduled reboots without analysis just institutionalize the workaround.&quot;],
        [&quot;Access to a shared folder, listed in the catalog with manager approval, is requested. This is:&quot;,
         [&quot;A service request following its predefined fulfilment workflow&quot;,
          &quot;A normal change requiring CAB review&quot;,
          &quot;An incident&quot;,
          &quot;A known error&quot;],
         &quot;Predefined + pre-agreed (including its approval step) = service request. The CAB has no business here.&quot;],
        [&quot;Which statement about ITIL 4 and DevOps&#x2F;Agile is MOST accurate?&quot;,
         [&quot;ITIL 4 was explicitly designed to integrate with Agile, DevOps, and Lean ways of working&quot;,
          &quot;ITIL 4 forbids continuous deployment&quot;,
          &quot;DevOps replaces the need for any service management&quot;,
          &quot;Agile teams are exempt from change enablement&quot;],
         &quot;v4&#x27;s redesign (guiding principles, value streams, decentralized change authority) exists precisely to complement, not fight, modern delivery.&quot;],
        [&quot;The service catalog provides:&quot;,
         [&quot;A structured view of the services available to consumers and the information needed to request them&quot;,
          &quot;The full technical configuration of every CI&quot;,
          &quot;The organization&#x27;s financial statements&quot;,
          &quot;The list of known errors&quot;],
         &quot;The catalog is the consumer-facing menu: what exists, for whom, and how to get it. Without it, every request becomes an improvised email.&quot;],
    ];

    const TOTAL = 60;
    const PASS_PCT = 65;
    const body = document.getElementById(&quot;ex-body&quot;);
    let quiz = [], idx = 0, score = 0;

    function shuffle(arr) {
        for (let i = arr.length - 1; i &gt; 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [arr[i], arr[j]] = [arr[j], arr[i]];
        }
        return arr;
    }

    function renderStart() {
        body.innerHTML = `
            &lt;div class=&quot;ex-start&quot;&gt;
                &lt;p&gt;${TOTAL} questions await, drawn at random from a hidden bank of ${BANK.length}.&lt;br&gt;
                Answer each one; when you miss, you&#x27;ll be told why.&lt;br&gt;
                Score ${PASS_PCT}% or better to pass. No timer.&lt;&#x2F;p&gt;
                &lt;button class=&quot;ex-btn&quot; id=&quot;ex-start-btn&quot;&gt;Start the exam&lt;&#x2F;button&gt;
            &lt;&#x2F;div&gt;`;
        document.getElementById(&quot;ex-start-btn&quot;).addEventListener(&quot;click&quot;, startExam);
    }

    function startExam() {
        quiz = shuffle(BANK.slice()).slice(0, TOTAL);
        idx = 0;
        score = 0;
        renderQuestion();
    }

    function renderQuestion() {
        const [q, opts] = quiz[idx];
        const options = shuffle(opts.map((text, i) =&gt; ({ text: text, correct: i === 0 })));
        const pct = Math.round((idx &#x2F; TOTAL) * 100);
        body.innerHTML = `
            &lt;div class=&quot;ex-progress&quot;&gt;
                &lt;div class=&quot;ex-progress-text&quot;&gt;
                    &lt;span&gt;Question ${idx + 1} &#x2F; ${TOTAL}&lt;&#x2F;span&gt;
                    &lt;span&gt;Score: ${score}&lt;&#x2F;span&gt;
                &lt;&#x2F;div&gt;
                &lt;div class=&quot;ex-progress-bar&quot;&gt;&lt;div class=&quot;ex-progress-fill&quot; style=&quot;width:${pct}%&quot;&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;ex-question&quot;&gt;${q}&lt;&#x2F;div&gt;
            &lt;div class=&quot;ex-options&quot; id=&quot;ex-options&quot;&gt;&lt;&#x2F;div&gt;
            &lt;div id=&quot;ex-feedback&quot;&gt;&lt;&#x2F;div&gt;
            &lt;div class=&quot;ex-nav&quot; id=&quot;ex-nav&quot;&gt;&lt;&#x2F;div&gt;`;
        const container = document.getElementById(&quot;ex-options&quot;);
        options.forEach(opt =&gt; {
            const btn = document.createElement(&quot;button&quot;);
            btn.className = &quot;ex-option&quot;;
            btn.textContent = opt.text;
            btn.addEventListener(&quot;click&quot;, () =&gt; answer(btn, opt.correct, container));
            container.appendChild(btn);
        });
    }

    function answer(clicked, isCorrect, container) {
        const explanation = quiz[idx][2];
        container.querySelectorAll(&quot;.ex-option&quot;).forEach(b =&gt; {
            b.disabled = true;
            if (b.textContent === quiz[idx][1][0]) b.classList.add(&quot;correct&quot;);
        });
        if (isCorrect) {
            score++;
        } else {
            clicked.classList.add(&quot;wrong&quot;);
        }
        const fb = document.getElementById(&quot;ex-feedback&quot;);
        fb.innerHTML = `
            &lt;div class=&quot;ex-explain ${isCorrect ? &quot;good&quot; : &quot;bad&quot;}&quot;&gt;
                &lt;div class=&quot;ex-explain-head&quot;&gt;${isCorrect ? &quot;✓ Correct&quot; : &quot;✗ Missed: here&#x27;s why&quot;}&lt;&#x2F;div&gt;
                &lt;div&gt;${explanation}&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;`;
        const nav = document.getElementById(&quot;ex-nav&quot;);
        const nextBtn = document.createElement(&quot;button&quot;);
        nextBtn.className = &quot;ex-btn&quot;;
        nextBtn.textContent = (idx + 1 &lt; TOTAL) ? &quot;Next question →&quot; : &quot;See my result&quot;;
        nextBtn.addEventListener(&quot;click&quot;, () =&gt; {
            idx++;
            if (idx &lt; TOTAL) renderQuestion(); else renderResult();
        });
        nav.appendChild(nextBtn);
        nextBtn.focus();
    }

    function renderResult() {
        const pct = Math.round((score &#x2F; TOTAL) * 100);
        const passed = pct &gt;= PASS_PCT;
        const messages = passed
            ? (pct &gt;= 90 ? &quot;Outstanding. The real exam should hold no surprises.&quot;
                         : &quot;You pass. Review the ones you missed and the real thing is yours.&quot;)
            : (pct &gt;= 50 ? &quot;Close. Re-read the practice purposes and the definitions. That&#x27;s where the points hide.&quot;
                         : &quot;Not yet. Go back through the diagrams above, then try again. The bank has plenty you haven&#x27;t seen.&quot;);
        body.innerHTML = `
            &lt;div class=&quot;ex-result&quot;&gt;
                &lt;div class=&quot;ex-score&quot; style=&quot;color:${passed ? &quot;var(--green)&quot; : &quot;var(--red)&quot;}&quot;&gt;${score} &#x2F; ${TOTAL}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ex-verdict ${passed ? &quot;pass&quot; : &quot;fail&quot;}&quot;&gt;${pct}% ${passed ? &quot;Pass&quot; : &quot;Fail&quot;} (bar: ${PASS_PCT}%)&lt;&#x2F;div&gt;
                &lt;p&gt;${messages}&lt;&#x2F;p&gt;
                &lt;button class=&quot;ex-btn&quot; id=&quot;ex-restart-btn&quot;&gt;Start over ↻&lt;&#x2F;button&gt;
            &lt;&#x2F;div&gt;`;
        document.getElementById(&quot;ex-restart-btn&quot;).addEventListener(&quot;click&quot;, startExam);
    }

    renderStart();
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h2&gt;
&lt;p&gt;Not much really.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.careersmarter.com&#x2F;itil-4-foundation-exam-questions&#x2F;&quot;&gt;ITIL v4 Foundation exam questions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=uI0n0kmoYy0&quot;&gt;ITIL v4 Foundation cram course&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.processexam.com&#x2F;peoplecert&#x2F;peoplecert-itil-4-foundation-certification-exam-sample-questions&quot;&gt;ITIL v4 Foundation certification exam sample questions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Samplyr</title>
        <published>2026-07-05T00:00:00+00:00</published>
        <updated>2026-07-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/samplyr/"/>
        <id>https://nskm.xyz/posts/samplyr/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/samplyr/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;sampling.gif&quot; alt=&quot;sampling&quot; title=&quot;sampling&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Render unto Caesar what is Caesar&#x27;s: Claude helped me find up-to-date documentation links.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;No other disclaimers for this article.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;the-message-that-found-me-in-thies&quot;&gt;The message that found me in Thiès&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s Saturday, around 1pm. Usually I&#x27;m lying down at that time on a Saturday, but not this one, I was outside, under the Senegalese sun.&lt;&#x2F;p&gt;
&lt;p&gt;With a few good friends, I was wandering around &lt;a href=&quot;https:&#x2F;&#x2F;maps.app.goo.gl&#x2F;wttogBYeYJcnMJi47&quot;&gt;Keur Cherif Lo&lt;&#x2F;a&gt;, a small commune situated in western Senegal. It forms part of the Pambal district in the department of Tivaouane (Thiès region).&lt;&#x2F;p&gt;
&lt;p&gt;I was looking for a plot of land to buy when I got a Signal notification, a message from my friend and brother Dicko. He asked me to proofread some slides he&#x27;d written for a talk he&#x27;s giving at the &lt;a href=&quot;https:&#x2F;&#x2F;user2026.r-project.org&#x2F;&quot;&gt;useR! 2026 conference&lt;&#x2F;a&gt;. We&#x27;re really &lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;JM83LzAsdt8AAAAd&#x2F;tenor.gif&quot;&gt;proud&lt;&#x2F;a&gt; of him.&lt;&#x2F;p&gt;
&lt;p&gt;I wasn&#x27;t in front of my &lt;a href=&quot;https:&#x2F;&#x2F;frame.work&#x2F;laptop13&quot;&gt;computer&lt;&#x2F;a&gt;, and it was unbearably hot, so I replied that I&#x27;d read everything calmly once I got home. Which I did, of course, &lt;em&gt;I&#x27;m a man of my word&lt;&#x2F;em&gt;, but mostly because Dicko rarely writes, and when he does, it&#x27;s always extremely interesting.... &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=K0HSD_i2DvA&quot;&gt;Music&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 200px&quot; src=&quot;&#x2F;images&#x2F;land.jpg&quot; alt=&quot;land&quot; title=&quot;land&quot;&#x2F;&gt;
&lt;h2 id=&quot;describe-the-what-not-the-how&quot;&gt;Describe the what, not the how&lt;&#x2F;h2&gt;
&lt;p&gt;I work in an industry where it&#x27;s often preferable to describe what you want to obtain, rather than how to obtain it.&lt;&#x2F;p&gt;
&lt;p&gt;This has a name: &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Declarative_programming&quot;&gt;declarative programming&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, as opposed to &lt;em&gt;imperative programming&lt;&#x2F;em&gt;. A declarative language lets you express the logic of a computation without spelling out its control flow: SQL, regular expressions, and Makefiles are the textbook examples. Everything below, from Django models to Kubernetes manifests to samplyr itself, is really the same idea wearing different clothes.&lt;&#x2F;p&gt;
&lt;p&gt;I first ran into this idea when I wrote my first lines of Django in 2006.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# models.py — we describe the shape of the data we want,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# not the SQL needed to create or query it.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;House(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    region = models.ForeignKey(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, on_delete=models.CASCADE)
&lt;&#x2F;span&gt;&lt;span&gt;    beds = models.PositiveIntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    treated_nets = models.PositiveIntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Django&amp;#39;s ORM (the &amp;quot;engine&amp;quot;) takes care of the &amp;quot;how&amp;quot;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# generating the CREATE TABLE statement, indexes, migrations, etc.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In reality, I&#x27;d already run into the concept &lt;em&gt;without recognizing it, without really realizing it&lt;&#x2F;em&gt;, back in 2005, when I wrote my first lines of SQL. When you write a SQL query, you don&#x27;t describe the &quot;how&quot;, you describe the &quot;what&quot;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;-- We describe the &amp;quot;what&amp;quot;: the shape of the result set we want.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; region, SUM(beds) AS total_beds, SUM(treated_nets) AS total_nets
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; houses
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span&gt; region;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;-- The query planner (the &amp;quot;engine&amp;quot;) decides &amp;quot;how&amp;quot;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;-- which indexes to scan, what join order to use, how to sort and aggregate.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the pattern shows up in so many places. I write quite a few &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Kubernetes manifests&lt;&#x2F;a&gt; these days:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# We describe the desired state: three replicas of this container,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# always running, always listening on port 8000.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;survey-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;survey-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;survey-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;survey-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;registry.example.com&#x2F;survey-api:1.4.0&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Kubernetes (the &amp;quot;engine&amp;quot;) takes care of the &amp;quot;how&amp;quot;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# scheduling pods, restarting crashed containers, rolling out updates.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;where-this-connects-to-sampling&quot;&gt;Where this connects to sampling&lt;&#x2F;h2&gt;
&lt;p&gt;Because the solution Dicko came up with follows roughly the same pattern: describe the &quot;what&quot;, not the &quot;how&quot;, and let the library produce the right result. We&#x27;re talking about &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Sampling_(statistics)&quot;&gt;statistics and sampling&lt;&#x2F;a&gt; here, fields that are, in some ways, quite far from mine, and yet the parallel exists, and I find that genuinely interesting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-real-problem-sampling-a-population-fairly&quot;&gt;The real problem: sampling a population fairly&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s the original problem: if you have a list of every house in a country and you want to know the number of beds and the number of insecticide-treated mosquito nets, how do you go about it?&lt;&#x2F;p&gt;
&lt;p&gt;You could, of course, draw 300 houses at random from the total. And after the draw, end up with 250 houses clustered around a single town, 49 a bit further away, and one lone house completely and utterly isolated from the other 299.&lt;&#x2F;p&gt;
&lt;p&gt;Is that representative of the whole population? And from a cost and logistics standpoint, &lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;Qr-JcZEAOekAAAAC&#x2F;tenor.gif&quot;&gt;do you really want&lt;&#x2F;a&gt; to travel that far just to survey a single house?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;enter-samplyr-a-grammar-for-sampling-designs&quot;&gt;Enter Samplyr: a grammar for sampling designs&lt;&#x2F;h2&gt;
&lt;p&gt;What Dicko actually wants is to carry out sampling that&#x27;s as representative as possible of the total population under study. He wants to be certain that whenever he draws a sample, it follows a specific formula, a specific design: stratum &amp;gt; cluster &amp;gt; stage &amp;gt; draw.&lt;&#x2F;p&gt;
&lt;p&gt;Writing that design in R meant that, rereading the code afterwards, it became very, very hard to recognize the design and the steps that made it up. To his surprise, the same design written in SAS or SPSS actually read like the design itself. So he decided to fix the problem: write his R code in a way that lets him clearly see and read the strata, clusters, stages, and draws.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 200px&quot; src=&quot;&#x2F;images&#x2F;challenge-accepted.png&quot; alt=&quot;challenge accepted&quot; title=&quot;challenge-accepted&quot;&#x2F;&gt;
&lt;p&gt;To solve this, he built a kind of grammar that helps him write the design directly in R. Its engine takes care of executing the design and correctly applying it to the data under study.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;eyes-opening&quot;&gt;Eyes opening&lt;&#x2F;h2&gt;
&lt;p&gt;I didn&#x27;t think you had to account for all these considerations before running surveys. I guess I learned something today.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m also realizing that when I do &lt;code&gt;random.sample(items, x)&lt;&#x2F;code&gt;, the result of this function call may not be as representative as I thought it is. This is a very good lesson.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;random.sample()&lt;&#x2F;code&gt; performs &lt;strong&gt;simple random sampling (SRS)&lt;&#x2F;strong&gt;: every item has an equal, independent chance of being drawn, with no notion of the population&#x27;s structure &lt;em&gt;(no regions, no stratums, no clusters)&lt;&#x2F;em&gt;. SRS is unbiased &lt;em&gt;in expectation&lt;&#x2F;em&gt;, but for any single draw, a stratum can be &lt;em&gt;over or under&lt;&#x2F;em&gt; represented &lt;strong&gt;purely by chance&lt;&#x2F;strong&gt;, especially with small sample sizes. Here&#x27;s a population of 1000 houses spread unevenly across three regions:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;random
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;collections &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Counter
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;random.seed(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 1000 houses spread unevenly across 3 regions
&lt;&#x2F;span&gt;&lt;span&gt;population = ([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Dakar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;700&lt;&#x2F;span&gt;&lt;span&gt;) + ([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Thies&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;) + ([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Ziguinchor&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;sample = random.sample(population, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;print(Counter(sample))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Counter({&amp;#39;Dakar&amp;#39;: 17, &amp;#39;Thies&amp;#39;: 3})
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Ziguinchor is 10% of the population, and got drawn zero times.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;is-there-a-way-to-use-those-concepts-on-a-daily-basis&quot;&gt;Is there a way to use those concepts on a daily basis ?&lt;&#x2F;h2&gt;
&lt;p&gt;In my day-to-day work, as a software engineer, I don&#x27;t do anything related to statistics or probability. The people who (maybe) do are the epidemiologists and biostatisticians in the epidemiology department of the &lt;a href=&quot;https:&#x2F;&#x2F;institutpasteurdakar.sn&#x2F;&quot;&gt;medical research center&lt;&#x2F;a&gt; I currently work at.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s a shame, really: we never talk to each other, we never collaborate. They&#x27;re off in one corner, and we&#x27;re in another. On rare occasions, they hand us R scripts that we somehow manage to run, just to get a few charts out of it and that&#x27;s it.... It&#x27;s a real pity... Anyway...&lt;&#x2F;p&gt;
&lt;p&gt;I suddenly feel the urge to update my &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;patrick_dikiesse.pdf&quot;&gt;CV&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;I strongly and vividly encourage you to read Dicko&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;dickoa.gitlab.io&#x2F;samplyr_user2026&#x2F;#&#x2F;title-slide&quot;&gt;slides&lt;&#x2F;a&gt; to learn more. And if you like what you see, please share it far and wide, because he uses free and open source software to address humanitarian problems in Africa.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to visit Dicko&#x27;s website or the useR! 2026 conference website.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ahmadoudicko.com&#x2F;&quot;&gt;Ahmadou Dicko, PhD&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dickoa.gitlab.io&#x2F;samplyr&#x2F;&quot;&gt;Samplyr&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;user2026.r-project.org&#x2F;&quot;&gt;useR! 2026 Conference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=na8YD63Juck&quot;&gt;9th Wonder &amp;amp; Bob James in conversation around sampling and getting sampled&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;samplics-org&#x2F;samplics&quot;&gt;samplics&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;samplics-org.github.io&#x2F;samplics&#x2F;&quot;&gt;svy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=35FNO5ygnP4&quot;&gt;Samplyr, plays audio files from a microSD card with an 8-bit, 32kHz architecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;random.html#random.sample&quot;&gt;Python docs: &lt;code&gt;random.sample()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Developer Growth Report — 2026-06-22</title>
        <published>2026-06-22T00:00:00+00:00</published>
        <updated>2026-06-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/developer-growth/developer-growth-2026-06-22/"/>
        <id>https://nskm.xyz/developer-growth/developer-growth-2026-06-22/</id>
        
        <content type="html" xml:base="https://nskm.xyz/developer-growth/developer-growth-2026-06-22/">&lt;h1 id=&quot;developer-growth-report&quot;&gt;Developer Growth Report&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Period&lt;&#x2F;strong&gt;: 2026-06-15 to 2026-06-22
&lt;strong&gt;Generated&lt;&#x2F;strong&gt;: 2026-06-22&lt;&#x2F;p&gt;
&lt;h2 id=&quot;work-summary&quot;&gt;Work Summary&lt;&#x2F;h2&gt;
&lt;p&gt;This week spanned 7 projects and 131 recorded messages — a dense, multi-domain sprint. The dominant thread was the &lt;strong&gt;WALIP health surveillance platform&lt;&#x2F;strong&gt;: auditing 6 Django microservices (consultation, analyses, patient, notifications, organizations, bio_bank), reasoning about cross-service data ownership, hardening Kafka consumers, securing Swagger endpoints, and exploring deployment infrastructure for multi-country rollouts. A second thread was content creation — a comprehensive article on the Senegalese road code (&lt;code&gt;code-de-la-route-sn.md&lt;&#x2F;code&gt;) requiring research, source verification, interactive mind maps, and structured HTML tables across 10+ sections.&lt;&#x2F;p&gt;
&lt;p&gt;DevOps thinking ran deep this week: the deployment repository (&lt;code&gt;automatisation-deploiement-4s-sn-et-pays&lt;&#x2F;code&gt;) triggered a full infrastructure analysis — mixed k8s&#x2F;Docker Compose strategies per country, database migration approaches (Django ORM vs. raw SQL), and an exploration of OCI-artifact-based Compose includes and git submodules. There was also a brief but intentional foray into Zig, signaling a curiosity about systems-level programming beyond the Python&#x2F;Django comfort zone.&lt;&#x2F;p&gt;
&lt;p&gt;The most significant event was personal: the user explicitly acknowledged having over-delegated code writing to AI over many months, and consciously chose to write code themselves — asking Claude to verify rather than generate.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;improvement-areas&quot;&gt;Improvement Areas&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-reclaiming-active-coding-ownership&quot;&gt;1. Reclaiming Active Coding Ownership&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: Fluency degrades without exercise. The muscle memory for writing, debugging, and reading code is separate from the ability to instruct an AI. If the AI is always the one holding the keyboard, the engineer&#x27;s own speed and confidence shrink over time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: Direct self-report: &lt;em&gt;&quot;i spent so many months&#x2F;weeks asking you to write code for me that i lost the habit :) i think i&#x27;m good now&quot;&lt;&#x2F;em&gt; (consultation-microservice session, June 17). Later in the same session, the user wrote the migration themselves and asked for verification — a concrete behavioral shift. This is significant and worth reinforcing deliberately.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Introduce a personal rule — for any task estimated under 30 minutes, write the code first, then ask for review. Use Claude for verification and feedback, not generation. Treat this like a gym habit: schedule 3 &quot;solo coding sessions&quot; per week where Claude is read-only.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Ongoing habit — zero extra time, just a change in mode.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-stop-bypassing-pre-commit-hooks&quot;&gt;2. Stop Bypassing Pre-commit Hooks&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: &lt;code&gt;--no-verify&lt;&#x2F;code&gt; is a deferred bug. Every bypass accumulates technical debt in the form of code that skipped the agreed-upon safety net. Worse, it normalizes the bypass as a workaround rather than signaling that the hook itself needs fixing.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: &lt;code&gt;--no-verify&lt;&#x2F;code&gt; was used across at least 4 separate commits in 3 different microservices this week (notifications, consultation, patient). In one session, the user explicitly said: &lt;em&gt;&quot;please just do a commit and use the --no-verify flag, we&#x27;ll deal with pre-commit in a later time&quot;&lt;&#x2F;em&gt;. The &quot;later time&quot; rarely comes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Dedicate one focused session to auditing what pre-commit checks are failing and why. Fix the root causes (likely import sorting, type stubs, or missing test coverage). Add a note to your team&#x27;s CONTRIBUTING.md that &lt;code&gt;--no-verify&lt;&#x2F;code&gt; requires a paired follow-up ticket. CI&#x2F;CD should run the same checks — so bypassing locally only shifts the pain downstream.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 2–4 hours to audit and fix pre-commit configuration across the monorepo.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-formalizing-microservice-data-ownership-decisions&quot;&gt;3. Formalizing Microservice Data Ownership Decisions&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: The WALIP platform has 6 services with fuzzy boundaries. This week saw multiple conversations about where models should live (Project model: analyses-service vs consultation-service?), what crosses via Kafka vs REST, and how to represent cross-service references (FK vs. string code vs. ArrayField). Without a shared decision framework, each engineer makes these calls differently.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: Three separate sessions involved the same class of question — &quot;where should this model live?&quot; and &quot;should I store the ID or the code?&quot;. The reasoning was good each time, but there was no reference document to anchor decisions. The ArrayField approach for &lt;code&gt;projects&lt;&#x2F;code&gt; was implemented across Prescription, TDR, SymptomType, Vaccines, ChronicDisease — which is a significant cross-cutting decision that deserves explicit documentation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Write a one-page Architecture Decision Record (ADR) for the WALIP platform covering: (1) which service owns which entities, (2) how cross-service references are represented (string codes vs. IDs), (3) when to use Kafka vs. REST. This document prevents the same reasoning from being re-derived in every session.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 3–4 hours to draft, review with team.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-deep-dive-into-kafka-consumer-guarantees&quot;&gt;4. Deep Dive into Kafka Consumer Guarantees&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: The consumer porting work this week was done correctly, but the understanding of &lt;em&gt;why&lt;&#x2F;em&gt; each pattern matters — at-least-once delivery, auto-commit vs. manual commit, idempotency — was built incrementally through conversation rather than from a solid mental model. Gaps here surface as subtle bugs that don&#x27;t crash but produce broken behavior (as the user found: 2 logic bugs missed in first review).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: After porting the improved consumer from analyses-service to notifications-microservice, the user asked: &lt;em&gt;&quot;before doing the commit, teach me about the algorithm, the principles that has been followed to write this consumer module&quot;&lt;&#x2F;em&gt;. This is exactly the right instinct. The content was saved to a text file for future reference — but it hasn&#x27;t been transformed into a working mental model yet.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Turn that saved text file (&lt;code&gt;kafka_consumer.txt&lt;&#x2F;code&gt;) into a blog article (you already write those). The act of explaining it for a reader cements understanding better than passive reading. Complement with a deliberate experiment: write a consumer that deliberately fails mid-batch and verify your error handling behaves correctly.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 4–6 hours (article draft + hands-on experiment).&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;5-closing-the-devops-knowledge-gap-systematically&quot;&gt;5. Closing the DevOps Knowledge Gap Systematically&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: The deployment repository revealed several patterns the user encountered for the first time this week: OCI-artifact-based Docker Compose includes, mixed k8s&#x2F;Compose per-country strategies, git submodules for deployment config sharing. Each was explored reactively — prompted by a problem, not proactively understood.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: Multiple &quot;is this normal? is this something serious companies do?&quot; questions around k8s vs Compose mixed deployments (June 18). The user was skeptical — correctly — about using k8s CronJobs for countries whose main stack runs on Compose. The analysis was sound, but the knowledge was assembled from scratch in session rather than drawn from existing mental models.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Pick one authoritative resource on production deployment patterns (Kelsey Hightower&#x27;s Kubernetes the Hard Way, or the Docker Compose production guide) and work through it deliberately — not as a project, but as 30-minute reading blocks between coding sessions. Build the vocabulary so future deployment conversations start from a shared baseline.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 1–2 hours&#x2F;week over 4 weeks.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;strengths-observed&quot;&gt;Strengths Observed&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strong analogical thinking&lt;&#x2F;strong&gt;: Proactively sought aviation safety principles (CRM, checklists, dead-man&#x27;s switch) to apply to Django API development — a rare and valuable habit. Keep doing this cross-domain synthesis.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Documentation discipline&lt;&#x2F;strong&gt;: Consistently saved key conversations to text files for future reference (aviation principles, infrastructure analysis, Kafka consumer patterns). This is how organizational knowledge gets built.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Knowing when to push back&lt;&#x2F;strong&gt;: In the WALIP metrics session, the user challenged WHO&#x2F;CDC conventions rather than accepting them blindly — &lt;em&gt;&quot;is there really anything that I can do as a software engineer?&quot;&lt;&#x2F;em&gt; — and extracted actionable engineering implications. That intellectual honesty is a strength.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;action-items&quot;&gt;Action Items&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;This week&lt;&#x2F;strong&gt;: Write one piece of code solo (no generation, only verification). The patient-microservice migration you wrote yourself is the model — repeat it deliberately.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;This week&lt;&#x2F;strong&gt;: Run &lt;code&gt;pre-commit run --all-files&lt;&#x2F;code&gt; on one microservice, list the failures, fix them, and document why they were failing.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Next 2 weeks&lt;&#x2F;strong&gt;: Draft the WALIP ADR for service data ownership. Start with the &lt;code&gt;projects&lt;&#x2F;code&gt; ArrayField decision — it&#x27;s already been applied across 5 models.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Next month&lt;&#x2F;strong&gt;: Convert &lt;code&gt;kafka_consumer.txt&lt;&#x2F;code&gt; into a publishable article on the blog.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ongoing&lt;&#x2F;strong&gt;: 30 min&#x2F;week of structured DevOps reading — pick one resource and stick to it for a month.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;learning-resources&quot;&gt;Learning Resources&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;code-ownership-ai-dependency&quot;&gt;Code Ownership &amp;amp; AI Dependency&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46820924&quot;&gt;How AI assistance impacts the formation of coding skills&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Feb 2026 — Research data showing AI-assisted groups accomplished tasks faster but with measurable loss of competency. Directly relevant to the habit reclamation work this week.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=48463576&quot;&gt;Ask HN: How are you preserving your skills while using AI?&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Recent — Community strategies for maintaining engineering depth while using AI tools. The &quot;Prompt-Then-Review&quot; loop critique is particularly worth reading.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42336553&quot;&gt;The 70% problem: Hard truths about AI-assisted coding&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Dec 2024 — Honest assessment of where AI coding tools help and where they create subtle skill gaps.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;pre-commit-hooks-git-discipline&quot;&gt;Pre-commit Hooks &amp;amp; Git Discipline&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45527306&quot;&gt;Discussion of the Benefits and Drawbacks of the Git Pre-Commit Hook&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — 2025 — Balanced HN thread on when hooks help and when they become friction. Useful for deciding what to put in hooks vs. CI.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46398906&quot;&gt;Pre-commit hooks are broken&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — 2026 — Critique of current pre-commit tooling; clarifies &lt;em&gt;why&lt;&#x2F;em&gt; developers reach for &lt;code&gt;--no-verify&lt;&#x2F;code&gt; and what better alternatives look like.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=29634897&quot;&gt;Pre-commit: framework for managing&#x2F;maintaining multi-language pre-commit hooks&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Classic HN thread on the &lt;code&gt;pre-commit&lt;&#x2F;code&gt; framework that&#x27;s almost certainly what your projects use.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;microservices-event-driven-data-ownership&quot;&gt;Microservices &amp;amp; Event-Driven Data Ownership&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=40619521&quot;&gt;Anti-patterns in event-driven architecture&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — 2024 — Catalog of what goes wrong in event-driven microservices. Directly applicable to WALIP&#x27;s Kafka-based inter-service communication.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=28034882&quot;&gt;Ask HN: Has anyone fully embraced an event-driven architecture?&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Practitioners sharing hard-won lessons about schema evolution, failure modes, and data ownership — the same questions you were wrestling with this week.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46705134&quot;&gt;Microservices for the Benefits, Not the Hustle&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — 2026 — Pragmatic take on when microservices justify their complexity. Good reference for the WALIP ADR.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;kafka-consumer-reliability&quot;&gt;Kafka Consumer Reliability&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=23206566&quot;&gt;What every software engineer should know about Apache Kafka&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Foundational HN thread. If you haven&#x27;t read the linked article, it&#x27;s the one document that will fill the most gaps in your Kafka mental model.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=28903614&quot;&gt;Issues we&#x27;ve encountered while building a Kafka based data processing pipeline&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — 2021 — Real-world failure post-mortem. The bugs they encountered map directly onto the consumer patterns you ported this week.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14670801&quot;&gt;Exactly-once Semantics: How Kafka Does it&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Technical deep dive on exactly-once vs. at-least-once. Essential foundation for understanding why manual commit matters.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;devops-kubernetes-vs-docker-compose&quot;&gt;DevOps: Kubernetes vs. Docker Compose&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=32484008&quot;&gt;Docker Compose best practices for dev and prod&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — 2022 — Practical guide to Compose in production; includes patterns for multi-environment configs (directly relevant to your multi-country deployment problem).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=30767393&quot;&gt;Ask HN: Who operates at scale without containers?&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Perspective check: k8s is not always the answer. Helpful for evaluating the mixed-strategy approach in WALIP&#x27;s deployment repo.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=19321070&quot;&gt;Microservices, Containers and Kubernetes in Ten Minutes&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Compact conceptual overview to build vocabulary before deeper study.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Work Report — 2026-06-08 to 2026-06-22</title>
        <published>2026-06-22T00:00:00+00:00</published>
        <updated>2026-06-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/what-i-have-done/work-report-2026-06-22/"/>
        <id>https://nskm.xyz/what-i-have-done/work-report-2026-06-22/</id>
        
        <content type="html" xml:base="https://nskm.xyz/what-i-have-done/work-report-2026-06-22/">&lt;h1 id=&quot;work-report-2026-06-08-to-2026-06-22&quot;&gt;Work Report — 2026-06-08 to 2026-06-22&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Period&lt;&#x2F;strong&gt;: 8 June 2026 to 22 June 2026
&lt;strong&gt;Generated&lt;&#x2F;strong&gt;: 22 June 2026&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;The dominant theme of the period was stabilisation and feature expansion of the WALIP platform — a six-service web application for epidemiological surveillance, currently deployed across multiple countries in West Africa. The most critical delivery was fixing a silent failure in the notification service that was preventing supervisors from receiving epidemiological alert emails routed through a specific code path. In parallel, five entity types across three services received a new project-tagging mechanism that the frontend team requires to filter data by research project — work spread across 14 commits and multiple pull requests. Several sessions ran past midnight, particularly during the week of June 8–11.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-was-delivered&quot;&gt;What Was Delivered&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-supervisor-email-alert-routing-production-bug-fixed&quot;&gt;1. Supervisor email alert routing — production bug fixed&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Supervisors responsible for validating epidemiological results are now reliably notified by email when their action is required; previously, alerts sent via the &lt;code&gt;supervisor_email_map&lt;&#x2F;code&gt; routing path were silently discarded.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this fix, a supervisor could have missed a notification requiring urgent action on a critical sample result — with no error, no log visible to the user, and no indication the alert was ever sent. The failure was invisible.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: One focused session to diagnose the broken routing path, patch the resolver logic, document the dispatch flow in the README as an ASCII diagram, and write an ITIL-format incident ticket for the Jira backlog.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-project-tagging-across-five-clinical-entities&quot;&gt;2. Project-tagging across five clinical entities&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The frontend application can now filter prescriptions, test requests (TDR), symptom types, conduct records, and chronic disease records by research project code — a capability that enables multi-project views previously impossible to build.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this, the frontend would have had to fetch all records and filter client-side, exposing data from unrelated projects to users who should not see it. The correct solution required a database field, a migration, and a filter endpoint — the fast workaround would have created a data-visibility gap.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Delivered across five separate pull requests over six days (June 16–18), covering three microservices (consultation, patient, analyses), with Python and SQL migrations in parallel for each entity.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-kafka-consumer-message-queue-reader-reliability-hardened&quot;&gt;3. Kafka consumer (message queue reader) reliability — hardened&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The notification service&#x27;s message reader now correctly tracks which messages it has processed, preventing messages from being silently lost or incorrectly replayed when the service restarts under load.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Two logic bugs were present that would not crash the system but would cause broken behaviour: messages could be acknowledged before processing completed, and error recovery was not triggering correctly. Had these remained, epidemiological notification data could have been silently delayed or dropped without any visible error, with the system appearing healthy.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Half a night of work (session started ~18:25, continued past midnight). The consumer was rewritten and verified in two review passes before commit, specifically because the first pass missed both bugs.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-platform-administration-feature-soft-delete-and-full-management-api&quot;&gt;4. Platform administration feature — soft delete and full management API&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Administrators can now create, update, enable, and disable laboratory platforms (the equipment categories used to classify sample analyses) through the API, without deleting records from the database — preserving historical data integrity.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;The previous state had no soft-delete mechanism: deactivating a platform would have required a hard delete, breaking all historical analyses referencing it and making audit trails impossible to reconstruct.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Mirrored from prior work on the patient service — one session to port, add seed data, write full unit test coverage (pushing coverage from 75% to 76%), and create insert-command tests for all reference tables.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;5-api-documentation-access-control-locked-down&quot;&gt;5. API documentation — access control locked down&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The platform&#x27;s interactive API documentation (Swagger) now requires authentication before it can be accessed. Previously, any person who knew the URL — inside or outside the organisation — could read the full list of endpoints, parameters, and data structures.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;An unauthenticated API schema is a reconnaissance map for an attacker. Knowing all endpoint paths, expected fields, and data types cuts the effort of a targeted attack significantly. This was particularly sensitive given the platform handles patient and epidemiological data.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Identified during a management-data audit session; fixed in the same session with a targeted change to both documentation views.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;6-institut-pasteur-intranet-redesigned-and-shipped&quot;&gt;6. Institut Pasteur intranet — redesigned and shipped&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Institut Pasteur de Dakar now has a branded internal portal with working navigation, a workplace health and safety section, and a quick-access layout for common tools (IT ticketing, HR forms) — replacing a default Quarto template that did not reflect the institution&#x27;s identity.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without an accessible internal directory, staff finding tools, escalation contacts, or HR procedures were searching by memory or word of mouth — a real risk in incidents requiring fast escalation to the right person.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Two full sessions (one of which continued past midnight) for design, brand alignment, navigation restructuring, link verification on the Kubernetes deployment, and a footer redesign.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-was-prevented&quot;&gt;What Was Prevented&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-silent-production-failure-column-missing-in-deployment&quot;&gt;1. Silent production failure: column missing in deployment&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;A database column added to the platform management service had not been applied to the production environment via a migration. If the frontend team had called the platform listing endpoint in production before the column existed, every request would have returned a database error with no graceful fallback — taking the platform listing offline for all users in the deployed environment.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Spotted immediately during post-deployment testing when the endpoint returned a &lt;code&gt;ProgrammingError&lt;&#x2F;code&gt; referencing the missing column; investigated and resolved in the same session before wider use.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-seed-data-regression-earliest-migrations-silently-broken&quot;&gt;2. Seed data regression: earliest migrations silently broken&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;A seed data column was removed from a CSV file used by the earliest database migration without updating the migration itself. Every fresh deployment — onboarding a new country, spinning up a test environment, or running CI — would have failed silently at the data-seeding step, making the service appear correctly deployed but missing all reference data.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: During a debugging session on the custom SQL migration tool, a full sequential replay of all migrations revealed the breakage. A regression test was then written and committed to ensure this can never recur undetected.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-notification-consumer-deployed-with-two-silent-logic-bugs&quot;&gt;3. Notification consumer deployed with two silent logic bugs&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;Two bugs in the notification service&#x27;s message queue reader (Kafka consumer) would not have caused crashes or visible errors. The first would have acknowledged messages as processed before the processing actually completed, meaning a restart during high load could lose messages permanently. The second prevented the error-recovery path from triggering correctly.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Caught during a manual code review pass before the commit was made; required two review rounds to identify both bugs.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-is-in-progress-and-why-it-takes-time&quot;&gt;What Is In Progress and Why It Takes Time&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-sql-based-migration-tooling-for-controlled-database-updates&quot;&gt;1. SQL-based migration tooling for controlled database updates&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;&#x2F;strong&gt;: A custom Django management command that applies database changes using raw SQL files rather than relying solely on the framework&#x27;s automatic migration tool — allowing DBAs and operations teams to review and approve the exact SQL before it runs in production.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why it cannot be rushed&lt;&#x2F;strong&gt;: SQL migrations that include data insertion commands (via &lt;code&gt;COPY&lt;&#x2F;code&gt;) interact with database server permissions in ways that differ between local development and production environments. Rushing this risks applying partial migrations with no clean rollback path. The tool currently handles most cases correctly; the remaining edge cases involve SQL meta-commands (&lt;code&gt;\copy&lt;&#x2F;code&gt; vs &lt;code&gt;COPY&lt;&#x2F;code&gt;) that require testing against a real production-equivalent database environment.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-jenkins-automated-build-pipeline-standardisation-across-all-six-services&quot;&gt;2. Jenkins (automated build pipeline) standardisation across all six services&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;&#x2F;strong&gt;: A shared library of build and deployment scripts to replace six separate, inconsistently maintained pipeline configurations — one per microservice.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why it cannot be rushed&lt;&#x2F;strong&gt;: Changing a CI&#x2F;CD pipeline incorrectly blocks every developer from merging code until it is fixed. The shared library has been audited for what is missing; implementation requires coordination with colleagues who maintain the Jenkins server configuration and cannot be done unilaterally.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Report covers git activity and engineering work sessions from 2026-06-08 to 2026-06-22.&lt;&#x2F;em&gt;
&lt;em&gt;Generated 2026-06-22.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Developer Growth Report — 2026-06-08</title>
        <published>2026-06-08T00:00:00+00:00</published>
        <updated>2026-06-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/developer-growth/developer-growth-2026-06-08/"/>
        <id>https://nskm.xyz/developer-growth/developer-growth-2026-06-08/</id>
        
        <content type="html" xml:base="https://nskm.xyz/developer-growth/developer-growth-2026-06-08/">&lt;h1 id=&quot;developer-growth-report&quot;&gt;Developer Growth Report&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Period&lt;&#x2F;strong&gt;: 2026-06-01 to 2026-06-08
&lt;strong&gt;Generated&lt;&#x2F;strong&gt;: 2026-06-08&lt;&#x2F;p&gt;
&lt;h2 id=&quot;work-summary&quot;&gt;Work Summary&lt;&#x2F;h2&gt;
&lt;p&gt;This week touched nine separate projects across backend microservices (Django&#x2F;Python), an Angular frontend, documentation pipelines (Quarto&#x2F;Pandoc), and infrastructure tooling (Kubernetes, Docker, shell scripting). The dominant technical focus was on the backend microservice platform: implementing soft-delete, a coordinated security hardening sprint across six services, and investigating export&#x2F;filter inconsistencies in the analyses service.&lt;&#x2F;p&gt;
&lt;p&gt;A notable meta-theme ran alongside the feature work: you spent time explicitly improving your development tooling and constraints — refining CLAUDE.md, fixing the test-stub skill, and wiring up the plan-track system. This is a healthy signal. You are aware of the gaps in your workflow and investing in closing them, rather than just shipping features.&lt;&#x2F;p&gt;
&lt;p&gt;The breadth of the week is worth naming: backend, frontend, DevOps, documentation, and tooling all in seven days. That breadth is a genuine strength and also a source of the context-loss patterns discussed below.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;improvement-areas&quot;&gt;Improvement Areas&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-the-tdd-red-phase-from-formality-to-genuine-design-signal&quot;&gt;1. The TDD red phase — from formality to genuine design signal&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: A test that fails only because of &lt;code&gt;assert False, &quot;implement me&quot;&lt;&#x2F;code&gt; teaches you nothing about your design. The value of TDD is in writing a test that &lt;em&gt;describes the interface you wish existed&lt;&#x2F;em&gt; and watching it fail for the right reason — the implementation doesn&#x27;t exist yet. Skipping this produces tests that pass once you fill in the placeholder, without ever having validated that the test actually catches regressions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: You spent a significant portion of June 6th refining TDD enforcement in CLAUDE.md and fixing the test-stub skill. You caught that &lt;code&gt;assert False&lt;&#x2F;code&gt; placeholders produce trivially-satisfied red steps (&quot;the red step is satisfied — tests will always fail because of the placeholder, not because the logic is wrong&quot;). You also asked about using &lt;code&gt;pytest --collect-only&lt;&#x2F;code&gt; to verify test existence before writing — and then correctly abandoned that as too complex. This shows sharp intuition about the problem but the fix is still being searched for.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: For the next feature you implement — pick one model method or manager method — write the test &lt;em&gt;before any implementation file is touched&lt;&#x2F;em&gt;, run &lt;code&gt;pytest -k test_name&lt;&#x2F;code&gt; to confirm it fails with &lt;code&gt;AttributeError&lt;&#x2F;code&gt; or &lt;code&gt;ImportError&lt;&#x2F;code&gt; (not &lt;code&gt;AssertionError&lt;&#x2F;code&gt; from a placeholder), then implement. Do this three times deliberately and the habit wires in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: One intentional practice session per day for one week. No reading required — this is a muscle, not knowledge.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-django-domain-layer-confident-migrations-and-manager-design&quot;&gt;2. Django domain layer — confident migrations and manager design&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: Uncertainty at the ORM and migration layer slows down every feature. When you have to ask &quot;what will happen to existing rows?&quot;, or iterate on a field name three times (is_active → is_deleted → is_active again), you are paying a cognitive tax on every domain change. Closing this gap makes refactoring faster and migrations less scary.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: During the soft-delete implementation, you asked &quot;when applying the migration we just created about is_active, what will happen to the existing rows? Do we need an explicit migration to add True to all the existing rows?&quot; — a valid question but one that a confident Django user resolves by reading the migration file directly. Separately, you noticed a difference between migrations for two services (one had &lt;code&gt;AddField&lt;&#x2F;code&gt; only, the other had &lt;code&gt;AddField + AlterModelManager&lt;&#x2F;code&gt;) and needed confirmation that the SQL was identical — this is a good instinct to verify, but the underlying mental model of what Django migrations track (schema vs. Python-layer manager registration) was not yet solid.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Read the Django docs section on custom managers and querysets back-to-back with the HackerNews thread linked below on building higher-level query APIs. Then open any migration file in your codebase, read it line by line, and explain to yourself what each operation does at the SQL level. Do this for three migrations of different shapes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Two focused reading sessions (90 minutes total).&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-security-built-into-the-workflow-not-discovered-after-the-fact&quot;&gt;3. Security built into the workflow, not discovered after the fact&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: Every security finding discovered after a feature ships is a finding that lived in production for some time. The JWT log-scrubbing fix this week was correct and well-executed — but it was triggered by &quot;could you help me make my Django project more secure?&quot; after the feature was already running. A security checklist applied at PR time would have caught this before the first commit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: The security sprint on June 2nd started with an explicit reactive prompt: &quot;could you help me make my Django project even more secure and tell&#x2F;show me how to detect if there are some cyberattacks possible on them?&quot; The &lt;code&gt;django-security-hunter&lt;&#x2F;code&gt; scan (linked below, April 2026) is exactly the kind of tool that can be wired into a pre-commit or CI step to catch these passively. The OpenAPI&#x2F;Swagger exposure behind DEBUG was similarly a finding, not a design decision made upfront.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Add one step to your PR checklist (or CLAUDE.md): before merging a new endpoint or model field, ask &quot;does this touch auth, tokens, secrets, or logging?&quot; If yes, run &lt;code&gt;django-security-hunter&lt;&#x2F;code&gt; before the PR is reviewed. This converts security from a sprint into a gate.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 30 minutes to wire up &lt;code&gt;django-security-hunter&lt;&#x2F;code&gt; in one project as a proof of concept.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-release-pipeline-codification-from-scripting-to-a-defined-process&quot;&gt;4. Release pipeline codification — from scripting to a defined process&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: You asked on June 3rd: &quot;what is the most cleanest, stable, robust approach to do a release?&quot; — and the SQL migration script you started with that day was described as written &quot;à la va vite&quot; (hastily). These two signals together mean the path from &lt;code&gt;develop&lt;&#x2F;code&gt; to &lt;code&gt;production&lt;&#x2F;code&gt; is not yet documented, automated, or reliably repeatable. Every release carries unquantified risk.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: You have multiple environments (develop → recette → release → production), database migrations sometimes done via &lt;code&gt;manage.py migrate&lt;&#x2F;code&gt; and sometimes via raw SQL scripts, and environment variable setup that currently requires manual Kubernetes configmap edits (which you also built a script for this week). The individual tools exist; the pipeline connecting them does not.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Write a single &lt;code&gt;RELEASE.md&lt;&#x2F;code&gt; at the repo root of your most-deployed service describing the current manual steps in order. Do not automate yet — just document what actually happens. The act of writing it will reveal the gaps, the ordering assumptions, and the steps that are error-prone. Then automate the one step you do most often.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 2-hour documentation session; automation of one step is a separate sprint.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;5-cross-session-project-memory-structured-tracking-to-avoid-context-loss&quot;&gt;5. Cross-session project memory — structured tracking to avoid context loss&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: When you have to ask &quot;do you remember this bash script?&quot;, or say &quot;I completely forgot what we were doing&quot; about an in-progress project (dorkat), you are paying a re-orientation tax at the start of every session. For a developer working across 9 projects simultaneously, this compounds quickly.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: On June 7th you asked me to help locate a Kubernetes script from a previous conversation. On June 6th you opened the dorkat project and said &quot;I completely forgot&quot; what was in progress, needing to read PLAN files to reconstruct context. Both cases were resolved successfully — but only because the artefacts existed (the script, the PLAN files). The pattern suggests the PLAN.md system you set up is working but not yet consistently used across all projects.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: At the &lt;em&gt;close&lt;&#x2F;em&gt; of each session (not just at the start), write one sentence to the PLAN.md or TODO.txt of the project you were in: &quot;Stopped here: [what you were doing] — next step is [X].&quot; Two minutes at session end saves fifteen minutes at the next session start. The dorkat experience is the proof.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: A two-minute habit at each session close. The tooling (PLAN.md) already exists.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;strengths-observed&quot;&gt;Strengths Observed&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Breadth without shallow execution&lt;&#x2F;strong&gt;: Across nine projects in seven days, every deliverable was tested, committed properly, and reasoned through carefully. You do not ship half-measures.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Design intuition on domain modeling&lt;&#x2F;strong&gt;: When colleagues suggested &lt;code&gt;is_deleted&lt;&#x2F;code&gt;, you pushed back on the right grounds (&quot;one day None, another day a date, another day None again — not consistent enough&quot;) and defended the correct field semantics.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Meta-investment in tooling&lt;&#x2F;strong&gt;: Spending time fixing the test-stub skill, refining CLAUDE.md, and adding the plan-track system shows awareness that developer workflows compound. Engineers who ignore this debt become slower over time; you are going the other way.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;action-items&quot;&gt;Action Items&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Write one test using a real assertion (no placeholder) &lt;em&gt;before&lt;&#x2F;em&gt; touching an implementation file — do it for the next function you add anywhere. Confirm red with &lt;code&gt;pytest -k&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Add &lt;code&gt;django-security-hunter&lt;&#x2F;code&gt; to one project&#x27;s pre-commit or CI pipeline this week.&lt;&#x2F;li&gt;
&lt;li&gt;Write &lt;code&gt;RELEASE.md&lt;&#x2F;code&gt; for the analyses-service: document the current manual release steps in order, no automation yet.&lt;&#x2F;li&gt;
&lt;li&gt;At the end of today&#x27;s last coding session: write one sentence to the relevant PLAN.md — &quot;Stopped here: X, next step is Y.&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;learning-resources&quot;&gt;Learning Resources&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;django-orm-and-domain-layer&quot;&gt;Django ORM and domain layer&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=3952932&quot;&gt;Building a higher-level query API: the right way to use Django&#x27;s ORM&lt;&#x2F;a&gt; — Classic HN thread on &lt;code&gt;PassThroughManager&lt;&#x2F;code&gt; and composable querysets; directly relevant to the domain-logic-in-views problem you identified.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=41413641&quot;&gt;Taming the beast that is the Django ORM – An introduction&lt;&#x2F;a&gt; — More recent (2024) overview with emphasis on query optimisation patterns; good mental model for manager vs. queryset design.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45489347&quot;&gt;Django: One ORM to rule all databases&lt;&#x2F;a&gt; — HN discussion on ORM trade-offs; useful for understanding when to reach for raw SQL in migrations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;tdd-the-red-phase&quot;&gt;TDD — the red phase&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47119387&quot;&gt;Red&#x2F;Green TDD&lt;&#x2F;a&gt; — Recent HN thread (2026) directly on the red&#x2F;green cycle and what makes a red phase meaningful.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=32712909&quot;&gt;Ask HN: Seriously, how do you TDD?&lt;&#x2F;a&gt; — Practitioner answers on what TDD actually looks like in production codebases; useful for calibrating expectations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42317878&quot;&gt;Test Driven Development for your LLMs? Yes please&lt;&#x2F;a&gt; — Relevant for your Claude-assisted workflow specifically.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;security-built-into-workflow&quot;&gt;Security built into workflow&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=47719761&quot;&gt;Show HN: Django-security-hunter – Django security scanner CLI&lt;&#x2F;a&gt; — April 2026; the exact tool to wire into pre-commit for the JWT&#x2F;SECRET_KEY class of issues.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=34396443&quot;&gt;Authentication with Django and Single Page Apps&lt;&#x2F;a&gt; — HN discussion on JWT vs. session auth in Django; useful context for the log-scrubbing decisions you made.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;release-pipeline-design&quot;&gt;Release pipeline design&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42472384&quot;&gt;The CD Pipeline Manifesto&lt;&#x2F;a&gt; — Principled approach to continuous delivery; good framing for the develop → recette → production flow.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45613998&quot;&gt;Ask HN: How do you do CI&#x2F;CD in 2025?&lt;&#x2F;a&gt; — Practitioner answers from Oct 2025; useful for understanding what mature teams actually do vs. what the docs say.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=27447759&quot;&gt;Managing Databases in a CI&#x2F;CD pipeline is frankly difficult&lt;&#x2F;a&gt; — Directly addresses the &quot;sometimes manage.py migrate, sometimes raw SQL&quot; problem you have.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;cross-session-context-and-habits&quot;&gt;Cross-session context and habits&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=38149366&quot;&gt;Habits of great software engineers&lt;&#x2F;a&gt; — HN discussion with practitioner habits; the session-close note-writing habit is discussed in several comments.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42165057&quot;&gt;Good Software Development Habits&lt;&#x2F;a&gt; — Nov 2024 thread with concrete micro-habits; short read, high signal density.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Report covers engineering work sessions from 2026-06-01 to 2026-06-08.&lt;&#x2F;em&gt;
&lt;em&gt;Generated 2026-06-08.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Work Report — 2026-05-25 to 2026-06-08</title>
        <published>2026-06-08T00:00:00+00:00</published>
        <updated>2026-06-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/what-i-have-done/work-report-2026-06-08/"/>
        <id>https://nskm.xyz/what-i-have-done/work-report-2026-06-08/</id>
        
        <content type="html" xml:base="https://nskm.xyz/what-i-have-done/work-report-2026-06-08/">&lt;h1 id=&quot;work-report-2026-05-25-to-2026-06-08&quot;&gt;Work Report — 2026-05-25 to 2026-06-08&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Period&lt;&#x2F;strong&gt;: 2026-05-25 to 2026-06-08
&lt;strong&gt;Generated&lt;&#x2F;strong&gt;: 2026-06-08&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;The dominant theme of this period was security: a coordinated hardening sprint touched six backend services simultaneously, closing two separate credential-exposure vulnerabilities before they could be exploited. Alongside that, a soft-delete mechanism was delivered for clinical data models in two services, removing the risk of permanent accidental data loss during normal clinical workflows.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-was-delivered&quot;&gt;What Was Delivered&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-credential-exposure-fix-across-all-backend-services&quot;&gt;1. Credential-exposure fix across all backend services&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Authentication tokens and application secret keys can no longer leak into log files or be read from insecure environment configurations in any of the six core backend services (patient, notifications, organisations, consultation, analyses, biobank).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this fix, any engineer or administrator reading application logs — or any attacker who obtained log access — would have been able to extract valid user tokens and impersonate patients or clinicians on the platform. The insecure SECRET_KEY configuration additionally exposed every session cookie on the platform to forgery.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: A single coordinated branch was opened, the fix was applied and tested service by service, and six pull requests were merged on the same day to avoid a window where some services were patched and others were not.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-soft-delete-for-clinical-data-records-two-services&quot;&gt;2. Soft-delete for clinical data records (two services)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: When a clinician deletes a Suspected Disease entry or a Chronic Disease record, the record is deactivated rather than permanently erased, and can be restored if the deletion was a mistake.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this, a misclick during a consultation could have permanently destroyed clinical history with no recovery path. In a public-health surveillance context, a silently missing Suspected Disease record means an epidemiological alert may never be triggered.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: The feature required coordinated changes to the database model, query layer, API view, and reference data CSV files for four languages, plus migration scripts verified to be safe for existing rows. It was delivered for both the consultation service and the patient service within the same sprint.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-openapi-documentation-locked-behind-debug-flag-dashboard-service&quot;&gt;3. OpenAPI documentation locked behind debug flag (dashboard service)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The interactive API documentation interface (which lists every endpoint, parameter, and authentication scheme) is no longer publicly accessible on production deployments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;An exposed API schema hands an attacker a complete map of the system — every endpoint, every parameter, every authentication mechanism. On a production instance accessible from outside the local network, this would have dramatically reduced the time and skill required to find and exploit a vulnerability.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: A single targeted change; no functional behaviour was modified.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-docker-image-re-tagging-automation-tool&quot;&gt;4. Docker image re-tagging automation tool&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Operators can now re-tag a batch of Docker images (the packaged software containers used for deployment) across the private registry with a single command, with a confirmation step and a full success&#x2F;failure report at the end.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this, re-tagging images for a release was done manually, image by image. A missed image or a mistyped tag name during a production release directly causes a deployment failure or, worse, a silent rollback to an older version.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Delivered with a full test suite and executable shebang entry point. Skopeo (a remote registry inspection tool) is used to verify remotely that a tag does not already exist before any write operation is attempted.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;5-sql-migration-execution-script-hardened&quot;&gt;5. SQL migration execution script (hardened)&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Running database schema changes (SQL scripts that alter production database tables) is now a single command that validates inputs, stops immediately on the first failure, and reports exactly which scripts succeeded and which failed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without a fail-fast approach, a partially applied migration can leave the database in an inconsistent state that is extremely difficult to diagnose and roll back under pressure.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Rebuilt from an informal &quot;quick and dirty&quot; script into a production-grade tool, with argument validation, structured failure reporting, and support for passing a directory of ordered SQL files.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;6-user-guide-translation-completeness-and-rendering-quality&quot;&gt;6. User guide — translation completeness and rendering quality&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The platform&#x27;s user documentation is now fully translated into English, Spanish, and Portuguese in sync with the French source, and a verification script flags any future drift between language versions. PDF rendering quality for embedded screenshots was also improved.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;An outdated translation means field workers in non-French-speaking deployments operate from stale instructions — a patient safety risk if workflows have changed since the last update.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Covered the full document lifecycle: translation, image optimisation, PDF&#x2F;HTML rendering pipeline migration (switched to a single unified tool), and a Makefile target for automated translation-completeness checks.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-was-prevented&quot;&gt;What Was Prevented&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-token-theft-via-application-logs&quot;&gt;1. Token theft via application logs&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;If the JWT (authentication token) scrubbing had not been applied, the next time a developer or operations team member ran a log query — a routine daily activity — they would have been reading live authentication credentials. Any of those credentials could be replayed to authenticate as a real user.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: A security audit of the consultation service surfaced the pattern; it was then systematically searched for and removed across all six services in a single coordinated change.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-permanent-loss-of-clinical-records-due-to-missing-soft-delete&quot;&gt;2. Permanent loss of clinical records due to missing soft-delete&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;The Django REST Framework (the web API layer) default behaviour for a DELETE request is a hard database deletion. Before this sprint, a clinician accidentally pressing &quot;delete&quot; on a Suspected Disease record would have erased it from the database with no recovery path — and no alert.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Identified during a review of the API surface before a new feature was added on top of the same models.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-is-in-progress-and-why-it-takes-time&quot;&gt;What Is In Progress and Why It Takes Time&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-analyses-service-filter-consistency-between-display-and-export-endpoints&quot;&gt;1. Analyses service — filter consistency between display and export endpoints&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;&#x2F;strong&gt;: The filtered display endpoint and the CSV export endpoint for laboratory analyses currently apply different filter logic, meaning a user can see results on screen that are not present in the downloaded export.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why it cannot be rushed&lt;&#x2F;strong&gt;: The two endpoints were built independently and produce structurally different data (the export performs a pivot transformation and joins an external reference table). Aligning the filters without breaking either endpoint requires mapping the full data lineage for both paths before touching the code. A careless shortcut risks silently corrupting exported epidemiological data.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-consultation-microservice-domain-logic-centralisation&quot;&gt;2. Consultation microservice — domain logic centralisation&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;&#x2F;strong&gt;: Business logic (filtering, status checks, domain rules) is currently scattered across view files instead of being centralised in model or query-layer code. The work identifies which logic should move and where.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why it cannot be rushed&lt;&#x2F;strong&gt;: Moving logic from views to models in a live system requires verifying every call site. Missed call sites result in silent behavioural changes — the API appears to work but applies different rules than before.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Report covers git activity and engineering work sessions from 2026-05-25 to 2026-06-08.&lt;&#x2F;em&gt;
&lt;em&gt;Generated 2026-06-08.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>ITIL 4 Foundations</title>
        <published>2026-05-02T00:00:00+00:00</published>
        <updated>2026-05-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/itil-4/"/>
        <id>https://nskm.xyz/posts/itil-4/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/itil-4/">&lt;style&gt;
.it { border-collapse: collapse; width: 100%; margin: 1.2em 0; font-size: 0.88em; }
.it th, .it td { border: 1px solid #30363d; padding: 8px 13px; text-align: left; vertical-align: top; line-height: 1.5; }
.it thead th { background: #161b22; color: #388bfd; font-weight: 600; letter-spacing: 0.02em; }
.it tbody tr:nth-child(even) td { background: #0d111799; }
&lt;&#x2F;style&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;that-word.png&quot; alt=&quot;what?&quot; title=&quot;what?&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the author, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, or affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If you are a colleague and recognize the situation described below, remember: I&#x27;m critiquing the system, not the people.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Render unto Caesar what is Caesar&#x27;s: Claude helped me find up-to-date documentation links and helped beautify all the diagrams used (and not used) in this article.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article has been proofread by &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&#x2F;&quot;&gt;Mame Astou&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;Abdoul Karim&lt;&#x2F;a&gt;. Thank you both.
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;I tend to stay in my lane. Focus on what I understand, the perimeter I actually control. Everything beyond my code, my systems, my terminal &lt;em&gt;(the hierarchy, management, all the people I work with who don&#x27;t write programs)&lt;&#x2F;em&gt; has always been a blur to me. Vague, formless, abstract. Sometimes genuinely incomprehensible. Not because I think those people are wrong, but because whatever they do has always felt like noise I couldn&#x27;t parse.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll grudgingly admit, though: since joining this &lt;a href=&quot;https:&#x2F;&#x2F;institutpasteurdakar.sn&#x2F;&quot;&gt;biomedical research center&lt;&#x2F;a&gt;, everything that happens &lt;em&gt;outside&lt;&#x2F;em&gt; my direct work has become the most interesting part of the job. Humans are fascinating creatures to observe from a safe distance. Maybe it&#x27;s because my actual technical work is no longer the hardest thing on my plate. Or maybe because what happens in the corridors and meeting rooms has a direct, outsized impact on my work, on my &lt;a href=&quot;#&quot;&gt;freedom&lt;&#x2F;a&gt; to do that work the way I&#x27;d want to.&lt;&#x2F;p&gt;
&lt;p&gt;The hardest thing is collaborating with many other people, exchanging information in a way that everyone actually understands each other. Not just hears: understands. The hardest thing is listening, really listening to what others have to say, deeply, absorbing and retaining what they meant. Then responding, expressing yourself in a way that gets through, in a way that convinces. Making the right compromises, the right calls, and moving forward together, making sure everyone gets something of what they came for.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;Last Tuesday, I was enrolled in an &lt;strong&gt;ITIL 4 Foundations&lt;&#x2F;strong&gt; training organized by my hierarchy. The stated goals were clear: &lt;em&gt;garantir la disponibilité des systèmes&lt;&#x2F;em&gt; (ensure system availability), &lt;em&gt;structurer la gestion des incidents&lt;&#x2F;em&gt; (structure incident management), and &lt;em&gt;parler le même langage&lt;&#x2F;em&gt; (speak the same language). Perfectly reasonable goals.&lt;&#x2F;p&gt;
&lt;p&gt;In practice: sitting in a room while someone talks through concept after concept, deploying words and definitions at high velocity, is its own endurance sport. It&#x27;s made harder by the fact that some concepts I thought I already knew get redefined with vocabulary I would never have chosen — and some familiar words get used in ways that are subtly but persistently disorienting.&lt;&#x2F;p&gt;
&lt;p&gt;That said, I have to be honest: &lt;strong&gt;ITIL 4 is not the bureaucratic nightmare its reputation suggests&lt;&#x2F;strong&gt;. If anything, I realized I&#x27;d already been practicing most of these concepts; informally, imperfectly, without knowing there was a name for them. Done right, this is a coherent framework that actually acknowledges modern realities: Agile, DevOps, SRE, Lean.&lt;&#x2F;p&gt;
&lt;p&gt;Since I took notes anyway, might as well turn them into something useful. I hope you&#x27;ll learn something. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=mbf9aLD8E8M&quot;&gt;Music&lt;&#x2F;a&gt; \o&#x2F;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Companion piece&lt;&#x2F;strong&gt;: the same concepts, compressed into interactive diagrams, live in &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4-again&#x2F;&quot;&gt;ITIL 4... as fast as possible&lt;&#x2F;a&gt; — the picture book to this article&#x27;s textbook.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#what-is-itil-4&quot;&gt;What is itil 4?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#why-should-your-organization-care&quot;&gt;Why should your organization care?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-vocabulary&quot;&gt;The vocabulary&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#pestle-the-external-forces-you-cannot-control&quot;&gt;Pestle: external forces&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-big-picture-service-value-system-svs&quot;&gt;The service value system (svs)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#inside-the-svs-the-service-value-chain-svc&quot;&gt;The service value chain (svc)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-4-dimensions&quot;&gt;The 4 dimensions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-7-guiding-principles&quot;&gt;The 7 guiding principles&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#the-34-management-practices&quot;&gt;The 34 practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#incident-management&quot;&gt;Incident management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#problem-management&quot;&gt;Problem management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#service-request-management&quot;&gt;Service request management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#what-kind-of-ticket-is-this&quot;&gt;What kind of ticket is this?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#change-enablement&quot;&gt;Change enablement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#continual-improvement&quot;&gt;Continual improvement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#governance-and-risk-management&quot;&gt;Governance and risk management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#itil-4-agile-devops-lean&quot;&gt;ITIL 4 ↔ agile, devops, lean&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#case-study&quot;&gt;Case study&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#maturity-baseline&quot;&gt;Maturity baseline&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#tooling&quot;&gt;Tooling&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#where-does-this-break-down&quot;&gt;Where does this break down?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#itil-4-for-python-django-developers&quot;&gt;ITIL 4 for Python&#x2F;Django developers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#itil-v5&quot;&gt;ITIL v5&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;itil-4&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-itil-4&quot;&gt;What is ITIL 4?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.axelos.com&#x2F;certifications&#x2F;itil-service-management&quot;&gt;ITIL (Information Technology Infrastructure Library)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is a framework for IT Service Management (ITSM). It provides guidance on how organizations can use IT as a tool to facilitate business transformation and growth.&lt;&#x2F;p&gt;
&lt;p&gt;Key facts:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Origin&lt;&#x2F;strong&gt;: Developed in the 1980s by the UK government&#x27;s CCTA (Central Computer and Telecommunications Agency) to standardize IT practices across public services.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ITIL 4&lt;&#x2F;strong&gt; (released &lt;strong&gt;2019&lt;&#x2F;strong&gt;): The current version. A major rethink compared to ITIL v3, designed to integrate with modern approaches: Agile, DevOps, Lean, SRE.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Owner&lt;&#x2F;strong&gt;: Currently maintained by &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.peoplecert.org&#x2F;&quot;&gt;PeopleCert&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, which acquired AXELOS (the previous owner) in 2021.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Who uses it?&lt;&#x2F;strong&gt; Organizations of all sizes, across industries. Particularly common in banking, telecom, healthcare, public sector, and large IT departments.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;One thing ITIL 4 gets right that its predecessors didn&#x27;t: it explicitly acknowledges that &lt;strong&gt;you don&#x27;t need to implement all 34 practices&lt;&#x2F;strong&gt;. You pick what fits. This was not how earlier versions were often sold and it caused a lot of unnecessary process theater in organizations that implemented ITIL like a checkbox exercise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-should-your-organization-care&quot;&gt;Why should your organization care?&lt;&#x2F;h2&gt;
&lt;p&gt;During the training, an interesting observation was made about three organizational thresholds where ITIL practices start to become relevant:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Threshold&lt;&#x2F;th&gt;&lt;th&gt;Pain Point&lt;&#x2F;th&gt;&lt;th&gt;What Starts Breaking&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;≥ 5 people&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Memory loss&lt;&#x2F;td&gt;&lt;td&gt;Knowledge lives in people&#x27;s heads, not in runbooks&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;≥ 10 people&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Complexity&lt;&#x2F;td&gt;&lt;td&gt;Coordination overhead grows faster than the team&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;&amp;gt; 10 people&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Compliance&lt;&#x2F;td&gt;&lt;td&gt;Audits, regulations, and reporting requirements appear&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The practical implication: &lt;strong&gt;you don&#x27;t need all of ITIL&lt;&#x2F;strong&gt;. A 7-person startup building an internal tool doesn&#x27;t need a Change Advisory Board. A bank with 200 IT staff probably does. ITIL 4&#x27;s design philosophy is, understand the principles, apply the practices that solve your actual problems, and leave the rest on the shelf.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-vocabulary&quot;&gt;The vocabulary&lt;&#x2F;h2&gt;
&lt;p&gt;Before we can discuss the framework, we need to agree on definitions. ITIL has precise meanings for words we use casually.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;who-s-involved&quot;&gt;Who&#x27;s involved?&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Definition&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Organization&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A person or group with its own functions, responsibilities, and authorities&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Stakeholder&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any person with an interest in an organization, product, or service&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Provider&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;An organization that delivers services to consumers&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Consumer&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;An organization or individual that receives services&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Customer&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Defines requirements and owns the outcomes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;User&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The person who uses the service day-to-day&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Sponsor&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The person who authorizes the budget&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;In practice: the &lt;strong&gt;customer&lt;&#x2F;strong&gt; decides &lt;em&gt;what&lt;&#x2F;em&gt; they need, the &lt;strong&gt;user&lt;&#x2F;strong&gt; interacts with it daily, and the &lt;strong&gt;sponsor&lt;&#x2F;strong&gt; pays for it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-are-we-delivering&quot;&gt;What are we delivering?&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Definition&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Resource&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Any component used to deliver value: people, infrastructure, capital, information&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Product&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A configuration of resources designed to offer value to a consumer&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A means of enabling value co-creation by facilitating outcomes that customers want&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Offering&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A formal description of one or more services, designed for a target consumer group&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;the-value-equation&quot;&gt;The value equation&lt;&#x2F;h3&gt;
&lt;p&gt;This is arguably the most important concept in ITIL v4:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Value = Utility × Warranty&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Utility&lt;&#x2F;strong&gt;: What the service does — &lt;em&gt;fit for purpose&lt;&#x2F;em&gt;. Does it support the customer&#x27;s performance or remove a constraint?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Warranty&lt;&#x2F;strong&gt;: How reliably it does it — &lt;em&gt;fit for use&lt;&#x2F;em&gt;. Is it available when needed? Secure? Capable of handling the load?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A service that does the right thing but crashes every Monday morning has no value. A service that&#x27;s always available but solves the wrong problem also has no value. We need both, because a zero on either side collapses the product.&lt;&#x2F;p&gt;
&lt;p&gt;And value is &lt;strong&gt;subjective, contextual, and co-created&lt;&#x2F;strong&gt;. The provider alone cannot create value, it&#x27;s always produced in interaction with the customer. This shifts the conversation from &lt;em&gt;&quot;we delivered the system&quot;&lt;&#x2F;em&gt; to &lt;em&gt;&quot;did the customer actually get what they needed?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-actors-wrapper&quot;&gt;
&lt;style&gt;
.itil4-actors-wrapper {
    --bg:      #0d1117;
    --bg2:     #161b22;
    --bg3:     #21262d;
    --border:  #30363d;
    --text:    #e6edf3;
    --muted:   #8b949e;
    --blue:    #8296ab;
    --blue-d:  #64788f;
    --green:   #8fa98f;
    --purple:  #9b8fab;
    --orange:  #ab9179;
    --yellow:  #a89a70;
    font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
    background: var(--bg);
    color: var(--text);
    padding: 28px 20px 20px;
    margin: 30px 0;
}
.itil4-actors-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

.act-header { text-align: center; margin-bottom: 22px; }
.act-header h2 { font-size: 1.2rem; font-weight: 700; color: var(--blue); text-transform: uppercase; letter-spacing: 0.05em; }
.act-header p  { color: var(--muted); font-size: 0.8rem; margin-top: 5px; }

&#x2F;* ── 3-column main layout ── *&#x2F;
.act-main {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 12px;
    align-items: center;
}

&#x2F;* ── lane (provider &#x2F; consumer) ── *&#x2F;
.act-lane {
    border: 1px solid var(--border);
    overflow: hidden;
}
.act-lane-header {
    padding: 7px 12px;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    text-align: center;
}
.act-lane-header.provider { background: rgba(130,150,171,0.15); color: var(--blue); }
.act-lane-header.consumer { background: rgba(155,143,171,0.15); color: var(--purple); }
.act-lane-body { padding: 10px; display: flex; flex-direction: column; gap: 0; background: var(--bg2); }

&#x2F;* ── nodes ── *&#x2F;
.act-node {
    border: 1px solid var(--border);
    padding: 9px 12px;
    cursor: pointer;
    transition: border-color 0.15s, transform 0.1s;
    background: var(--bg3);
}
.act-node:hover  { border-color: var(--blue); transform: translateX(2px); }
.act-node.active { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(130,150,171,0.2); }
.act-node .nd-icon  { font-size: 1.1rem; }
.act-node .nd-name  { font-size: 0.78rem; font-weight: 700; color: var(--text); margin-top: 3px; }
.act-node .nd-role  { font-size: 0.68rem; color: var(--muted); margin-top: 2px; line-height: 1.4; }

&#x2F;* chain arrow between nodes in a lane *&#x2F;
.act-chain-arrow {
    text-align: center;
    color: var(--muted);
    font-size: 0.9rem;
    padding: 2px 0;
    line-height: 1;
}

&#x2F;* ── centre exchange column ── *&#x2F;
.act-exchange {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 110px;
    padding: 0 4px;
}

.act-flow-row {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: 0.7rem;
    color: var(--muted);
    white-space: nowrap;
}
.act-flow-arrow { font-size: 1rem; }
.act-flow-label { font-size: 0.65rem; color: var(--muted); text-align: center; }

.act-value-box {
    border: 1px solid var(--green);
    padding: 9px 10px;
    text-align: center;
    background: rgba(143,169,143,0.06);
    cursor: pointer;
    transition: border-color 0.15s;
}
.act-value-box:hover { border-color: #a3bda3; }
.act-value-box.active { box-shadow: 0 0 0 2px rgba(143,169,143,0.25); }
.act-value-box .vb-eq   { font-size: 0.8rem; font-weight: 700; color: var(--green); }
.act-value-box .vb-sub  { font-size: 0.65rem; color: var(--muted); margin-top: 3px; line-height: 1.4; }

.act-cocreate {
    font-size: 0.62rem;
    color: var(--muted);
    text-align: center;
    font-style: italic;
    padding: 0 4px;
}

&#x2F;* ── info panel ── *&#x2F;
.act-panel {
    margin-top: 16px;
    background: var(--bg3);
    border: 1px solid var(--border);
    padding: 14px 16px;
    font-size: 0.84rem;
    min-height: 72px;
}
.act-panel .ap-title { font-weight: 700; color: var(--blue); margin-bottom: 5px; font-size: 0.88rem; }
.act-panel .ap-desc  { color: var(--text); line-height: 1.6; }
.act-panel .ap-hint  { color: var(--muted); font-style: italic; font-size: 0.78rem; }
.act-panel .ap-tags  { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.act-panel .ap-tag   { font-size: 0.7rem; background: var(--bg2); border: 1px solid var(--border); padding: 2px 8px; color: var(--orange); }

@media (max-width: 580px) {
    .act-main { grid-template-columns: 1fr; }
    .act-exchange { flex-direction: row; flex-wrap: wrap; justify-content: center; min-width: unset; }
    .act-flow-row { font-size: 0.65rem; }
}
&lt;&#x2F;style&gt;

&lt;div class=&quot;act-header&quot;&gt;
    &lt;h2&gt;Who does what: for whom&lt;&#x2F;h2&gt;
    &lt;p&gt;Click any node to see its ITIL 4 definition&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;act-main&quot;&gt;

    &lt;!-- LEFT: Service Provider lane --&gt;
    &lt;div class=&quot;act-lane&quot;&gt;
        &lt;div class=&quot;act-lane-header provider&quot;&gt;Service Provider&lt;&#x2F;div&gt;
        &lt;div class=&quot;act-lane-body&quot;&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;resource&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;▦&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Resource&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Raw input to build with&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ assembles into&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;product&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;▣&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Product&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Configured for value delivery&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ packaged as&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;service&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;✦&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Service&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Enables consumer outcomes&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ described in&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;offering&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;▤&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Service Offering&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Formal promise to the consumer&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- CENTRE: exchange --&gt;
    &lt;div class=&quot;act-exchange&quot;&gt;
        &lt;div class=&quot;act-flow-row&quot;&gt;
            &lt;span class=&quot;act-flow-arrow&quot; style=&quot;color:#8296ab&quot;&gt;→&lt;&#x2F;span&gt;
            &lt;span class=&quot;act-flow-label&quot;&gt;delivers&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;act-value-box&quot; data-act=&quot;value&quot;&gt;
            &lt;div class=&quot;vb-eq&quot;&gt;Utility × Warranty&lt;&#x2F;div&gt;
            &lt;div class=&quot;vb-sub&quot;&gt;= Value&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;act-cocreate&quot;&gt;co-created&lt;br&gt;by both sides&lt;&#x2F;div&gt;

        &lt;div class=&quot;act-flow-row&quot;&gt;
            &lt;span class=&quot;act-flow-label&quot;&gt;requires&lt;&#x2F;span&gt;
            &lt;span class=&quot;act-flow-arrow&quot; style=&quot;color:#9b8fab&quot;&gt;←&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- RIGHT: Service Consumer lane --&gt;
    &lt;div class=&quot;act-lane&quot;&gt;
        &lt;div class=&quot;act-lane-header consumer&quot;&gt;Service Consumer&lt;&#x2F;div&gt;
        &lt;div class=&quot;act-lane-body&quot;&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;sponsor&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;¤&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Sponsor&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Authorizes the budget&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ funds&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;customer&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;◎&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Customer&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Defines requirements &amp;amp; owns outcomes&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ specifies for&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;user&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;○&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;User&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Uses the service day-to-day&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;act-chain-arrow&quot;&gt;↓ feeds back to&lt;&#x2F;div&gt;
            &lt;div class=&quot;act-node&quot; data-act=&quot;stakeholder&quot;&gt;
                &lt;span class=&quot;nd-icon&quot;&gt;⊕&lt;&#x2F;span&gt;
                &lt;div class=&quot;nd-name&quot;&gt;Stakeholder&lt;&#x2F;div&gt;
                &lt;div class=&quot;nd-role&quot;&gt;Any party with an interest&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;&#x2F;div&gt;&lt;!-- &#x2F;act-main --&gt;

&lt;div class=&quot;act-panel&quot; id=&quot;act-panel&quot;&gt;
    &lt;div class=&quot;ap-hint&quot;&gt;← Click any node to see its definition&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function () {
    const defs = {
        resource: {
            title: &quot;Resource&quot;,
            desc: &quot;Any component that can be used to deliver value: people, infrastructure, capital, information, or time. Resources are the raw inputs that the service provider assembles into something useful.&quot;,
            tags: [&quot;People&quot;, &quot;Infrastructure&quot;, &quot;Capital&quot;, &quot;Information&quot;]
        },
        product: {
            title: &quot;Product&quot;,
            desc: &quot;A configuration of resources designed to offer value to a consumer. A product is what the service provider builds. It may not be directly visible to the consumer, but it&#x27;s what the service is built on top of.&quot;,
            tags: [&quot;Configuration of resources&quot;, &quot;Provider-facing&quot;, &quot;Foundation of a service&quot;]
        },
        service: {
            title: &quot;Service&quot;,
            desc: &quot;A means of enabling value co-creation by facilitating outcomes that customers want to achieve, without the customer having to manage specific costs and risks. The key insight: value is not delivered, it is co-created.&quot;,
            tags: [&quot;Enables outcomes&quot;, &quot;Removes customer risk&quot;, &quot;Co-created with consumer&quot;]
        },
        offering: {
            title: &quot;Service Offering&quot;,
            desc: &quot;A formal description of one or more services, designed to address the needs of a target consumer group. It&#x27;s the official &#x27;promise&#x27; from provider to consumer: what&#x27;s included, what&#x27;s not, and at what terms.&quot;,
            tags: [&quot;Goods&quot;, &quot;Access to resources&quot;, &quot;Service actions&quot;, &quot;Terms &amp; conditions&quot;]
        },
        sponsor: {
            title: &quot;Sponsor&quot;,
            desc: &quot;The person who authorizes the budget for the consumption of a service. The sponsor may be the customer, or a separate person (e.g., a CFO who approves a service contract that the IT team actually uses).&quot;,
            tags: [&quot;Authorizes budget&quot;, &quot;May differ from Customer&quot;, &quot;Financial accountability&quot;]
        },
        customer: {
            title: &quot;Customer&quot;,
            desc: &quot;The person who defines the requirements for a service and takes responsibility for the outcomes of service consumption. The customer decides what is needed and judges whether the service delivered value.&quot;,
            tags: [&quot;Defines requirements&quot;, &quot;Owns outcomes&quot;, &quot;Negotiates SLAs&quot;, &quot;May also be Sponsor&quot;]
        },
        user: {
            title: &quot;User&quot;,
            desc: &quot;The person who uses services in their day-to-day work. Users interact directly with the service and often experience it differently from what the customer specified or the sponsor funded. This gap is why XLAs matter.&quot;,
            tags: [&quot;Day-to-day usage&quot;, &quot;Direct experience&quot;, &quot;Source of XLA signals&quot;, &quot;May differ from Customer&quot;]
        },
        stakeholder: {
            title: &quot;Stakeholder&quot;,
            desc: &quot;Any person who has an interest in an organization, product, service, practice, or other entity. Stakeholders include everyone on both sides: providers, consumers, regulators, partners, suppliers, and even the public in some contexts.&quot;,
            tags: [&quot;Broad category&quot;, &quot;Provider side&quot;, &quot;Consumer side&quot;, &quot;Regulators &amp; partners&quot;]
        },
        value: {
            title: &quot;Value = Utility × Warranty&quot;,
            desc: &quot;Value is subjective, contextual, and co-created. It cannot be delivered unilaterally by the provider. Utility is fitness for purpose (does the service do what the customer needs?). Warranty is fitness for use (is it available, secure, and reliable enough?). A zero on either factor collapses the value entirely.&quot;,
            tags: [&quot;Utility = fit for purpose&quot;, &quot;Warranty = fit for use&quot;, &quot;Co-created&quot;, &quot;Subjective &amp; contextual&quot;]
        }
    };

    const panel = document.getElementById(&#x27;act-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-actors-wrapper [data-act]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function () {
            const key = this.dataset.act;
            const d = defs[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-actors-wrapper [data-act]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tags = d.tags.map(t =&gt; `&lt;span class=&quot;ap-tag&quot;&gt;${t}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;ap-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ap-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;ap-tags&quot;&gt;${tags}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pestle-the-external-forces-you-cannot-control&quot;&gt;PESTLE: The external forces you cannot control&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4 acknowledges that organizations don&#x27;t operate in a vacuum. &lt;strong&gt;PESTLE analysis&lt;&#x2F;strong&gt; provides a structured lens for scanning the external environment:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Factor&lt;&#x2F;th&gt;&lt;th&gt;What It Covers&lt;&#x2F;th&gt;&lt;th&gt;IT Relevance&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Political&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Government policies, regulations&lt;&#x2F;td&gt;&lt;td&gt;Data sovereignty laws, public sector mandates&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Economic&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Budget cycles, cost pressures&lt;&#x2F;td&gt;&lt;td&gt;Cloud cost optimization, license negotiation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Social&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;User expectations, workforce trends&lt;&#x2F;td&gt;&lt;td&gt;Remote work adoption, digital literacy gaps&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Technological&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Emerging tech, vendor landscape&lt;&#x2F;td&gt;&lt;td&gt;AI integration, cloud migration, security threats&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Legal&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Compliance requirements&lt;&#x2F;td&gt;&lt;td&gt;GDPR, HIPAA, sector-specific regulations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Environmental&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sustainability, green IT&lt;&#x2F;td&gt;&lt;td&gt;Data center energy, hardware lifecycle&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;pestle.png&quot; alt=&quot;pestle&quot; title=&quot;pestle&quot;&#x2F;&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cipd.org&#x2F;en&#x2F;knowledge&#x2F;factsheets&#x2F;pestle-analysis-factsheet&#x2F;&quot;&gt;PESTLE&lt;&#x2F;a&gt; is not unique to ITIL, it&#x27;s a general strategic analysis tool. ITIL v4 borrows it because service management decisions are always made inside an organizational and environmental context. We never want to build a technically excellent system that doesn&#x27;t survive its first compliance audit or budget cut.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-big-picture-service-value-system-svs&quot;&gt;The big picture: Service Value System (SVS)&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;strong&gt;Service Value System (SVS)&lt;&#x2F;strong&gt; is ITIL v4&#x27;s model for how an organization creates value. Think of it as the engine diagram for your IT service operations.&lt;&#x2F;p&gt;
&lt;p&gt;It takes &lt;strong&gt;opportunities and demands&lt;&#x2F;strong&gt; as input, runs them through a system of governance, practices, and activities, and outputs &lt;strong&gt;value&lt;&#x2F;strong&gt; for all stakeholders.&lt;&#x2F;p&gt;
&lt;p&gt;The SVS is composed of five components:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Guiding Principles&lt;&#x2F;strong&gt; — universal recommendations that apply to all decisions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Governance&lt;&#x2F;strong&gt; — the framework for directing and controlling the organization&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Service Value Chain (SVC)&lt;&#x2F;strong&gt; — the set of interconnected activities that turn demand into value&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Management Practices&lt;&#x2F;strong&gt; — the 34 practices that provide organizational capability&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Continual Improvement&lt;&#x2F;strong&gt; — the persistent drive to improve everything&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;


&lt;div class=&quot;itil4-svs-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svs-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            --yellow: #a89a70;
            --red: #ab7d79;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 32px 20px;
            margin: 30px 0;
        }
        .itil4-svs-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svs-title-block {
            text-align: center;
            margin-bottom: 28px;
        }
        .svs-title-block h2 {
            font-size: 1.4rem;
            font-weight: 700;
            color: var(--blue);
            letter-spacing: 0.05em;
            text-transform: uppercase;
        }
        .svs-title-block p {
            color: var(--muted);
            font-size: 0.85rem;
            margin-top: 6px;
        }

        .svs-main-layout {
            display: flex;
            align-items: stretch;
            gap: 12px;
        }

        &#x2F;* --- Input&#x2F;Output columns --- *&#x2F;
        .svs-io {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            gap: 16px;
            min-width: 90px;
        }
        .svs-io-item {
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 12px 10px;
            text-align: center;
            font-size: 0.78rem;
            width: 90px;
        }
        .svs-io-item .io-icon { font-size: 1.4rem; display: block; margin-bottom: 4px; }
        .svs-io-item .io-label { color: var(--muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; }
        .svs-io-item .io-name { color: var(--text); font-weight: 600; margin-top: 2px; }

        .svs-arrow {
            color: var(--blue);
            font-size: 1.6rem;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0 4px;
        }

        &#x2F;* --- SVS box --- *&#x2F;
        .svs-box {
            flex: 1;
            border: 2px solid var(--blue-dim);
            padding: 16px;
            position: relative;
            background: var(--bg2);
        }

        .svs-guiding-label, .svs-ci-label {
            text-align: center;
            font-size: 0.72rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.08em;
            padding: 5px 0;
            margin-bottom: 10px;
        }
        .svs-guiding-label {
            color: var(--purple);
            border: 1px dashed var(--purple);
            opacity: 0.85;
        }
        .svs-ci-label {
            color: var(--green);
            border: 1px dashed var(--green);
            margin-top: 10px;
            margin-bottom: 0;
            opacity: 0.85;
        }

        .svs-inner-grid {
            display: grid;
            grid-template-columns: 1fr 2fr;
            gap: 10px;
            margin: 10px 0;
        }

        .svs-component {
            padding: 12px;
            cursor: pointer;
            transition: border-color 0.2s, transform 0.1s;
            border: 1px solid var(--border);
        }
        .svs-component:hover { border-color: var(--blue); transform: translateY(-1px); }
        .svs-component.active { border-color: var(--blue); box-shadow: 0 0 0 2px rgba(130,150,171,0.25); }

        .svs-component .comp-icon { font-size: 1.3rem; margin-bottom: 5px; }
        .svs-component .comp-name {
            font-size: 0.8rem;
            font-weight: 700;
            color: var(--text);
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .svs-component .comp-sub {
            font-size: 0.72rem;
            color: var(--muted);
            margin-top: 4px;
            line-height: 1.4;
        }

        .comp-governance { background: rgba(155,143,171,0.08); }
        .comp-svc { background: rgba(130,150,171,0.08); grid-row: 1 &#x2F; 3; }
        .comp-practices { background: rgba(171,145,121,0.08); }

        .svc-activities {
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            margin-top: 8px;
        }
        .svc-act {
            font-size: 0.68rem;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 2px 6px;
            color: var(--blue);
            font-weight: 500;
        }

        &#x2F;* --- Info panel --- *&#x2F;
        .svs-info-panel {
            margin-top: 20px;
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.85rem;
            min-height: 80px;
            transition: all 0.2s;
        }
        .svs-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            font-size: 0.9rem;
            margin-bottom: 6px;
        }
        .svs-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svs-info-panel .panel-hint {
            color: var(--muted);
            font-size: 0.78rem;
            font-style: italic;
        }
        .svs-info-panel .panel-items {
            display: flex;
            flex-wrap: wrap;
            gap: 6px;
            margin-top: 8px;
        }
        .svs-info-panel .panel-tag {
            font-size: 0.72rem;
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 2px 8px;
            color: var(--text);
        }

        .svs-legend {
            display: flex;
            flex-wrap: wrap;
            gap: 12px;
            margin-top: 16px;
            font-size: 0.75rem;
            color: var(--muted);
            justify-content: center;
        }
        .svs-legend-item { display: flex; align-items: center; gap: 5px; }
        .svs-legend-dot {
            width: 8px; height: 8px;
            display: inline-block;
        }

        @media (max-width: 600px) {
            .svs-main-layout { flex-direction: column; }
            .svs-arrow { transform: rotate(90deg); }
            .svs-inner-grid { grid-template-columns: 1fr; }
            .comp-svc { grid-row: auto; }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svs-title-block&quot;&gt;
        &lt;h2&gt;ITIL 4: Service Value System (SVS)&lt;&#x2F;h2&gt;
        &lt;p&gt;Click any component to learn more&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svs-main-layout&quot;&gt;
        &lt;!-- Inputs --&gt;
        &lt;div class=&quot;svs-io&quot;&gt;
            &lt;div class=&quot;svs-io-item&quot;&gt;
                &lt;span class=&quot;io-icon&quot;&gt;▹&lt;&#x2F;span&gt;
                &lt;div class=&quot;io-label&quot;&gt;Input&lt;&#x2F;div&gt;
                &lt;div class=&quot;io-name&quot;&gt;Opportunity&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
            &lt;div class=&quot;svs-io-item&quot;&gt;
                &lt;span class=&quot;io-icon&quot;&gt;▹&lt;&#x2F;span&gt;
                &lt;div class=&quot;io-label&quot;&gt;Input&lt;&#x2F;div&gt;
                &lt;div class=&quot;io-name&quot;&gt;Demand&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svs-arrow&quot;&gt;→&lt;&#x2F;div&gt;

        &lt;!-- SVS Box --&gt;
        &lt;div class=&quot;svs-box&quot;&gt;
            &lt;div class=&quot;svs-guiding-label&quot; data-svs=&quot;guiding&quot; style=&quot;cursor:pointer&quot;&gt;
                ✦ Guiding Principles: universally applicable ✦
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svs-inner-grid&quot;&gt;
                &lt;div class=&quot;svs-component comp-governance&quot; data-svs=&quot;governance&quot;&gt;
                    &lt;div class=&quot;comp-icon&quot;&gt;☰&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-name&quot;&gt;Governance&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-sub&quot;&gt;Direct · Evaluate · Monitor&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;

                &lt;div class=&quot;svs-component comp-svc&quot; data-svs=&quot;svc&quot;&gt;
                    &lt;div class=&quot;comp-icon&quot;&gt;⇉&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-name&quot;&gt;Service Value Chain&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-sub&quot;&gt;6 interconnected activities that convert demand into value&lt;&#x2F;div&gt;
                    &lt;div class=&quot;svc-activities&quot;&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Plan&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Engage&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Design &amp;amp; Transition&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Obtain &#x2F; Build&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Deliver &amp;amp; Support&lt;&#x2F;span&gt;
                        &lt;span class=&quot;svc-act&quot;&gt;Improve&lt;&#x2F;span&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;

                &lt;div class=&quot;svs-component comp-practices&quot; data-svs=&quot;practices&quot;&gt;
                    &lt;div class=&quot;comp-icon&quot;&gt;✱&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-name&quot;&gt;34 Practices&lt;&#x2F;div&gt;
                    &lt;div class=&quot;comp-sub&quot;&gt;General (14) · Service (17) · Technical (3)&lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;div class=&quot;svs-ci-label&quot; data-svs=&quot;ci&quot; style=&quot;cursor:pointer&quot;&gt;
                ↻ Continual Improvement: embedded at every level ↺
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;

        &lt;div class=&quot;svs-arrow&quot;&gt;→&lt;&#x2F;div&gt;

        &lt;!-- Output --&gt;
        &lt;div class=&quot;svs-io&quot;&gt;
            &lt;div class=&quot;svs-io-item&quot; style=&quot;width:90px&quot;&gt;
                &lt;span class=&quot;io-icon&quot;&gt;◆&lt;&#x2F;span&gt;
                &lt;div class=&quot;io-label&quot;&gt;Output&lt;&#x2F;div&gt;
                &lt;div class=&quot;io-name&quot;&gt;Value for all stakeholders&lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Info panel --&gt;
    &lt;div class=&quot;svs-info-panel&quot; id=&quot;svs-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click a component above to see its role in the SVS&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svs-legend&quot;&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#9b8fab&quot;&gt;&lt;&#x2F;span&gt; Guiding Principles&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#9b8fab; opacity:0.5&quot;&gt;&lt;&#x2F;span&gt; Governance&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#8296ab&quot;&gt;&lt;&#x2F;span&gt; Service Value Chain&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#ab9179&quot;&gt;&lt;&#x2F;span&gt; 34 Practices&lt;&#x2F;div&gt;
        &lt;div class=&quot;svs-legend-item&quot;&gt;&lt;span class=&quot;svs-legend-dot&quot; style=&quot;background:#8fa98f&quot;&gt;&lt;&#x2F;span&gt; Continual Improvement&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        guiding: {
            title: &quot;7 Guiding Principles&quot;,
            desc: &quot;Universal recommendations that guide organizations in all circumstances. Unlike practices or processes, they apply regardless of what you&#x27;re doing or where you are in the SVS. They cannot be overridden by management or policy.&quot;,
            items: [&quot;Focus on value&quot;, &quot;Start where you are&quot;, &quot;Progress iteratively with feedback&quot;, &quot;Collaborate and promote visibility&quot;, &quot;Think and work holistically&quot;, &quot;Keep it simple and practical&quot;, &quot;Optimize and automate&quot;]
        },
        governance: {
            title: &quot;Governance&quot;,
            desc: &quot;The framework by which an organization is directed and controlled. In the SVS, governance sits above everything else. It sets the direction and ensures accountability. Three core functions:&quot;,
            items: [&quot;Direct: set strategy, objectives, policies&quot;, &quot;Evaluate: assess performance, risk, compliance&quot;, &quot;Monitor: track adherence and verify outcomes&quot;]
        },
        svc: {
            title: &quot;Service Value Chain (SVC)&quot;,
            desc: &quot;The operational model at the heart of the SVS. Six activities that can be combined in different ways to create value streams: the specific sequences of steps for a given product or service. It is NOT linear: each value stream activates a different combination of activities.&quot;,
            items: [&quot;Plan: shared understanding of direction&quot;, &quot;Engage: stakeholder needs and relationships&quot;, &quot;Design &amp; Transition: meet stakeholder expectations&quot;, &quot;Obtain&#x2F;Build: components available when needed&quot;, &quot;Deliver &amp; Support: services per agreed specs&quot;, &quot;Improve: continual improvement across all services&quot;]
        },
        practices: {
            title: &quot;34 Management Practices&quot;,
            desc: &quot;Sets of organizational resources designed for performing work or accomplishing an objective. Organized into three categories. You do not need to implement all 34. Adopt what solves your actual problems.&quot;,
            items: [&quot;General Management (14): strategy, risk, knowledge, continual improvement...&quot;, &quot;Service Management (17): incident, change, service desk, problem...&quot;, &quot;Technical Management (3): deployment, infrastructure, software dev&quot;]
        },
        ci: {
            title: &quot;Continual Improvement&quot;,
            desc: &quot;A recurring practice embedded across the entire SVS, not just a step at the end. Every component, every practice, every activity should be subject to improvement. The Continual Improvement Register (CIR) tracks improvement ideas and their status.&quot;,
            items: [&quot;7-step model: vision → baseline → target → plan → act → measure → sustain&quot;, &quot;3 axes: strategic, tactical, operational&quot;, &quot;Tools: OKR, KPI, SLA, XLA, CIR&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svs-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svs-wrapper [data-svs]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.svs;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svs-wrapper [data-svs]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const tagsHtml = d.items.map(i =&gt; `&lt;span class=&quot;panel-tag&quot;&gt;${i}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-items&quot;&gt;${tagsHtml}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;NOTA BENE: &lt;strong&gt;Guiding Principles&lt;&#x2F;strong&gt; and &lt;strong&gt;Continual Improvement&lt;&#x2F;strong&gt; are not steps in a sequence. They&#x27;re a mindset that applies to all activities, at all times. You don&#x27;t &quot;do continual improvement&quot; after you&#x27;re done. You do it while you&#x27;re doing everything else.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inside-the-svs-the-service-value-chain-svc&quot;&gt;Inside the SVS: the Service Value Chain (SVC)&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;strong&gt;Service Value Chain&lt;&#x2F;strong&gt; is the operational model at the core of the SVS. It defines 6 activities that can be combined in different ways. The combination for a given service or request is called a &lt;strong&gt;value stream&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Activity&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Plan&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Shared understanding of vision, direction, and current state&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Engage&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Understand stakeholder needs; maintain transparency and relationships&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Design &amp;amp; Transition&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ensure products and services meet stakeholder expectations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Obtain &#x2F; Build&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ensure service components are available when and where needed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Deliver &amp;amp; Support&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Ensure services are delivered and supported per agreed specifications&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Improve&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Continual improvement across all products, services, and practices&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The SVC is &lt;strong&gt;not linear&lt;&#x2F;strong&gt;. An incident resolution primarily activates Engage, Deliver &amp;amp; Support, and Improve. A new service launch activates all six. A routine service request might only need Engage and Deliver &amp;amp; Support.&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-svc-wrapper&quot;&gt;
    &lt;style&gt;
        .itil4-svc-wrapper {
            --bg: #0d1117;
            --bg2: #161b22;
            --bg3: #21262d;
            --border: #30363d;
            --text: #e6edf3;
            --muted: #8b949e;
            --blue: #8296ab;
            --blue-dim: #64788f;
            --green: #8fa98f;
            --purple: #9b8fab;
            --orange: #ab9179;
            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--bg);
            color: var(--text);
            padding: 28px 20px;
            margin: 30px 0;
        }
        .itil4-svc-wrapper * { margin: 0; padding: 0; box-sizing: border-box; }

        .svc-header {
            text-align: center;
            margin-bottom: 24px;
        }
        .svc-header h2 {
            font-size: 1.3rem;
            font-weight: 700;
            color: var(--blue);
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }
        .svc-header p {
            color: var(--muted);
            font-size: 0.82rem;
            margin-top: 5px;
        }

        .svc-flow {
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            justify-content: center;
            gap: 6px;
            margin-bottom: 20px;
        }

        .svc-node {
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 10px 14px;
            cursor: pointer;
            text-align: center;
            min-width: 110px;
            transition: border-color 0.2s, transform 0.1s, background 0.2s;
        }
        .svc-node:hover { border-color: var(--blue); transform: translateY(-2px); }
        .svc-node.active { border-color: var(--blue); background: rgba(130,150,171,0.1); }
        .svc-node .node-icon { font-size: 1.3rem; display: block; margin-bottom: 4px; }
        .svc-node .node-name {
            font-size: 0.78rem;
            font-weight: 700;
            color: var(--text);
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .svc-node .node-sub {
            font-size: 0.68rem;
            color: var(--muted);
            margin-top: 3px;
        }

        .svc-connector {
            color: var(--blue-dim);
            font-size: 1.1rem;
            opacity: 0.7;
        }

        .svc-note {
            text-align: center;
            font-size: 0.75rem;
            color: var(--muted);
            margin-bottom: 16px;
            font-style: italic;
        }

        .svc-info-panel {
            background: var(--bg3);
            border: 1px solid var(--border);
            padding: 16px;
            font-size: 0.84rem;
            min-height: 70px;
        }
        .svc-info-panel .panel-title {
            font-weight: 700;
            color: var(--blue);
            margin-bottom: 5px;
        }
        .svc-info-panel .panel-desc { color: var(--text); line-height: 1.6; }
        .svc-info-panel .panel-hint { color: var(--muted); font-style: italic; font-size: 0.78rem; }
        .svc-info-panel .panel-examples {
            margin-top: 8px;
            font-size: 0.78rem;
            color: var(--muted);
        }
        .svc-info-panel .panel-examples span {
            background: var(--bg2);
            border: 1px solid var(--border);
            padding: 1px 7px;
            margin-right: 4px;
            display: inline-block;
            margin-top: 4px;
            color: var(--orange);
        }

        @media (max-width: 600px) {
            .svc-flow { flex-direction: column; }
            .svc-connector { transform: rotate(90deg); }
        }
    &lt;&#x2F;style&gt;

    &lt;div class=&quot;svc-header&quot;&gt;
        &lt;h2&gt;Service Value Chain (SVC)&lt;&#x2F;h2&gt;
        &lt;p&gt;Six interconnected activities, combined differently for each value stream&lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svc-flow&quot;&gt;
        &lt;div class=&quot;svc-node&quot; data-svc=&quot;plan&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;⌖&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Plan&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Direction &amp;amp; strategy&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;engage&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;⇄&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Engage&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Stakeholders &amp;amp; needs&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;design&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;◇&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Design &amp;amp; Transition&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Meet expectations&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;build&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;▲&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Obtain &#x2F; Build&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Components ready&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;deliver&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;▸&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Deliver &amp;amp; Support&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Run &amp;amp; resolve&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;svc-connector&quot;&gt;↔&lt;&#x2F;div&gt;

        &lt;div class=&quot;svc-node&quot; data-svc=&quot;improve&quot;&gt;
            &lt;span class=&quot;node-icon&quot;&gt;Δ&lt;&#x2F;span&gt;
            &lt;div class=&quot;node-name&quot;&gt;Improve&lt;&#x2F;div&gt;
            &lt;div class=&quot;node-sub&quot;&gt;Always, for everything&lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;div class=&quot;svc-note&quot;&gt;↔ Activities are non-linear: each service interaction combines them differently&lt;&#x2F;div&gt;

    &lt;div class=&quot;svc-info-panel&quot; id=&quot;svc-panel&quot;&gt;
        &lt;div class=&quot;panel-hint&quot;&gt;← Click an activity above to see what it covers&lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const info = {
        plan: {
            title: &quot;Plan&quot;,
            desc: &quot;Ensures a shared understanding of vision, current status, and direction for all four dimensions. Produces plans, policies, portfolios, and architectures used by all other activities.&quot;,
            examples: [&quot;Capacity planning&quot;, &quot;IT strategy&quot;, &quot;Risk register updates&quot;, &quot;Architecture decisions&quot;]
        },
        engage: {
            title: &quot;Engage&quot;,
            desc: &quot;Provides a good understanding of stakeholder needs, enables transparency, and maintains productive relationships. The primary contact point between the organization and its customers and users.&quot;,
            examples: [&quot;Service requests intake&quot;, &quot;User feedback collection&quot;, &quot;Customer communications&quot;, &quot;SLA negotiation&quot;]
        },
        design: {
            title: &quot;Design &amp; Transition&quot;,
            desc: &quot;Ensures products and services continually meet stakeholder expectations for quality, costs, and time-to-market. Includes design, testing, and transitioning services into live operation.&quot;,
            examples: [&quot;Service design documents&quot;, &quot;Test plans&quot;, &quot;Release planning&quot;, &quot;Training materials&quot;]
        },
        build: {
            title: &quot;Obtain &#x2F; Build&quot;,
            desc: &quot;Ensures service components are available when and where needed, meeting agreed specifications. Covers both acquiring from suppliers and building internally.&quot;,
            examples: [&quot;Software development&quot;, &quot;Infrastructure provisioning&quot;, &quot;Vendor procurement&quot;, &quot;Configuration of components&quot;]
        },
        deliver: {
            title: &quot;Deliver &amp; Support&quot;,
            desc: &quot;Ensures services are delivered and supported according to agreed specifications and stakeholder expectations. Day-to-day operations, incident management, and service fulfillment.&quot;,
            examples: [&quot;Incident resolution&quot;, &quot;Service desk operations&quot;, &quot;Monitoring &amp; alerting&quot;, &quot;Fulfilling service requests&quot;]
        },
        improve: {
            title: &quot;Improve&quot;,
            desc: &quot;Ensures continual improvement across all products, services, and practices. Works in parallel with all other activities. Every component of the SVS should be subject to improvement at all times.&quot;,
            examples: [&quot;Post-incident reviews&quot;, &quot;Performance trend analysis&quot;, &quot;Process optimization&quot;, &quot;Updating the CIR (Continual Improvement Register)&quot;]
        }
    };

    const panel = document.getElementById(&#x27;svc-panel&#x27;);

    document.querySelectorAll(&#x27;.itil4-svc-wrapper [data-svc]&#x27;).forEach(el =&gt; {
        el.addEventListener(&#x27;click&#x27;, function() {
            const key = this.dataset.svc;
            const d = info[key];
            if (!d) return;

            document.querySelectorAll(&#x27;.itil4-svc-wrapper [data-svc]&#x27;).forEach(e =&gt; e.classList.remove(&#x27;active&#x27;));
            this.classList.add(&#x27;active&#x27;);

            const examples = d.examples.map(e =&gt; `&lt;span&gt;${e}&lt;&#x2F;span&gt;`).join(&#x27;&#x27;);
            panel.innerHTML = `
                &lt;div class=&quot;panel-title&quot;&gt;${d.title}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-desc&quot;&gt;${d.desc}&lt;&#x2F;div&gt;
                &lt;div class=&quot;panel-examples&quot;&gt;${examples}&lt;&#x2F;div&gt;
            `;
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-4-dimensions&quot;&gt;The 4 dimensions&lt;&#x2F;h2&gt;
&lt;p&gt;Every component of the SVS should be considered from 4 perspectives. Ignoring any of them is one of the most reliable ways to make a project fail.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dimension&lt;&#x2F;th&gt;&lt;th&gt;What It Covers&lt;&#x2F;th&gt;&lt;th&gt;Classic Failure Mode&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Organizations and People&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Org structure, culture, roles, responsibilities&lt;&#x2F;td&gt;&lt;td&gt;&quot;We deployed the tool but nobody knows how to use it&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Information and Technology&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Data, knowledge, tools, infrastructure&lt;&#x2F;td&gt;&lt;td&gt;&quot;The system works but we can&#x27;t query the data we need&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Partners and Suppliers&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;External providers, contracts, integrations&lt;&#x2F;td&gt;&lt;td&gt;&quot;Our vendor went down and we had no fallback&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Value Streams and Processes&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;How work flows through the organization&lt;&#x2F;td&gt;&lt;td&gt;&quot;Everyone&#x27;s busy but nothing ships&quot;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;These 4 dimensions are interdependent. Migrating to a new monitoring tool (Information &amp;amp; Technology) means retraining people (Organizations &amp;amp; People), renegotiating vendor contracts (Partners &amp;amp; Suppliers), and redesigning on-call workflows (Value Streams &amp;amp; Processes).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-7-guiding-principles&quot;&gt;The 7 guiding principles&lt;&#x2F;h2&gt;
&lt;p&gt;These are universal principles that guide decision-making in any circumstance. They apply regardless of which practices you&#x27;re implementing.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Principle&lt;&#x2F;th&gt;&lt;th&gt;In one sentence&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;1. Focus on value&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Every action should trace back to a benefit for a stakeholder — if it doesn&#x27;t, stop.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;2. Start where you are&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Assess what already works before designing something new; don&#x27;t erase to rebuild.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;3. Progress iteratively with feedback&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Deliver in small increments, gather real feedback, then adjust — the same logic as Agile sprints.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;4. Collaborate and promote visibility&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Decisions made without the right people fail; make work visible and involve stakeholders early.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;5. Think and work holistically&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Services are systems; a change to one component will affect others — consider the whole, not just the part in front of you.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;6. Keep it simple and practical&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;If a process step adds no value, eliminate it; complexity is the enemy of reliability.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;7. Optimize and automate&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Fix the process first, then automate; automating a broken process gives you broken results faster.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;1. Focus on value&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Every activity should link back to value for stakeholders. Before starting anything, ask: who benefits, and how? If you can&#x27;t answer that, stop.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2. Start where you are&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Never ever assume you need to start from scratch. Assess what already works before designing something new. Most organizations already have something useful, the goal is to build on it, not erase it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;3. Progress iteratively with feedback&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Don&#x27;t try to design the perfect solution upfront. Deliver in small increments, gather feedback, adjust. This is the same philosophy behind Agile sprints and DevOps Continuous Delivery.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;4. Collaborate and promote visibility&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Work done in silos fails. Decisions made without the right people in the room fail. Make work visible: kanban boards, incident dashboards, change calendars; and involve stakeholders early, not at the end.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;5. Think and work holistically&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Services are systems. A change to one component can have unexpected effects elsewhere. Consider end-to-end impact, not just the piece in front of you. &lt;em&gt;Lol!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;6. Keep it simple and practical&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
If a process step doesn&#x27;t add value, eliminate it. If a tool creates more overhead than it saves, reconsider. Complexity is the enemy of reliability. Where I come from, we say &lt;strong&gt;&lt;em&gt;keep it simple and stupid&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;, see &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;KISS_principle&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;7. Optimize and automate&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
First, optimize the process (eliminate waste, reduce friction). Then, automate what remains. Automating a broken process gives you broken results, faster. The order matters.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-34-management-practices&quot;&gt;The 34 management practices&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4 defines &lt;strong&gt;34 practices&lt;&#x2F;strong&gt; designed for performing work or accomplishing an objective. They replace what ITIL v3 called &quot;processes&quot; (the shift reflects that a practice includes culture, tools, and knowledge, not just the steps).&lt;&#x2F;p&gt;
&lt;p&gt;They&#x27;re organized into 3 categories:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Category&lt;&#x2F;th&gt;&lt;th&gt;Count&lt;&#x2F;th&gt;&lt;th&gt;Examples&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;General management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;14&lt;&#x2F;td&gt;&lt;td&gt;Risk management, knowledge management, project management, continual improvement, organizational change management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;17&lt;&#x2F;td&gt;&lt;td&gt;Incident management, problem management, change enablement, service desk, service level management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Technical management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;Deployment management, infrastructure &amp;amp; platform management, software development &amp;amp; management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The full list of &lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;34-itil-4-management-practices&#x2F;&quot;&gt;34 ITIL 4 practices&lt;&#x2F;a&gt; exists for reference. No, you do not need to apply all 34 ITIL v4 practices. ITIL v4 is designed to be &lt;strong&gt;adopted and adapted&lt;&#x2F;strong&gt;. The core philosophy is to use &lt;strong&gt;only&lt;&#x2F;strong&gt; the practices that address your &lt;strong&gt;organization&#x27;s specific needs, pain points, and goals.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When you start, you need to identify your top 3 pain points (e.g., too many incidents, slow changes) to pick the right practices to implement first.&lt;&#x2F;p&gt;
&lt;p&gt;Here, we are almost starting from zero and we are already overwhelmed to the max. I would like to suggest 4 practices that, if we don&#x27;t have them, we&#x27;re operating blind:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;IT asset management        → What do we actually own?&lt;&#x2F;li&gt;
&lt;li&gt;Service request management → What are our users asking for?&lt;&#x2F;li&gt;
&lt;li&gt;Incident Management        → What is broken right now?&lt;&#x2F;li&gt;
&lt;li&gt;Change Enablement          → What is changing and why?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The 4 together cover the 4 basic operational questions any IT team needs answered at any moment. Everything else can be phased in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;incident-management&quot;&gt;Incident management&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Incident management&lt;&#x2F;strong&gt; is the practice responsible for managing the lifecycle of all incidents: unplanned interruptions or reductions in the quality of a service. Before we go further, let&#x27;s nail the vocabulary:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Term&lt;&#x2F;th&gt;&lt;th&gt;Definition&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A flaw in a component that could cause incidents&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Incident&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;An unplanned interruption or reduction in service quality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Problem&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The cause (known or unknown) of one or more incidents&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Known error&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;A problem that has been successfully analyzed, and a workaround or permanent solution has been identified&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Root Cause&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;The fundamental reason behind a problem&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;These are distinct. An &lt;strong&gt;incident&lt;&#x2F;strong&gt; is what you respond to at 2am. A &lt;strong&gt;problem&lt;&#x2F;strong&gt; is what you investigate to prevent the next one. Conflating them is how teams fix the same incident repeatedly without ever addressing what&#x27;s actually causing it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-7-step-incident-lifecycle&quot;&gt;The 7-Step incident lifecycle&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Identification&lt;&#x2F;strong&gt;: monitoring alert, user report, or support ticket&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Logging&lt;&#x2F;strong&gt;: full record: timestamp, description, affected service, reporter&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Categorization&lt;&#x2F;strong&gt;: what type of incident? which service&#x2F;component?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Prioritization&lt;&#x2F;strong&gt;: how urgent? how impactful?&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Diagnosis&lt;&#x2F;strong&gt;: initial investigation, probable cause&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Resolution&lt;&#x2F;strong&gt;: fix applied, service restored&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Closure&lt;&#x2F;strong&gt;: confirm resolution, document lessons, update knowledge base&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;incident-priority-matrix&quot;&gt;Incident Priority Matrix&lt;&#x2F;h3&gt;
&lt;p&gt;Priority is determined by &lt;strong&gt;Impact&lt;&#x2F;strong&gt; (how many users&#x2F;processes are affected) and &lt;strong&gt;Urgency&lt;&#x2F;strong&gt; (how quickly the business needs resolution). The matrix:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;High Urgency&lt;&#x2F;th&gt;&lt;th&gt;Medium Urgency&lt;&#x2F;th&gt;&lt;th&gt;Low Urgency&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;High Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;P1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P2&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Medium Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P2&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Low Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;td&gt;P3&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Trivial Impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;td&gt;P4&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;Priority codes (not to be confused with Biosafety Levels):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;P1 (Critical)&lt;&#x2F;strong&gt;: Production down, major business impact. Immediate response, all hands.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;P2 (High)&lt;&#x2F;strong&gt;: Significant service degradation. Fast response, escalation ready.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;P3 (Medium)&lt;&#x2F;strong&gt;: Partial impact, workaround available. Normal SLA response.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;P4 (Low)&lt;&#x2F;strong&gt;: Minimal impact, cosmetic or edge case. Can be scheduled.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;escalation&quot;&gt;Escalation&lt;&#x2F;h3&gt;
&lt;p&gt;The process within incident and service request management used to transfer issues to higher levels of authority or expertise when they cannot be resolved within normal, front-line support procedures.&lt;&#x2F;p&gt;
&lt;p&gt;When should we escalate ? When the incident exceed SLA timeframes, require higher expertise, or need more management authority.&lt;&#x2F;p&gt;
&lt;p&gt;There are 2 types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Functional escalation&lt;&#x2F;strong&gt;: pass to someone with more technical expertise&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Hierarchical escalation&lt;&#x2F;strong&gt;: involve management when impact warrants it or when SLA breach is imminent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A &lt;strong&gt;crisis&lt;&#x2F;strong&gt; is when an incident has business-wide consequences that require executive involvement. Knowing when a P1 becomes a crisis (and who to call) should be documented &lt;em&gt;before&lt;&#x2F;em&gt; the crisis, not during it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;problem-management&quot;&gt;Problem management&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Problem management&lt;&#x2F;strong&gt; is the practice responsible for managing the lifecycle of problems — the underlying causes of incidents. Where incident management asks &lt;em&gt;&quot;how do we restore service?&quot;&lt;&#x2F;em&gt;, problem management asks &lt;em&gt;&quot;why did this happen, and how do we prevent the next one?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The two practices are deliberately separate. Conflating them is one of the most reliable ways to spend your career fixing the same incident on a loop.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Mode&lt;&#x2F;th&gt;&lt;th&gt;Trigger&lt;&#x2F;th&gt;&lt;th&gt;Goal&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Reactive&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;After a significant incident or cluster of related incidents&lt;&#x2F;td&gt;&lt;td&gt;Find the root cause, document it, prevent recurrence&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Proactive&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pattern analysis, trend monitoring, or risk assessment — before incidents occur&lt;&#x2F;td&gt;&lt;td&gt;Eliminate problems before they cause service disruption&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;the-problem-lifecycle&quot;&gt;The problem lifecycle&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Detection&lt;&#x2F;strong&gt; — from incident trends, monitoring alerts, or staff observation&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Logging&lt;&#x2F;strong&gt; — create a problem record, link to related incident(s)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Categorization&lt;&#x2F;strong&gt; — which service? which component?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Prioritization&lt;&#x2F;strong&gt; — frequency × impact of the incidents it causes&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Investigation&lt;&#x2F;strong&gt; — root cause analysis (5 Whys, Fishbone diagram, timeline reconstruction)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Resolution&lt;&#x2F;strong&gt; — either a permanent fix (closes the problem) or a workaround (creates a &lt;em&gt;known error&lt;&#x2F;em&gt; record and keeps the problem open)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Closure&lt;&#x2F;strong&gt; — documented, linked to any changes raised to permanently fix it&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A &lt;strong&gt;known error&lt;&#x2F;strong&gt; is not a failure state. It means you&#x27;ve investigated, identified the root cause, and documented a workaround. Anyone who hits the same incident now resolves it in minutes instead of hours. The problem stays open until the permanent fix ships.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;root-cause-analysis-tools&quot;&gt;Root cause analysis tools&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;5 Whys&lt;&#x2F;strong&gt;: ask &quot;why?&quot; five times in sequence. Stop at the systemic cause, not the immediate trigger. &lt;em&gt;&quot;The server crashed&quot;&lt;&#x2F;em&gt; is an event. &lt;em&gt;&quot;The deployment process has no memory limit check&quot;&lt;&#x2F;em&gt; is a root cause.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Fishbone (Ishikawa) diagram&lt;&#x2F;strong&gt;: map contributing factors across categories (People, Process, Technology, Environment) to avoid anchoring on the first obvious suspect.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Timeline reconstruction&lt;&#x2F;strong&gt;: rebuild the sequence of events from logs, alerts, and operator notes. Frequently reveals that the &quot;incident&quot; started hours before anyone noticed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;service-request-management&quot;&gt;Service request management&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Service request management&lt;&#x2F;strong&gt; handles predefined, pre-approved requests from users. Nothing is broken (that&#x27;s an incident), and nothing unexpected is being modified in the IT environment (that&#x27;s change enablement). These are expected, routine interactions between users and the IT team.&lt;&#x2F;p&gt;
&lt;p&gt;Examples: new user account, software installation, password reset, access to a shared folder, equipment request.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-key-property-pre-approved&quot;&gt;The key property: pre-approved&lt;&#x2F;h3&gt;
&lt;p&gt;Every item in the service catalog has already been assessed for risk and policy compliance. When a user submits a service request, the IT team fulfills it — they don&#x27;t re-assess it. This is why the service catalog matters: without it, every request is treated as novel, lands in someone&#x27;s inbox, and creates invisible coordination overhead.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;&#x2F;th&gt;&lt;th&gt;Service Request&lt;&#x2F;th&gt;&lt;th&gt;Incident&lt;&#x2F;th&gt;&lt;th&gt;Change&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Trigger&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;User want or need&lt;&#x2F;td&gt;&lt;td&gt;Something broken, unplanned&lt;&#x2F;td&gt;&lt;td&gt;Planned modification&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Expected?&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Yes — predefined&lt;&#x2F;td&gt;&lt;td&gt;No — unplanned&lt;&#x2F;td&gt;&lt;td&gt;Yes — scheduled&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Authorization&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pre-approved via catalog&lt;&#x2F;td&gt;&lt;td&gt;None needed — respond immediately&lt;&#x2F;td&gt;&lt;td&gt;Required before action&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Goal&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Fulfill per SLA&lt;&#x2F;td&gt;&lt;td&gt;Restore service ASAP&lt;&#x2F;td&gt;&lt;td&gt;Implement safely with minimal disruption&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;the-automation-case&quot;&gt;The automation case&lt;&#x2F;h3&gt;
&lt;p&gt;Service requests represent the highest automation opportunity in the entire ITIL framework. If a request is genuinely predefined, low-risk, and repeatable, a human approving it manually every time is waste. Password resets, account provisioning, access to pre-approved groups — these can and should eventually be automated.&lt;&#x2F;p&gt;
&lt;p&gt;The path: design the process → document it → automate it. Automation without a clean process just speeds up a mess. This is guiding principle 7 applied directly: &lt;strong&gt;optimize first, then automate.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A mature service catalog has two properties: it is &lt;strong&gt;exhaustive&lt;&#x2F;strong&gt; (users can find everything IT actually offers) and &lt;strong&gt;increasingly self-service&lt;&#x2F;strong&gt; (as many requests as possible can be fulfilled without human intervention). Neither property is achieved on day one, but both should be the explicit direction of travel.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-kind-of-ticket-is-this&quot;&gt;What kind of ticket is this?&lt;&#x2F;h2&gt;
&lt;p&gt;In daily IT operations, the most common source of friction is not the absence of a practice — it is not knowing which practice applies. Is this broken thing an incident or a problem? Is this request a service request or a standard change?&lt;&#x2F;p&gt;


&lt;div class=&quot;itil4-tree-wrapper&quot;&gt;
&lt;style&gt;
.itil4-tree-wrapper {
    --bg:     #0d1117;
    --bg2:    #161b22;
    --bg3:    #21262d;
    --border: #30363d;
    --text:   #e6edf3;
    --muted:  #8b949e;
    --blue:   #8296ab;
    --green:  #8fa98f;
    --orange: #ab9179;
    --red:    #ab7d79;
    --yellow: #a89a70;
    --purple: #9b8fab;
    font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
    background: var(--bg);
    color: var(--text);
    padding: 28px 20px;
    margin: 30px 0;
}
.itil4-tree-wrapper * { box-sizing: border-box; margin: 0; padding: 0; }

.tree-header { text-align: center; margin-bottom: 22px; }
.tree-header h2 { font-size: 1.2rem; font-weight: 700; color: var(--blue); text-transform: uppercase; letter-spacing: 0.05em; }
.tree-header p  { color: var(--muted); font-size: 0.8rem; margin-top: 5px; }

.tree-breadcrumb {
    display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 14px;
    min-height: 24px;
}
.tree-crumb {
    font-size: 0.68rem; padding: 2px 8px;    border: 1px solid; white-space: nowrap;
}
.tree-crumb.yes { color: var(--green);  border-color: rgba(143,169,143,0.4);  background: rgba(143,169,143,0.07); }
.tree-crumb.no  { color: var(--orange); border-color: rgba(171,145,121,0.4); background: rgba(171,145,121,0.07); }

.tree-question {
    background: var(--bg2); border: 1px solid var(--border);    padding: 20px; margin-bottom: 14px;
}
.tree-q-step { font-size: 0.68rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px; }
.tree-q-text { font-size: 0.97rem; font-weight: 600; color: var(--text); line-height: 1.55; }

.tree-buttons { display: flex; gap: 10px; margin-bottom: 14px; }
.tree-btn {
    flex: 1; padding: 11px 16px; border: 1px solid;
    cursor: pointer; font-size: 0.85rem; font-weight: 700; letter-spacing: 0.02em;
    transition: opacity 0.15s, transform 0.1s; text-align: center; background: transparent;
    font-family: inherit;
}
.tree-btn:hover { opacity: 0.82; transform: translateY(-1px); }
.tree-btn.yes-btn { border-color: var(--green);  color: var(--green);  background: rgba(143,169,143,0.09); }
.tree-btn.no-btn  { border-color: var(--orange); color: var(--orange); background: rgba(171,145,121,0.09); }

.tree-result {
    background: var(--bg2); padding: 20px;
    margin-bottom: 14px; display: none;
}
.tree-result.show { display: block; }
.tree-result-badge {
    display: inline-block; padding: 3px 12px;    font-size: 0.7rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.07em; margin-bottom: 10px; border: 1px solid;
}
.tree-result-title { font-size: 1.05rem; font-weight: 700; color: var(--text); margin-bottom: 8px; }
.tree-result-desc  { font-size: 0.84rem; color: var(--muted); line-height: 1.6; margin-bottom: 10px; }
.tree-result-tags  { display: flex; flex-wrap: wrap; gap: 5px; }
.tree-result-tag {
    font-size: 0.7rem; background: var(--bg3); border: 1px solid var(--border);
 padding: 2px 8px; color: var(--orange);
}

.tree-restart {
    display: none; background: transparent; border: 1px solid var(--border);
 padding: 9px 20px; color: var(--muted); cursor: pointer;
    font-size: 0.8rem; width: 100%; transition: border-color 0.15s, color 0.15s;
    font-family: inherit;
}
.tree-restart.show { display: block; }
.tree-restart:hover { border-color: var(--blue); color: var(--blue); }
&lt;&#x2F;style&gt;

&lt;div class=&quot;tree-header&quot;&gt;
    &lt;h2&gt;What kind of ticket is this?&lt;&#x2F;h2&gt;
    &lt;p&gt;Answer each question to classify your request&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-breadcrumb&quot; id=&quot;itil-tree-crumbs&quot;&gt;&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-question&quot; id=&quot;itil-tree-question&quot;&gt;
    &lt;div class=&quot;tree-q-step&quot;  id=&quot;itil-tree-step&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-q-text&quot;  id=&quot;itil-tree-text&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-buttons&quot; id=&quot;itil-tree-btns&quot;&gt;
    &lt;button class=&quot;tree-btn yes-btn&quot; id=&quot;itil-tree-yes&quot;&gt;Yes&lt;&#x2F;button&gt;
    &lt;button class=&quot;tree-btn no-btn&quot;  id=&quot;itil-tree-no&quot;&gt;No&lt;&#x2F;button&gt;
&lt;&#x2F;div&gt;

&lt;div class=&quot;tree-result&quot; id=&quot;itil-tree-result&quot;&gt;
    &lt;div class=&quot;tree-result-badge&quot; id=&quot;itil-tree-badge&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-result-title&quot; id=&quot;itil-tree-rtitle&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-result-desc&quot;  id=&quot;itil-tree-rdesc&quot;&gt;&lt;&#x2F;div&gt;
    &lt;div class=&quot;tree-result-tags&quot;  id=&quot;itil-tree-rtags&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;button class=&quot;tree-restart&quot; id=&quot;itil-tree-restart&quot;&gt;↺ Start over&lt;&#x2F;button&gt;

&lt;script&gt;
(function () {
    var tree = {
        q1: {
            step: &quot;Question 1 of 4&quot;,
            text: &quot;Was this unplanned or unexpected, something that wasn&#x27;t meant to happen?&quot;,
            yes: &quot;q2a&quot;, no: &quot;q2b&quot;,
            crumb: &quot;Unplanned?&quot;
        },
        q2a: {
            step: &quot;Question 2 of 4&quot;,
            text: &quot;Is the service degraded or completely unavailable right now?&quot;,
            yes: &quot;incident&quot;, no: &quot;q3a&quot;,
            crumb: &quot;Service down?&quot;
        },
        q3a: {
            step: &quot;Question 3 of 4&quot;,
            text: &quot;Has the root cause already been identified and documented?&quot;,
            yes: &quot;known_error&quot;, no: &quot;problem&quot;,
            crumb: &quot;Root cause known?&quot;
        },
        q2b: {
            step: &quot;Question 2 of 4&quot;,
            text: &quot;Do you want to add, modify, or configure something in the IT environment?&quot;,
            yes: &quot;q3b&quot;, no: &quot;service_request&quot;,
            crumb: &quot;Modify IT?&quot;
        },
        q3b: {
            step: &quot;Question 3 of 4&quot;,
            text: &quot;Is this a predefined, well-understood, low-risk action with a documented procedure?&quot;,
            yes: &quot;std_change&quot;, no: &quot;q4b&quot;,
            crumb: &quot;Predefined &amp; low-risk?&quot;
        },
        q4b: {
            step: &quot;Question 4 of 4&quot;,
            text: &quot;Does this need to bypass the normal review cycle? Is it urgent enough to fast-track?&quot;,
            yes: &quot;emerg_change&quot;, no: &quot;normal_change&quot;,
            crumb: &quot;Urgent?&quot;
        }
    };

    var results = {
        incident: {
            color: &quot;#ab7d79&quot;,
            badge: &quot;Incident&quot;,
            title: &quot;Open an Incident ticket&quot;,
            desc: &quot;An unplanned interruption or reduction in service quality. Priority = Impact × Urgency. The immediate goal is service restoration. Root cause investigation comes later, via Problem Management.&quot;,
            tags: [&quot;Respond immediately&quot;, &quot;Prioritize by impact + urgency&quot;, &quot;Log timestamp + affected service&quot;, &quot;Escalate if P1&#x2F;P2&quot;]
        },
        problem: {
            color: &quot;#a89a70&quot;,
            badge: &quot;Problem&quot;,
            title: &quot;Open a Problem ticket&quot;,
            desc: &quot;The unknown or unconfirmed cause of one or more incidents. Not urgent in the incident sense (the service may be running), but it must be investigated to prevent the next occurrence.&quot;,
            tags: [&quot;Link to related incidents&quot;, &quot;Assign for root cause analysis&quot;, &quot;5 Whys or Fishbone&quot;, &quot;Track until permanent fix&quot;]
        },
        known_error: {
            color: &quot;#ab9179&quot;,
            badge: &quot;Known Error&quot;,
            title: &quot;Log a Known Error record&quot;,
            desc: &quot;Root cause is identified. Document the workaround in the known error database so any future recurrence is resolved in minutes. The problem stays open until the permanent fix ships.&quot;,
            tags: [&quot;Document the workaround&quot;, &quot;Link to parent problem&quot;, &quot;Open a Change to permanently fix&quot;, &quot;Notify support team&quot;]
        },
        service_request: {
            color: &quot;#8296ab&quot;,
            badge: &quot;Service Request&quot;,
            title: &quot;Submit a Service Request&quot;,
            desc: &quot;A predefined, pre-approved request for something in the service catalog. Nothing is broken; this is a routine interaction. Fulfillment follows a documented procedure: no new risk assessment needed.&quot;,
            tags: [&quot;Use the service catalog&quot;, &quot;SLA starts at submission&quot;, &quot;Should eventually be automated&quot;, &quot;Log for reporting&quot;]
        },
        std_change: {
            color: &quot;#8fa98f&quot;,
            badge: &quot;Standard Change&quot;,
            title: &quot;Execute as a Standard Change&quot;,
            desc: &quot;Pre-authorized, low-risk, documented procedure with a known outcome. No CAB review required. Follow the approved process and log the change for audit purposes.&quot;,
            tags: [&quot;Pre-authorized&quot;, &quot;Follow approved procedure&quot;, &quot;Log for audit trail&quot;, &quot;No CAB required&quot;]
        },
        normal_change: {
            color: &quot;#a89a70&quot;,
            badge: &quot;Normal Change&quot;,
            title: &quot;Submit an RFC for CAB review&quot;,
            desc: &quot;A change requiring risk assessment and authorization before implementation. Prepare an RFC with impact assessment, risk matrix, rollback plan, and communication plan. Awaits Change Authority review.&quot;,
            tags: [&quot;Submit RFC&quot;, &quot;Impact + risk assessment&quot;, &quot;Tested rollback plan required&quot;, &quot;CAB review before action&quot;]
        },
        emerg_change: {
            color: &quot;#ab7d79&quot;,
            badge: &quot;Emergency Change&quot;,
            title: &quot;Initiate Emergency Change process&quot;,
            desc: &quot;Fast-tracked through emergency authority because urgency outweighs normal review time. Speed does not mean no process: document, implement, then complete the post-implementation review.&quot;,
            tags: [&quot;Emergency authority required&quot;, &quot;Implement first, document in parallel&quot;, &quot;Post-implementation review mandatory&quot;, &quot;Notify all stakeholders&quot;]
        }
    };

    var state = &quot;q1&quot;;
    var crumbs = [];

    var elCrumbs  = document.getElementById(&#x27;itil-tree-crumbs&#x27;);
    var elQ       = document.getElementById(&#x27;itil-tree-question&#x27;);
    var elStep    = document.getElementById(&#x27;itil-tree-step&#x27;);
    var elText    = document.getElementById(&#x27;itil-tree-text&#x27;);
    var elBtns    = document.getElementById(&#x27;itil-tree-btns&#x27;);
    var elResult  = document.getElementById(&#x27;itil-tree-result&#x27;);
    var elBadge   = document.getElementById(&#x27;itil-tree-badge&#x27;);
    var elRTitle  = document.getElementById(&#x27;itil-tree-rtitle&#x27;);
    var elRDesc   = document.getElementById(&#x27;itil-tree-rdesc&#x27;);
    var elRTags   = document.getElementById(&#x27;itil-tree-rtags&#x27;);
    var elRestart = document.getElementById(&#x27;itil-tree-restart&#x27;);

    function renderCrumbs() {
        elCrumbs.innerHTML = crumbs.map(function(c) {
            return &#x27;&lt;span class=&quot;tree-crumb &#x27; + c.answer + &#x27;&quot;&gt;&#x27; + c.label + &#x27; → &#x27; + (c.answer === &#x27;yes&#x27; ? &#x27;Yes&#x27; : &#x27;No&#x27;) + &#x27;&lt;&#x2F;span&gt;&#x27;;
        }).join(&#x27;&#x27;);
    }

    function renderQuestion() {
        var node = tree[state];
        elStep.textContent = node.step;
        elText.textContent = node.text;
        elQ.style.display      = &#x27;block&#x27;;
        elBtns.style.display   = &#x27;flex&#x27;;
        elResult.classList.remove(&#x27;show&#x27;);
        elRestart.classList.remove(&#x27;show&#x27;);
        renderCrumbs();
    }

    function renderResult(key) {
        var r = results[key];
        elQ.style.display    = &#x27;none&#x27;;
        elBtns.style.display = &#x27;none&#x27;;

        elBadge.textContent = r.badge;
        elBadge.style.color      = r.color;
        elBadge.style.borderColor = r.color + &#x27;66&#x27;;
        elBadge.style.background  = r.color + &#x27;18&#x27;;

        elRTitle.textContent = r.title;
        elRDesc.textContent  = r.desc;
        elRTags.innerHTML    = r.tags.map(function(t) {
            return &#x27;&lt;span class=&quot;tree-result-tag&quot;&gt;&#x27; + t + &#x27;&lt;&#x2F;span&gt;&#x27;;
        }).join(&#x27;&#x27;);

        elResult.classList.add(&#x27;show&#x27;);
        elRestart.classList.add(&#x27;show&#x27;);
        renderCrumbs();
    }

    function answer(yes) {
        var node = tree[state];
        crumbs.push({ label: node.crumb, answer: yes ? &#x27;yes&#x27; : &#x27;no&#x27; });
        var next = yes ? node.yes : node.no;
        if (results[next]) {
            renderResult(next);
        } else {
            state = next;
            renderQuestion();
        }
    }

    document.getElementById(&#x27;itil-tree-yes&#x27;).addEventListener(&#x27;click&#x27;, function() { answer(true); });
    document.getElementById(&#x27;itil-tree-no&#x27;).addEventListener(&#x27;click&#x27;,  function() { answer(false); });
    document.getElementById(&#x27;itil-tree-restart&#x27;).addEventListener(&#x27;click&#x27;, function() {
        state = &quot;q1&quot;;
        crumbs = [];
        renderQuestion();
    });

    renderQuestion();
})();
&lt;&#x2F;script&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;change-enablement&quot;&gt;Change enablement&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Change Enablement&lt;&#x2F;strong&gt; manages the lifecycle of all changes to maximize the probability of success and minimize disruption.&lt;&#x2F;p&gt;
&lt;p&gt;ITIL v4 recognizes 3 change types:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Risk&lt;&#x2F;th&gt;&lt;th&gt;Authorization&lt;&#x2F;th&gt;&lt;th&gt;Examples&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Standard&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Low, well-understood&lt;&#x2F;td&gt;&lt;td&gt;Pre-authorized&lt;&#x2F;td&gt;&lt;td&gt;Antivirus update, user account creation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Normal&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable&lt;&#x2F;td&gt;&lt;td&gt;Change authority &#x2F; CAB review&lt;&#x2F;td&gt;&lt;td&gt;Application deployment, infrastructure change&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Emergency&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;High urgency&lt;&#x2F;td&gt;&lt;td&gt;Emergency authority (fast-track)&lt;&#x2F;td&gt;&lt;td&gt;Critical security patch, production hotfix&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;the-cab-change-advisory-board&quot;&gt;The CAB (Change Advisory Board)&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;strong&gt;CAB&lt;&#x2F;strong&gt; is a group that reviews and authorizes significant normal changes. Typical members: IT operations, security, business stakeholders, and the change owner. The CAB doesn&#x27;t exist to slow things down, it exists to catch problems before they become incidents. It is the organizational mechanism that &lt;em&gt;prevents the finance team from being unable to run payroll on a Friday.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A proper CAB dossier for a normal change includes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: which services, users, and systems are affected?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Risk&lt;&#x2F;strong&gt;: what&#x27;s the probability of failure, and what&#x27;s the impact if it fails?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rollback plan&lt;&#x2F;strong&gt;: how do we revert cleanly if the change fails? (Tested rollback, not theoretical)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Post-implementation review&lt;&#x2F;strong&gt;: how do we verify success after deployment?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;continual-improvement&quot;&gt;Continual improvement&lt;&#x2F;h2&gt;
&lt;p&gt;Continual improvement is both a guiding principle and a dedicated practice in ITIL 4. It ensures the organization continuously improves its services, practices, and the SVS itself.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;Continual Improvement Register (CIR)&lt;&#x2F;strong&gt; is the operational tool: a log of all improvement ideas, their status, priority, and outcomes. Think of it as a backlog specifically for operational improvements, not features, not incidents, but &lt;em&gt;how we work&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-7-step-improvement-model&quot;&gt;The 7-Step improvement model&lt;&#x2F;h3&gt;
&lt;p&gt;This model is cyclical by design. Reaching step 7 doesn&#x27;t mean you&#x27;re done, it means you start over with a new vision.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Question to Answer&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;1&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;What is the vision?&lt;&#x2F;strong&gt; Align the improvement to business strategy&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;2&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Where are we now?&lt;&#x2F;strong&gt; Baseline assessment: metrics, maturity, current state&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Where do we want to be?&lt;&#x2F;strong&gt; Define target state and measurable success criteria&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;How do we get there?&lt;&#x2F;strong&gt; Build the improvement plan&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Take action.&lt;&#x2F;strong&gt; Execute iteratively&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;6&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;Did we get there?&lt;&#x2F;strong&gt; Measure against success criteria&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;7&lt;&#x2F;td&gt;&lt;td&gt;&lt;strong&gt;How do we keep the momentum?&lt;&#x2F;strong&gt; Embed the change, celebrate wins, start the cycle again&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;measuring-improvement-sla-vs-xla-and-beyond&quot;&gt;Measuring improvement: SLA vs XLA and beyond&lt;&#x2F;h3&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Metric&lt;&#x2F;th&gt;&lt;th&gt;What It Measures&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;KPI&lt;&#x2F;strong&gt; (Key Performance Indicator)&lt;&#x2F;td&gt;&lt;td&gt;Technical performance against defined targets&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;SLA&lt;&#x2F;strong&gt; (Service Level Agreement)&lt;&#x2F;td&gt;&lt;td&gt;Contractual service commitments (uptime, response times)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;OKR&lt;&#x2F;strong&gt; (Objective and Key Result)&lt;&#x2F;td&gt;&lt;td&gt;Strategic goal achievement across a period&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;XLA&lt;&#x2F;strong&gt; (Experience Level Agreement)&lt;&#x2F;td&gt;&lt;td&gt;User satisfaction and actual experience quality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;CIR&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Improvement pipeline health and throughput&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;SLA vs XLA&lt;&#x2F;strong&gt; deserves its own paragraph. An SLA measures &lt;em&gt;what the system does&lt;&#x2F;em&gt; (was uptime ≥ 99.9%?). An &lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;what-exactly-are-xlas-and-how-do-you-use-them&#x2F;&quot;&gt;XLA&lt;&#x2F;a&gt; measures &lt;em&gt;how the user felt about it&lt;&#x2F;em&gt;. You can meet every SLA and still have furious users, because the system was slow even within the threshold, or the error messages were unhelpful, or the support experience was frustrating. XLAs align IT metrics with actual business outcomes, not just technical compliance.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-axes-of-improvement&quot;&gt;3 Axes of improvement&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strategic&lt;&#x2F;strong&gt;: organization-wide, long-term (e.g., &lt;em&gt;&quot;reach 95% automated change deployment by end of year&quot;&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tactical&lt;&#x2F;strong&gt;: team&#x2F;process level, medium-term (e.g., &lt;em&gt;&quot;reduce MTTR on P1 incidents by 40% this quarter&quot;&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Operational&lt;&#x2F;strong&gt;: day-to-day (e.g., &lt;em&gt;&quot;update the incident categorization taxonomy this sprint&quot;&lt;&#x2F;em&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;governance-and-risk-management&quot;&gt;Governance and Risk Management&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Governance&lt;&#x2F;strong&gt; sits at the top of the SVS. It provides direction and ensures the organization stays aligned with its objectives and obligations. Three functions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Direct&lt;&#x2F;strong&gt;: Set strategy, policies, and organizational objectives&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Evaluate&lt;&#x2F;strong&gt;: Assess organizational performance, risks, and compliance&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Monitor&lt;&#x2F;strong&gt;: Track adherence to policies and verify outcomes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For service management, governance ensures that the SVS is accountable: decisions are traceable, risks are understood, and exceptions are handled systematically.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk Management&lt;&#x2F;strong&gt; in ITIL follows a straightforward formula:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Risk = Probability × Impact&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Three responses:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Mitigate&lt;&#x2F;strong&gt;: reduce probability or impact (implement redundancy, add monitoring, require peer review)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Transfer&lt;&#x2F;strong&gt;: shift the risk to another party (insurance, contractual SLAs with vendors, outsourcing)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Accept&lt;&#x2F;strong&gt;: acknowledge the risk and decide to live with it (for low probability, low impact scenarios)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Risk isn&#x27;t inherently bad. The problem is &lt;strong&gt;unacknowledged risk&lt;&#x2F;strong&gt;, for example: changes deployed without a risk assessment, dependencies unknown until they fail, vulnerabilities known but not documented. Risk management doesn&#x27;t eliminate uncertainty; it makes it visible and traceable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;itil-4-agile-devops-lean&quot;&gt;ITIL 4 ↔ Agile, DevOps, Lean&lt;&#x2F;h2&gt;
&lt;p&gt;One of the major improvements in ITIL v4 over its predecessors is the explicit integration with modern practices. The framework doesn&#x27;t compete with DevOps or Agile. It provides the governance layer that makes them sustainable at scale.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;ITIL 4 Concept&lt;&#x2F;th&gt;&lt;th&gt;Agile Equivalent&lt;&#x2F;th&gt;&lt;th&gt;DevOps Equivalent&lt;&#x2F;th&gt;&lt;th&gt;Lean Equivalent&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;Service Value System&lt;&#x2F;td&gt;&lt;td&gt;Product Delivery Flow&lt;&#x2F;td&gt;&lt;td&gt;CI&#x2F;CD Pipeline&lt;&#x2F;td&gt;&lt;td&gt;Value Stream&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Continual Improvement&lt;&#x2F;td&gt;&lt;td&gt;Sprint Retrospective&lt;&#x2F;td&gt;&lt;td&gt;Blameless Post-mortem&lt;&#x2F;td&gt;&lt;td&gt;Kaizen&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Change Enablement&lt;&#x2F;td&gt;&lt;td&gt;Sprint Planning&lt;&#x2F;td&gt;&lt;td&gt;Deployment Pipeline&lt;&#x2F;td&gt;&lt;td&gt;Flow Management&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Incident Management&lt;&#x2F;td&gt;&lt;td&gt;Bug Sprint&lt;&#x2F;td&gt;&lt;td&gt;Incident Response&lt;&#x2F;td&gt;&lt;td&gt;A3 Problem Solving&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Service Request&lt;&#x2F;td&gt;&lt;td&gt;Backlog Item&lt;&#x2F;td&gt;&lt;td&gt;Work Item&lt;&#x2F;td&gt;&lt;td&gt;Pull System&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;SLA &#x2F; XLA&lt;&#x2F;td&gt;&lt;td&gt;Definition of Done&lt;&#x2F;td&gt;&lt;td&gt;SLO &#x2F; SLI&lt;&#x2F;td&gt;&lt;td&gt;Quality Standards&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;CAB Review&lt;&#x2F;td&gt;&lt;td&gt;Sprint Review&lt;&#x2F;td&gt;&lt;td&gt;Deployment Gate&lt;&#x2F;td&gt;&lt;td&gt;Go&#x2F;No-Go Decision&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Problem Management&lt;&#x2F;td&gt;&lt;td&gt;Root Cause Analysis&lt;&#x2F;td&gt;&lt;td&gt;Post-mortem&lt;&#x2F;td&gt;&lt;td&gt;5 Whys&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Service Desk&lt;&#x2F;td&gt;&lt;td&gt;Product Owner (ops)&lt;&#x2F;td&gt;&lt;td&gt;L1&#x2F;L2 Support&lt;&#x2F;td&gt;&lt;td&gt;Andon Cord&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.axelos.com&#x2F;resource-hub&quot;&gt;official ITIL 4 and DevOps resources&lt;&#x2F;a&gt; make the integration case explicitly. The short version: &lt;strong&gt;ITIL handles governance and accountability; DevOps handles speed and flow. You need both.&lt;&#x2F;strong&gt; Speed without governance creates chaos. Governance without speed creates bureaucracy. ITIL v4 was redesigned precisely to not be the bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;case-study&quot;&gt;Case study&lt;&#x2F;h2&gt;
&lt;p&gt;Here is what ITIL v4 looks like applied to a real IT direction inside a biomedical research center in Senegal. Any resemblance to real persons, living or dead, is &lt;em&gt;purely coincidental.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;part-1-service-catalog&quot;&gt;Part 1 — Service catalog&lt;&#x2F;h3&gt;
&lt;p&gt;The official list of what the IT direction provides, to whom, under what terms. It is the operational contract between the IT team and the rest of the organization. Without it, users don&#x27;t know what to ask for, IT doesn&#x27;t know what they&#x27;re accountable for, and incidents pile up in a shared mailbox nobody consistently monitors.&lt;&#x2F;p&gt;
&lt;p&gt;Below: 5 services covering the majority of what a research institute IT direction actually handles day-to-day.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Service&lt;&#x2F;th&gt;
      &lt;th&gt;Description&lt;&#x2F;th&gt;
      &lt;th&gt;Channel&lt;&#x2F;th&gt;
      &lt;th&gt;SLA — Response &#x2F; Resolution&lt;&#x2F;th&gt;
      &lt;th&gt;Responsible&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;User account provisioning&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Creation, modification, or deactivation of accounts (Active Directory, email, VPN, application access). Covers onboarding and offboarding.&lt;&#x2F;td&gt;
      &lt;td&gt;ITSM ticketing portal &#x2F; HR workflow trigger&lt;&#x2F;td&gt;
      &lt;td&gt;4h &#x2F; 1 business day&lt;&#x2F;td&gt;
      &lt;td&gt;Sysadmin — Identity &amp;amp; Access team&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Workstation support&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Hardware diagnosis and repair, OS reinstall, peripheral setup (printers, scanners, external drives). On-site or remote via support session.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal — phone for P1&#x2F;P2 only&lt;&#x2F;td&gt;
      &lt;td&gt;P3: 4h &#x2F; 2 days &amp;mdash; P4: next business day &#x2F; 5 days&lt;&#x2F;td&gt;
      &lt;td&gt;IT Support technician&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Application support&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Functional support for lab and corporate applications: LIMS, ERP (finance, HR), syndromic surveillance platform, email (M365). Includes access requests and usage questions.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal, categorized by application&lt;&#x2F;td&gt;
      &lt;td&gt;P2: 2h &#x2F; 4h &amp;mdash; P3: 4h &#x2F; 1 day &amp;mdash; P4: 1 day &#x2F; 3 days&lt;&#x2F;td&gt;
      &lt;td&gt;Application owner + IT Operations&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;VPN &amp;amp; remote access&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Setup, configuration, and troubleshooting of remote access (VPN client, MFA token). Covers new setups for approved staff and incident resolution for existing connections.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal — escalation via phone if blocking remote work&lt;&#x2F;td&gt;
      &lt;td&gt;New setup: 1 day &#x2F; 2 days &amp;mdash; Incident: 2h &#x2F; 4h&lt;&#x2F;td&gt;
      &lt;td&gt;Network team&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Backup &amp;amp; data recovery&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;Scheduled backups of research data, institutional databases, and user file shares. Restore requests for accidental deletions or corruption. Covers file-level and full-system restores.&lt;&#x2F;td&gt;
      &lt;td&gt;Ticketing portal — critical restores via phone (P1&#x2F;P2)&lt;&#x2F;td&gt;
      &lt;td&gt;P1 restore: 1h acknowledged &#x2F; 4h RTO &amp;mdash; P3 file restore: 4h &#x2F; 1 day&lt;&#x2F;td&gt;
      &lt;td&gt;Sysadmin — Infrastructure team&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;part-2-rfc-cab-dossier-lims-major-version-upgrade&quot;&gt;Part 2 — RFC &amp;amp; CAB Dossier: LIMS major version upgrade&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;strong&gt;Request for Change (RFC)&lt;&#x2F;strong&gt; is the formal input to the Change Enablement practice. For a Normal or a Major change, it triggers a full CAB review before any action is taken. Here is what a complete dossier looks like.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt;: The institute uses a LIMS (Laboratory Information Management System) to track samples, tests, and results across all its labs. The vendor has released version 4.0, which drops support for the current version 3.x at end of year. The upgrade is not optional, but it touches sample data, active test runs, and integrations with the syndromic surveillance platform.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;rfc-identification&quot;&gt;RFC identification&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Field&lt;&#x2F;th&gt;&lt;th&gt;Value&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;RFC Number&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;RFC-2026-014&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Title&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;LIMS major version upgrade: v3.8 → v4.0&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Change type&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Normal — Major&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Requestor&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Head of IT Operations&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Application owner&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Director of Laboratory Services&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Submission date&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;2026-05-03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Requested deployment window&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;2026-05-23, Saturday 22:00 → Sunday 06:00 (WAT)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;CAB review date&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;2026-05-13&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h4 id=&quot;justification&quot;&gt;Justification&lt;&#x2F;h4&gt;
&lt;p&gt;The current LIMS v3.x reaches vendor end-of-life on 2026-12-31. After that date: no security patches, no bug fixes, no vendor support. Version 4.0 also introduces a native REST API required by the next release of the syndromic surveillance platform. This change is driven by compliance (security posture) and technical dependency (surveillance platform roadmap) simultaneously.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;impact-assessment&quot;&gt;Impact assessment&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dimension&lt;&#x2F;th&gt;&lt;th&gt;Details&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Systems affected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;LIMS application servers (lims-prod-01, lims-prod-02), LIMS PostgreSQL database (lims-db-01), integration bridge with surveillance platform&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Users affected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~65 lab technicians and researchers across 4 departments: Virology, Bacteriology, Epidemiology, Quality&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Business processes affected&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Sample reception, test assignment, result entry, result validation, report generation, QC workflows&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Downstream services&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Surveillance platform reads LIMS results via API — will operate in read-only degraded mode during the window&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Duration of impact&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;LIMS unavailable ~8 hours; all impact contained within the Saturday night window&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;Data at risk&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~120,000 sample records, 3 years of test history. No patient PII in LIMS (samples referenced by anonymous ID).&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;risk-assessment&quot;&gt;Risk assessment&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Risk&lt;&#x2F;th&gt;&lt;th&gt;Probability&lt;&#x2F;th&gt;&lt;th&gt;Impact&lt;&#x2F;th&gt;&lt;th&gt;Score&lt;&#x2F;th&gt;&lt;th&gt;Mitigation&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;DB migration script fails mid-run, leaving schema in inconsistent state&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;Critical&lt;&#x2F;td&gt;&lt;td&gt;🔴 High&lt;&#x2F;td&gt;&lt;td&gt;Full DB snapshot before migration; script tested 3× on staging with a copy of production data&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;v4.0 breaks custom report templates (Quality dept uses non-standard format)&lt;&#x2F;td&gt;&lt;td&gt;Medium&lt;&#x2F;td&gt;&lt;td&gt;Medium&lt;&#x2F;td&gt;&lt;td&gt;🟡 Medium&lt;&#x2F;td&gt;&lt;td&gt;All 12 templates validated on staging; Quality dept sign-off obtained before CAB submission&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Surveillance platform integration fails after API change&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;High&lt;&#x2F;td&gt;&lt;td&gt;🟡 Medium&lt;&#x2F;td&gt;&lt;td&gt;Integration tested on staging against v4.0 API; surveillance team on standby Sunday 00:30&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Deployment overruns window, runs into Monday lab opening at 07:30&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;High&lt;&#x2F;td&gt;&lt;td&gt;🟡 Medium&lt;&#x2F;td&gt;&lt;td&gt;Hard rollback decision point at 04:00 — if not complete by then, rollback regardless of progress&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;UI changes slow down lab technicians Monday morning&lt;&#x2F;td&gt;&lt;td&gt;Medium&lt;&#x2F;td&gt;&lt;td&gt;Low&lt;&#x2F;td&gt;&lt;td&gt;🟢 Low&lt;&#x2F;td&gt;&lt;td&gt;30-min walkthrough session Monday 08:00; quick reference card distributed Friday&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;implementation-plan&quot;&gt;Implementation plan&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Time (WAT)&lt;&#x2F;th&gt;&lt;th&gt;Step&lt;&#x2F;th&gt;&lt;th&gt;Responsible&lt;&#x2F;th&gt;&lt;th&gt;Checkpoint&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;Sat 21:30&lt;&#x2F;td&gt;&lt;td&gt;Pre-deployment checklist: verify backup completed, confirm no active test runs, notify on-call lab manager&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:00&lt;&#x2F;td&gt;&lt;td&gt;Put LIMS in maintenance mode (users see scheduled maintenance banner)&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:05&lt;&#x2F;td&gt;&lt;td&gt;Full PostgreSQL dump to backup server + verify checksum&lt;&#x2F;td&gt;&lt;td&gt;DBA&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:30&lt;&#x2F;td&gt;&lt;td&gt;Stop LIMS application services on both nodes&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 22:35&lt;&#x2F;td&gt;&lt;td&gt;Run database schema migration script (estimated: 45 min)&lt;&#x2F;td&gt;&lt;td&gt;DBA&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 23:20&lt;&#x2F;td&gt;&lt;td&gt;Deploy v4.0 application package on lims-prod-01 (primary node)&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sat 23:40&lt;&#x2F;td&gt;&lt;td&gt;Run automated smoke test suite against lims-prod-01&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 00:00&lt;&#x2F;td&gt;&lt;td&gt;Deploy v4.0 on lims-prod-02, verify cluster synchronization&lt;&#x2F;td&gt;&lt;td&gt;Sysadmin&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 00:30&lt;&#x2F;td&gt;&lt;td&gt;Test surveillance platform integration against new v4.0 API&lt;&#x2F;td&gt;&lt;td&gt;Surveillance team&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 01:00&lt;&#x2F;td&gt;&lt;td&gt;Manual validation by on-call lab manager: create test sample, enter result, generate report&lt;&#x2F;td&gt;&lt;td&gt;Lab manager&lt;&#x2F;td&gt;&lt;td&gt;✓ required to proceed&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 01:30&lt;&#x2F;td&gt;&lt;td&gt;Remove maintenance mode, monitor application logs for 30 min&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Sun 02:00&lt;&#x2F;td&gt;&lt;td&gt;Deployment declared successful — confirmation sent to all stakeholders&lt;&#x2F;td&gt;&lt;td&gt;IT Ops lead&lt;&#x2F;td&gt;&lt;td&gt;&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Hard rollback decision point: Sunday 04:00.&lt;&#x2F;strong&gt; If not complete and validated by then, rollback is initiated regardless of progress. No exceptions — the lab opens at 07:30.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;rollback-procedure&quot;&gt;Rollback procedure&lt;&#x2F;h4&gt;
&lt;p&gt;Triggered if: any required checkpoint fails and cannot be resolved within 30 minutes, OR the 04:00 hard deadline is reached.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Stop all LIMS application services on both nodes&lt;&#x2F;li&gt;
&lt;li&gt;Drop the migrated database: &lt;code&gt;dropdb lims_production&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Restore from the pre-migration dump: &lt;code&gt;pg_restore -d lims_production &#x2F;backup&#x2F;lims-premig-20260523.dump&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Verify integrity: compare row counts for &lt;code&gt;samples&lt;&#x2F;code&gt;, &lt;code&gt;tests&lt;&#x2F;code&gt;, &lt;code&gt;results&lt;&#x2F;code&gt; tables against the pre-migration snapshot&lt;&#x2F;li&gt;
&lt;li&gt;Redeploy the v3.8 package from artifact registry on both nodes&lt;&#x2F;li&gt;
&lt;li&gt;Restart application services, verify cluster health&lt;&#x2F;li&gt;
&lt;li&gt;Remove maintenance mode, run the same smoke test suite&lt;&#x2F;li&gt;
&lt;li&gt;Notify all stakeholders: rollback completed, root cause analysis scheduled Monday&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Estimated rollback duration: &lt;strong&gt;45 minutes.&lt;&#x2F;strong&gt; The 04:00 decision point leaves 2.5 hours of margin before lab opening.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;communication-plan&quot;&gt;Communication plan&lt;&#x2F;h4&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Audience&lt;&#x2F;th&gt;&lt;th&gt;Message&lt;&#x2F;th&gt;&lt;th&gt;When&lt;&#x2F;th&gt;&lt;th&gt;Channel&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;All LIMS users&lt;&#x2F;td&gt;&lt;td&gt;Scheduled maintenance — LIMS unavailable Saturday 22:00 → Sunday 06:00&lt;&#x2F;td&gt;&lt;td&gt;Friday 2026-05-22, 14:00&lt;&#x2F;td&gt;&lt;td&gt;Email + in-app banner&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Lab managers&lt;&#x2F;td&gt;&lt;td&gt;Upgrade rationale, v4.0 UI changes, quick reference card attached&lt;&#x2F;td&gt;&lt;td&gt;Friday 2026-05-22, 14:00&lt;&#x2F;td&gt;&lt;td&gt;Email&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;Surveillance team&lt;&#x2F;td&gt;&lt;td&gt;API changes summary, integration test results, standby request for Sunday 00:30&lt;&#x2F;td&gt;&lt;td&gt;Thursday 2026-05-21&lt;&#x2F;td&gt;&lt;td&gt;Direct message + ticket&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;All stakeholders&lt;&#x2F;td&gt;&lt;td&gt;Outcome (success or rollback) + next steps&lt;&#x2F;td&gt;&lt;td&gt;Sunday 2026-05-24, by 06:00&lt;&#x2F;td&gt;&lt;td&gt;Email&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;post-implementation-review&quot;&gt;Post-implementation review&lt;&#x2F;h4&gt;
&lt;p&gt;Scheduled: &lt;strong&gt;Monday 2026-05-25, 10:00&lt;&#x2F;strong&gt; &#x2F; 30 minutes. Attendees: IT Ops lead, application owner, one representative per affected lab department.&lt;&#x2F;p&gt;
&lt;p&gt;Agenda:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Did deployment complete within window? If not: what caused the overrun?&lt;&#x2F;li&gt;
&lt;li&gt;Were all required checkpoints met? Document any deviations or waivers.&lt;&#x2F;li&gt;
&lt;li&gt;User-reported issues since go-live (collected Monday morning, before the review)&lt;&#x2F;li&gt;
&lt;li&gt;Was rollback triggered? If yes: full root cause analysis before next major change&lt;&#x2F;li&gt;
&lt;li&gt;Were Application Support SLAs met during the post-go-live monitoring period?&lt;&#x2F;li&gt;
&lt;li&gt;Update the LIMS runbook with any new procedures discovered during the upgrade&lt;&#x2F;li&gt;
&lt;li&gt;Close RFC-2026-014 in the ITSM tool; status: &lt;em&gt;Successful&lt;&#x2F;em&gt; or &lt;em&gt;Successful with deviations&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The output feeds directly into the &lt;strong&gt;Continual Improvement Register&lt;&#x2F;strong&gt;: anything harder than expected, any gap in the rollback procedure, any user adoption friction; logged as improvement items before the next major change.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;maturity-baseline&quot;&gt;Maturity baseline&lt;&#x2F;h2&gt;
&lt;p&gt;Before selecting practices to implement, identify where your organization currently stands. The goal is not to jump to level 5 — it is to take the next step from wherever you are.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Level&lt;&#x2F;th&gt;&lt;th&gt;Name&lt;&#x2F;th&gt;&lt;th&gt;Characteristics&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;0&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Chaos&lt;&#x2F;td&gt;&lt;td&gt;No formal process. Knowledge lives in individuals. When the person who knows leaves, the knowledge goes with them. Incidents are resolved by whoever happens to be available.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;1&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Reactive&lt;&#x2F;td&gt;&lt;td&gt;Basic incident response exists but is informal. Some documentation. Recurring incidents get fixed but never investigated. No service catalog. Change management is ad hoc (&quot;heads up, deploying tonight&quot;).&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;2&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Repeatable&lt;&#x2F;td&gt;&lt;td&gt;A ticketing system exists and is actually used. Common incidents have runbooks. A change notification process exists, even if informal. Users know roughly how to request IT services.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;3&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Defined&lt;&#x2F;td&gt;&lt;td&gt;A formal service catalog with SLAs. Documented change process with a review step. Incident priorities are defined and applied consistently. Problem management exists — recurring incidents trigger investigations.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;4&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Managed&lt;&#x2F;td&gt;&lt;td&gt;SLAs actively tracked and reported. CIR reviewed on a regular cadence with improvements actually closed. XLAs measured alongside SLAs. Most standard service requests are automated. Change success rate is tracked.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;strong&gt;5&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Optimizing&lt;&#x2F;td&gt;&lt;td&gt;Continuous improvement is embedded in every practice. Automation covers the majority of standard changes and service requests. Post-incident reviews generate CIR items within 48 hours. The team spends more time improving than firefighting.&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;quick-self-assessment&quot;&gt;Quick self-assessment&lt;&#x2F;h3&gt;
&lt;p&gt;Answer each question — each &quot;yes&quot; adds one point:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Does every IT request, incident, and change go through a single tracked system — and does the team use it consistently?&lt;&#x2F;li&gt;
&lt;li&gt;Can any user in your organization find, in under 2 minutes, what IT offers and how to request it?&lt;&#x2F;li&gt;
&lt;li&gt;Is there a process by which the IT team communicates planned changes to affected users &lt;em&gt;before&lt;&#x2F;em&gt; they happen?&lt;&#x2F;li&gt;
&lt;li&gt;After a major incident, does the team systematically document what happened and what will prevent recurrence?&lt;&#x2F;li&gt;
&lt;li&gt;Is there a maintained list of known improvement items, reviewed at least monthly?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Score&lt;&#x2F;th&gt;&lt;th&gt;Level&lt;&#x2F;th&gt;&lt;th&gt;First action&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;0&lt;&#x2F;td&gt;&lt;td&gt;Level 0–1&lt;&#x2F;td&gt;&lt;td&gt;Implement a ticketing system and write down your 5 most common requests&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;1–2&lt;&#x2F;td&gt;&lt;td&gt;Level 1–2&lt;&#x2F;td&gt;&lt;td&gt;Make the basics consistent before adding new practices&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;3&lt;&#x2F;td&gt;&lt;td&gt;Level 2–3&lt;&#x2F;td&gt;&lt;td&gt;You have a foundation — add formal SLAs and a documented change process&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;4&lt;&#x2F;td&gt;&lt;td&gt;Level 3–4&lt;&#x2F;td&gt;&lt;td&gt;Start measuring; close the loop on improvement items&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;5&lt;&#x2F;td&gt;&lt;td&gt;Level 4–5&lt;&#x2F;td&gt;&lt;td&gt;Focus on automation and XLA measurement&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tooling&quot;&gt;Tooling&lt;&#x2F;h2&gt;
&lt;p&gt;No tool enforces ITIL by itself. The process has to exist first, the tool just reduces friction. That said, the right tooling makes the difference between a practice that lives on paper and one that teams actually follow.&lt;&#x2F;p&gt;
&lt;p&gt;A word on scope: &lt;strong&gt;ServiceNow&lt;&#x2F;strong&gt; is the de facto enterprise standard and covers nearly everything in the table below. It is also expensive, slow to configure, and overkill for most organizations below a few hundred IT staff.&lt;&#x2F;p&gt;
&lt;p&gt;The open source column below deserves serious consideration. &lt;strong&gt;GLPI&lt;&#x2F;strong&gt; in particular covers incident, change, CMDB, and knowledge management in a single self-hosted package.&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;&#x2F;th&gt;
      &lt;th&gt;ITSM Platform&lt;&#x2F;th&gt;
      &lt;th&gt;Incident Detection &amp; Alerting&lt;&#x2F;th&gt;
      &lt;th&gt;Incident Response&lt;&#x2F;th&gt;
      &lt;th&gt;Knowledge Management&lt;&#x2F;th&gt;
      &lt;th&gt;Change Tracking&lt;&#x2F;th&gt;
      &lt;th&gt;Continual Improvement&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Suggested tools&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;ServiceNow, Jira Service Management, Freshservice&lt;&#x2F;td&gt;
      &lt;td&gt;PagerDuty, OpsGenie, incident.io&lt;&#x2F;td&gt;
      &lt;td&gt;FireHydrant, Rootly&lt;&#x2F;td&gt;
      &lt;td&gt;Confluence, Notion, GitBook&lt;&#x2F;td&gt;
      &lt;td&gt;Jira, LinearB&lt;&#x2F;td&gt;
      &lt;td&gt;Sleuth, Datadog, LinearB&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Free &amp; open source&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.glpi-project.org&#x2F;&quot;&gt;GLPI&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.combodo.com&#x2F;itop&quot;&gt;iTop&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.znuny.org&#x2F;en&quot;&gt;Znuny&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;&quot;&gt;Prometheus + Alertmanager&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.zabbix.com&#x2F;&quot;&gt;Zabbix&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;—&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;js.wiki&#x2F;&quot;&gt;Wiki.js&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.getoutline.com&#x2F;&quot;&gt;Outline&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.bookstackapp.com&#x2F;&quot;&gt;BookStack&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;plane.so&#x2F;&quot;&gt;Plane&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;about.gitea.com&#x2F;&quot;&gt;Gitea&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
      &lt;td&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dora-team&#x2F;fourkeys&quot;&gt;Four Keys (Google)&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;If you&#x27;re under 50 staff, start with GLPI and Prometheus — everything else is optional.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-does-this-break-down&quot;&gt;Where does this break down?&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4&#x27;s reputation for bureaucratic theater doesn&#x27;t come from the framework itself — it comes from predictable patterns in how organizations implement it. Here are the failure modes that appear most often.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-cab-becomes-a-bottleneck-or-a-rubber-stamp&quot;&gt;The CAB becomes a bottleneck — or a rubber stamp&lt;&#x2F;h3&gt;
&lt;p&gt;The CAB fails in two symmetric ways:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bottleneck mode&lt;&#x2F;strong&gt;: every change, including routine low-risk ones that should be standard, gets queued for a weekly meeting nobody prioritizes. Teams start bypassing the process because it costs more than it saves. Shadow changes accumulate.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rubber stamp mode&lt;&#x2F;strong&gt;: the CAB meets, approves everything without real scrutiny, and provides no value beyond a compliance checkbox. Teams stop writing quality RFC dossiers because nothing ever gets challenged.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both paths lead to the same outcome: the CAB becomes theater rather than governance.&lt;&#x2F;p&gt;
&lt;p&gt;The fix is structural: ruthlessly classify standard changes and remove them from CAB scope entirely. The CAB should only review changes that genuinely require multi-stakeholder risk assessment. If your CAB is reviewing password resets, something went wrong in the classification step.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-continual-improvement-register-becomes-a-graveyard&quot;&gt;The Continual Improvement Register becomes a graveyard&lt;&#x2F;h3&gt;
&lt;p&gt;The CIR is a backlog of improvement items. In organizations that implement it but don&#x27;t maintain it, it becomes a list of things that were logged and then forgotten. Items accumulate, nobody assigns owners, nothing gets closed. Teams stop logging new items because they&#x27;ve learned nothing will happen anyway.&lt;&#x2F;p&gt;
&lt;p&gt;The CIR needs a review cadence — monthly minimum — and every item needs an owner and a target date. An improvement item without both is a wish, not a commitment. Treat the CIR like a product backlog: prioritize, assign, close.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sla-gaming&quot;&gt;SLA gaming&lt;&#x2F;h3&gt;
&lt;p&gt;SLAs create a metric. Metrics can be gamed. Common patterns:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Tickets closed prematurely to hit the response time target, then re-opened when the user escalates.&lt;&#x2F;li&gt;
&lt;li&gt;Tickets parked in &quot;pending user response&quot; status indefinitely to pause the SLA clock.&lt;&#x2F;li&gt;
&lt;li&gt;Categorization manipulation to assign a lower priority with a more comfortable deadline.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The result: SLA compliance looks good on the dashboard while user satisfaction is deteriorating. This is exactly the gap XLAs were designed to expose. If your SLA compliance is consistently high but users are visibly unhappy, check whether the metric is being measured honestly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;incident-and-problem-management-conflate&quot;&gt;Incident and problem management conflate&lt;&#x2F;h3&gt;
&lt;p&gt;The same incident gets resolved for the fourth time this month. Each resolution was logged. Each SLA was met. Nobody opened a problem ticket after the second occurrence. Root cause never investigated. The team is fully occupied fixing the same thing repeatedly — which is the opposite of continual improvement.&lt;&#x2F;p&gt;
&lt;p&gt;The fix is a threshold rule: any incident that recurs more than N times in a rolling period automatically generates a problem ticket. That threshold is a policy decision. Make it explicit, write it down, enforce it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tool-first-implementation&quot;&gt;Tool-first implementation&lt;&#x2F;h3&gt;
&lt;p&gt;An organization buys ServiceNow (or its equivalent), then tries to configure it to match existing informal processes. The tool enforces workflows. The workflows don&#x27;t match how people actually work. Adoption fails. The tool gets blamed.&lt;&#x2F;p&gt;
&lt;p&gt;The correct sequence: define the process → document it → configure the tool to support it. A tool reduces friction in a process that already works; it cannot substitute for the process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;itil-as-compliance-theater&quot;&gt;ITIL as compliance theater&lt;&#x2F;h3&gt;
&lt;p&gt;The organization implements ITIL because an audit requires it. Forms are filled out. Tickets are opened and closed on schedule. SLA reports are generated. Nobody reads them. The framework exists on paper while informal processes continue in parallel.&lt;&#x2F;p&gt;
&lt;p&gt;The diagnostic: if you can&#x27;t name three specific problems that ITIL practices solved in the last quarter, your implementation is theater. Pick one practice, one pain point, one measurable outcome. Get that working — visibly, demonstrably — and then add the next one.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;itil-4-for-python-django-developers&quot;&gt;ITIL 4 for Python&#x2F;Django developers&lt;&#x2F;h2&gt;
&lt;p&gt;If you write Django code daily, you&#x27;ve been doing service management without the vocabulary. ITIL names the disciplines you&#x27;re already practicing — informally, inconsistently, and often without the parts that matter most.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;django-migrations-normal-changes&quot;&gt;Django migrations = Normal Changes&lt;&#x2F;h3&gt;
&lt;p&gt;Every &lt;code&gt;python manage.py migrate&lt;&#x2F;code&gt; on production is a Normal Change. It touches persistent data, may be irreversible without preparation, and if it fails mid-run it can leave the schema in an inconsistent state. The RFC dossier for a non-trivial migration:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: which tables change? which queries might break?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Risk&lt;&#x2F;strong&gt;: additive (low), destructive (high), or data backfill (variable)?&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Rollback plan&lt;&#x2F;strong&gt;: &lt;code&gt;python manage.py migrate &amp;lt;app&amp;gt; &amp;lt;previous&amp;gt;&lt;&#x2F;code&gt; — tested on staging, not theoretical.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Post-implementation check&lt;&#x2F;strong&gt;: verify row counts, run smoke tests, watch error rate for 15 minutes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The developers who skip the staging rollback test are the ones who spend their Saturday recovering a production database.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;management-commands-standard-changes&quot;&gt;Management commands = Standard Changes&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;createsuperuser&lt;&#x2F;code&gt;, &lt;code&gt;collectstatic&lt;&#x2F;code&gt;, &lt;code&gt;clearsessions&lt;&#x2F;code&gt; — predefined, low-risk, documented. They belong in your service catalog as standard changes: run by following the procedure, log the run, no CAB review needed. The moment a management command touches financial data, research records, or performs an irreversible bulk operation, it graduates to a Normal Change and needs a dossier.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-ci-cd-pipeline-is-change-enablement-in-code&quot;&gt;The CI&#x2F;CD pipeline is Change Enablement in code&lt;&#x2F;h3&gt;
&lt;p&gt;Your GitHub Actions or GitLab CI pipeline is an automated CAB. Each stage is a checkpoint:&lt;&#x2F;p&gt;
&lt;table class=&quot;it&quot;&gt;
  &lt;thead&gt;&lt;tr&gt;&lt;th&gt;Pipeline stage&lt;&#x2F;th&gt;&lt;th&gt;ITIL equivalent&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;&lt;td&gt;&lt;code&gt;tests pass&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Warranty check — fit for use&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;code&gt;linting passes&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Quality gate — code health&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;code&gt;staging deploy OK&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pre-production validation&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;code&gt;smoke tests pass&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Rollback decision point&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;code&gt;production deploy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Go-live — start monitoring&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;A merge gate that requires all checks to pass is the automated equivalent of CAB approval for standard changes. You&#x27;ve been calling it &quot;CI&#x2F;CD.&quot; What ITIL adds: &lt;strong&gt;the rollback plan needs to be tested&lt;&#x2F;strong&gt;, not just written. A &lt;code&gt;git revert&lt;&#x2F;code&gt; is not a rollback plan if you&#x27;ve never run it against a production data snapshot.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sentry-structured-logging-incident-identification&quot;&gt;Sentry + structured logging = Incident identification&lt;&#x2F;h3&gt;
&lt;p&gt;The 7-step incident lifecycle starts with identification. In a Django application:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LOGGING&lt;&#x2F;code&gt; config with structured output → categorizable, searchable logs&lt;&#x2F;li&gt;
&lt;li&gt;Sentry alert → automated identification (lifecycle step 1)&lt;&#x2F;li&gt;
&lt;li&gt;Sentry error grouped by fingerprint → categorization (step 3)&lt;&#x2F;li&gt;
&lt;li&gt;Error rate + affected user count → prioritization (step 4)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;&#x2F;health&lt;&#x2F;code&gt; endpoint returning degraded → warranty failure visible to monitoring&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;code&gt;python manage.py check --deploy&lt;&#x2F;code&gt; is the pre-deployment checklist equivalent — it catches misconfigurations before they become incidents. Running it in CI is reasonable. Skipping it is how &lt;code&gt;DEBUG=True&lt;&#x2F;code&gt; ends up in production.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-postmortem-problem-management&quot;&gt;The postmortem = Problem management&lt;&#x2F;h3&gt;
&lt;p&gt;After a production incident: the service is restored, the incident is closed. Problem management starts now.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git log --since=&quot;48 hours ago&quot;&lt;&#x2F;code&gt; + deploy history — what changed before the incident?&lt;&#x2F;li&gt;
&lt;li&gt;Reconstruct the timeline from Sentry, structured logs, and deploy timestamps&lt;&#x2F;li&gt;
&lt;li&gt;Apply 5 Whys to the root cause — stop at the systemic failure, not the immediate trigger&lt;&#x2F;li&gt;
&lt;li&gt;Create a problem ticket with the root cause documented&lt;&#x2F;li&gt;
&lt;li&gt;If a workaround exists before the permanent fix ships, log a known error record&lt;&#x2F;li&gt;
&lt;li&gt;The permanent fix becomes a Normal Change with a rollback plan&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;A GitHub issue tagged &lt;code&gt;post-incident&lt;&#x2F;code&gt; with root cause, workaround, and fix plan is a perfectly adequate known error record. The tool doesn&#x27;t matter; the discipline does.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;value-utility-x-warranty-in-code&quot;&gt;Value = Utility × Warranty, in code&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Utility&lt;&#x2F;strong&gt; (fit for purpose): does the feature solve the actual user problem? Test coverage verifies your code does what you wrote. It cannot verify you wrote the right thing. Developers who never talk to users are building on assumptions they haven&#x27;t tested.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Warranty&lt;&#x2F;strong&gt; (fit for use): test coverage + CI pass + staging smoke test + error rate within SLO after deploy. A feature that works in CI and silently corrupts data in production has warranty = 0.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The developer temptation is to optimize for utility (shipping features) while treating warranty as someone else&#x27;s problem. ITIL&#x27;s value equation makes the trade-off explicit: both factors are required, and a zero on either side collapses the value entirely.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;itil-v5&quot;&gt;ITIL v5&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ve been taught during the training ITIL v5 was launched in february 2026. I tried to watch this &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8IxxdEgE_OE&quot;&gt;video&lt;&#x2F;a&gt; to have an overview of what is ITIL v5. The only thing I understood was: &quot;The new pace of changes today driven by &lt;a href=&quot;#&quot;&gt;cloud&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;ai&lt;&#x2F;a&gt;, digital products, experience-focused services, demand a new way of thinking.&quot; ITIL v5 answers that need. &lt;em&gt;Phew!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;ITIL v4 is a framework providing a &lt;strong&gt;vocabulary&lt;&#x2F;strong&gt; and a &lt;strong&gt;structure for conversations&lt;&#x2F;strong&gt; your organization was probably already having informally: &lt;em&gt;Who decides what gets changed? How do we prioritize when everything is on fire? How do we know we&#x27;re actually improving?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The most valuable takeaways from this training:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Value is co-created, not delivered.&lt;&#x2F;strong&gt; You can deploy perfect infrastructure and still fail if users can&#x27;t get value from it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;SLA ≠ user happiness&lt;&#x2F;strong&gt;. XLAs measure what actually matters to the business.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ITIL v4 and DevOps are complementary.&lt;&#x2F;strong&gt; ITIL provides the accountability layer that makes continuous delivery safe at organizational scale.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Adopt and adapt.&lt;&#x2F;strong&gt; Apply the practices that solve real problems, and leave the rest on the shelf until you need them.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If your systems go down and nobody knows who to call, what changed yesterday, or how long things have been broken, that&#x27;s not a technical problem. That&#x27;s a service management problem. ITIL v4 gives you the vocabulary to fix it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Congratulations, you made it to the end. If you enjoyed this, please &lt;em&gt;like, share &amp;amp; subscriiiibe&lt;&#x2F;em&gt;. You might also like my amazing post about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;AWS fundamentals&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;how I&#x27;m helping save lives in West Africa using free software&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This article is a summary of a three-day training course. Impossible to explore all the aspects of ITIL v4 in such a short post. Here are some useful links to lean more:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.peoplecert.org&#x2F;browse-certifications&#x2F;it-governance-and-service-management&#x2F;ITIL-1&quot;&gt;ITIL 4 official certification path&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;itil-guiding-principles&#x2F;&quot;&gt;ITIL 4 Guiding Principles explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;34-itil-4-management-practices&#x2F;&quot;&gt;34 ITIL 4 management practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itsm.tools&#x2F;what-exactly-are-xlas-and-how-do-you-use-them&#x2F;&quot;&gt;What are XLAs and how do you use them?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;itrevolution.com&#x2F;product&#x2F;the-phoenix-project&#x2F;&quot;&gt;The Phoenix project&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sc.edu&#x2F;about&#x2F;offices_and_divisions&#x2F;ehs&#x2F;research_and_laboratory_safety&#x2F;biological_safety&#x2F;biosafety_level_criteria&#x2F;&quot;&gt;Biosafety Levels&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even more:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gamingworks.nl&#x2F;business-simulations&#x2F;apollo-13&#x2F;&quot;&gt;Apollo 13 – An ITSM Case Experience (GamingWorks)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gamechanginginsight.com&#x2F;itil-in-play&quot;&gt;GameChangingInsight ITIL simulations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;d12.github.io&#x2F;itil-quiz&#x2F;&quot;&gt;ITIL v4 quiz (open source)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;purplegriffon.com&#x2F;quizzes&#x2F;itil-4-foundation-quiz-questions-and-answers&quot;&gt;Purple Griffon ITIL 4 quiz&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.careersmarter.com&#x2F;itil-4-foundation-exam-questions&#x2F;&quot;&gt;Career Smarter mock exam&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.processexam.com&#x2F;peoplecert&#x2F;peoplecert-itil-4-foundation-certification-exam-sample-questions&quot;&gt;PeopleCert official sample questions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.careersmarter.com&#x2F;itil-4-foundation-exam-questions&#x2F;&quot;&gt;Career Smarter mock exam&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Developer Growth Report — 2026-04-21</title>
        <published>2026-04-21T00:00:00+00:00</published>
        <updated>2026-04-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/developer-growth/developer-growth-2026-04-21/"/>
        <id>https://nskm.xyz/developer-growth/developer-growth-2026-04-21/</id>
        
        <content type="html" xml:base="https://nskm.xyz/developer-growth/developer-growth-2026-04-21/">&lt;h1 id=&quot;developer-growth-report&quot;&gt;Developer Growth Report&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Period&lt;&#x2F;strong&gt;: April 15–21, 2026
&lt;strong&gt;Generated&lt;&#x2F;strong&gt;: 2026-04-21&lt;&#x2F;p&gt;
&lt;h2 id=&quot;work-summary&quot;&gt;Work Summary&lt;&#x2F;h2&gt;
&lt;p&gt;This week split across three distinct areas. The largest chunk was engineering work: designing and beginning to implement Notification System V2 across the backend, building the &lt;code&gt;ipd-notification-client&lt;&#x2F;code&gt; shared library from scratch, and migrating several services. Alongside that ran a sustained investment in developer tooling — building two new Claude Code skills (&lt;code&gt;what-i-have-done&lt;&#x2F;code&gt;, &lt;code&gt;collect_conversations.py&lt;&#x2F;code&gt;), updating &lt;code&gt;CLAUDE.md&lt;&#x2F;code&gt; with a parallelism strategy, and investigating &lt;code&gt;mprocs&lt;&#x2F;code&gt; and GNU parallel for speeding up daily dev tasks. The third thread was technical communication: writing a blog post on Brook&#x27;s Law (&quot;Nine Mothers, One Baby&quot;) and building the &lt;code&gt;what-i-have-done&lt;&#x2F;code&gt; skill specifically to bridge the gap between engineering output and management understanding.&lt;&#x2F;p&gt;
&lt;p&gt;The pattern that stands out: you consistently invest time in &lt;em&gt;meta-work&lt;&#x2F;em&gt; — tooling, workflow, communication frameworks — not just feature delivery. This is a strong signal of engineering maturity. The gap this week is that several tools were researched and understood but not yet adopted in practice.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;improvement-areas&quot;&gt;Improvement Areas&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-parallelism-from-theory-to-practice&quot;&gt;1. Parallelism: from theory to practice&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: You spent time this week understanding GNU parallel, mprocs, and the distinction between shell parallelism and subagent parallelism. You even codified the rule in your CLAUDE.md. But there is no evidence yet of mprocs being configured or used in any project, and no GNU parallel invocation in your workflow.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: You asked about mprocs for running pytest, ruff, django checks, and pylint in parallel, confirmed it was a good idea, confirmed the &lt;code&gt;mprocs.yaml&lt;&#x2F;code&gt; could be committed to the repo — then the conversation ended. The knowledge is there; the implementation is not.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Create &lt;code&gt;mprocs.yaml&lt;&#x2F;code&gt; in one service (start with &lt;code&gt;analyses-service&lt;&#x2F;code&gt;) with four processes: &lt;code&gt;pytest&lt;&#x2F;code&gt;, &lt;code&gt;ruff check .&lt;&#x2F;code&gt;, &lt;code&gt;python manage.py check&lt;&#x2F;code&gt;, &lt;code&gt;python manage.py migrate --check&lt;&#x2F;code&gt;. Run it once. This converts research into muscle memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 30 minutes to set up, one week to form the habit.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-technical-writing-reducing-iteration-cycles&quot;&gt;2. Technical writing: reducing iteration cycles&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: You are actively investing in writing — a blog post, a management report skill, architecture documents. But the hook section of &quot;Nine Mothers, One Baby&quot; required three rewrites in the same session. That is a signal that the drafting process lacks structure, not that the ideas are weak.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: Three consecutive messages: &lt;em&gt;&quot;could you help me rephrase it in something cleaner?&quot;&lt;&#x2F;em&gt; — same request, same section, same session. The ideas were sound; the structure to get from idea to prose was missing.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Before drafting any section, write one sentence answering: &lt;em&gt;&quot;What do I want the reader to feel or believe after reading this?&quot;&lt;&#x2F;em&gt; Then write to that. It eliminates the back-and-forth because the target is explicit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: No time investment — just a habit change at the start of each writing block.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-strategic-positioning-in-the-llm-era&quot;&gt;3. Strategic positioning in the LLM era&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: You asked: &lt;em&gt;&quot;In 2026, what are the ways for a software engineer to stay relevant?&quot;&lt;&#x2F;em&gt; — then the conversation moved on. This is a question worth spending real time on, not leaving as a passing thought.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: The question was detailed and self-aware (mental models of large Django projects, feature implementation speed, PR reviews). You are already doing several of the right things: building meta-tooling, investing in domain knowledge (epidemiology surveillance systems), writing publicly, improving communication. But you haven&#x27;t articulated a &lt;em&gt;personal strategy&lt;&#x2F;em&gt; — just instincts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Write a one-page personal positioning document: what you are uniquely good at that an LLM cannot replicate (domain knowledge of epidemiological systems, multi-country context, Pasteur network relationships), and what skills you want to deepen over the next 12 months. Treat it like architecture documentation — a living doc, not a one-time exercise.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Two hours to write, revisited quarterly.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-skill-and-tool-inventory&quot;&gt;4. Skill and tool inventory&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Why it matters&lt;&#x2F;strong&gt;: You now have a growing library of custom Claude Code skills, scripts, and conventions (&lt;code&gt;smart-read&lt;&#x2F;code&gt;, &lt;code&gt;what-i-have-done&lt;&#x2F;code&gt;, &lt;code&gt;commit&lt;&#x2F;code&gt;, &lt;code&gt;collect_conversations.py&lt;&#x2F;code&gt;, &lt;code&gt;collect_git_activity.sh&lt;&#x2F;code&gt;, &lt;code&gt;CLAUDE.md&lt;&#x2F;code&gt; rules). This is valuable infrastructure — but it is undocumented as a whole. You discovered this yourself when you asked &lt;em&gt;&quot;is there a way to list available skills, commands, hooks?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I observed&lt;&#x2F;strong&gt;: Skills are spread across &lt;code&gt;~&#x2F;.claude&#x2F;skills&#x2F;&lt;&#x2F;code&gt;, scripts in &lt;code&gt;~&#x2F;.claude&#x2F;scripts&#x2F;&lt;&#x2F;code&gt;, and conventions in &lt;code&gt;CLAUDE.md&lt;&#x2F;code&gt;. There is no single place to see what you have, what each thing does, and when to reach for it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation&lt;&#x2F;strong&gt;: Add a &lt;code&gt;## My Tools&lt;&#x2F;code&gt; section to your global &lt;code&gt;CLAUDE.md&lt;&#x2F;code&gt; — a one-line description per skill and script, updated when you add something new. This also helps when onboarding colleagues to your workflow.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: 20 minutes now, 2 minutes per new tool going forward.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;strengths-observed&quot;&gt;Strengths Observed&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Architecture before code&lt;&#x2F;strong&gt;: Notification V2 went through multiple document revisions and a colleague review before a line of implementation was written. This prevents expensive rework and is a mark of engineering seniority.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Communication investment&lt;&#x2F;strong&gt;: Building tools to translate technical work for management (&lt;code&gt;what-i-have-done&lt;&#x2F;code&gt;) and writing publicly about engineering realities (Brook&#x27;s Law post) shows awareness that output alone is not enough — visibility and communication are force multipliers.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tooling ownership&lt;&#x2F;strong&gt;: You actively shape your own environment rather than accepting defaults. CLAUDE.md, custom skills, conversation scanners — this compounds over time.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;action-items&quot;&gt;Action Items&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;mprocs.yaml&lt;&#x2F;code&gt; in &lt;code&gt;analyses-service&lt;&#x2F;code&gt; with the four core Django dev checks — run it before end of this week.&lt;&#x2F;li&gt;
&lt;li&gt;Before the next writing session (blog or architecture doc), write the one-sentence target first.&lt;&#x2F;li&gt;
&lt;li&gt;Draft a one-page personal positioning document: domain strengths + 12-month skill priorities.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;learning-resources&quot;&gt;Learning Resources&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;parallelism-in-practice&quot;&gt;Parallelism in practice&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=31438807&quot;&gt;Show HN: Mprocs – TUI for controlling multiple processes in one terminal&lt;&#x2F;a&gt; — Original mprocs launch thread, good for setup patterns and real-world use cases from other devs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=44201276&quot;&gt;Mprocs written in Rust: Run multiple commands in parallel&lt;&#x2F;a&gt; — 2025 discussion, more recent usage patterns and comparison with alternatives.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;staying-relevant-in-the-llm-era&quot;&gt;Staying relevant in the LLM era&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42431103&quot;&gt;Ask HN: SWEs how do you future-proof your career in light of LLMs?&lt;&#x2F;a&gt; — High-signal thread. Domain expertise and system-level thinking cited repeatedly as the durable differentiator.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46409375&quot;&gt;Ask HN: By what percentage has AI changed your output as a software engineer?&lt;&#x2F;a&gt; — Concrete data points from practitioners; useful for calibrating expectations.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=46424233&quot;&gt;The future of software development is software developers&lt;&#x2F;a&gt; — Counter-narrative to replacement fear; argues for the orchestration&#x2F;judgment role.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;technical-writing&quot;&gt;Technical writing&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=42045477&quot;&gt;Blog Writing for Developers (2023)&lt;&#x2F;a&gt; — Practical advice on drafting, structure, and the value of writing for solidifying your own thinking.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=33370870&quot;&gt;How to communicate effectively as a developer&lt;&#x2F;a&gt; — Covers the &quot;assumed context&quot; problem directly: why engineers write for an audience that knows more than they do.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=32110690&quot;&gt;Technical Writing for Developers&lt;&#x2F;a&gt; — Introduces the Diataxis framework (tutorial &#x2F; how-to &#x2F; explanation &#x2F; reference) as a structure for any developer writing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Work Report — April 7 to April 21, 2026</title>
        <published>2026-04-21T00:00:00+00:00</published>
        <updated>2026-04-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/what-i-have-done/work-report-2026-04-21/"/>
        <id>https://nskm.xyz/what-i-have-done/work-report-2026-04-21/</id>
        
        <content type="html" xml:base="https://nskm.xyz/what-i-have-done/work-report-2026-04-21/">&lt;h1 id=&quot;work-report-april-7-to-april-21-2026&quot;&gt;Work Report — April 7 to April 21, 2026&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;strong&gt;Period&lt;&#x2F;strong&gt;: April 7–21, 2026
&lt;strong&gt;Generated&lt;&#x2F;strong&gt;: 2026-04-21&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;The dominant theme of this period was hardening: hardening how notifications are routed across services, hardening email delivery against a vendor platform change, and hardening the deployment pipeline across all six backend services. The single most important delivery was the shared notification library — without it, any future change to how alerts are formatted or routed would require six separate coordinated updates with no guarantee of consistency.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-was-delivered&quot;&gt;What Was Delivered&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-shared-notification-routing-library&quot;&gt;1. Shared notification routing library&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: A single, validated library now governs how all backend services send medical alerts — disease notifications, analysis results, patient updates — through the internal data pipeline (Kafka). Any service that needs to send a notification now calls one place instead of rolling its own logic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this, each of the six services had its own ad-hoc notification code. A change in notification format — or a bug in routing logic — would require six separate fixes. In a system that alerts field teams to epidemiological events, an inconsistent fix is as dangerous as no fix at all.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Built from scratch in one day (April 20), including data types, message envelope structure, input validation, and the public API. Speed was possible because the design had been agreed upon in advance with colleagues.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-email-delivery-hardened-against-a-vendor-platform-shutdown&quot;&gt;2. Email delivery hardened against a vendor platform shutdown&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: Both the analyses service and the notification service now send automated emails via Microsoft&#x27;s modern API, replacing a deprecated authentication method that Microsoft has permanently disabled for Microsoft 365 accounts.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Without this migration, all automated email delivery would have silently stopped — weekly arbovirus surveillance reports, analysis result notifications to field teams. There would be no error visible in our systems; emails would simply not arrive.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: The migration itself was straightforward; the hardening work (fixing draft emails left unsent in the mailbox, authentication failure handling, upload timeout recovery) required additional attention to failure modes that are invisible under normal conditions.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-next-generation-notification-system-foundation&quot;&gt;3. Next-generation notification system — foundation&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: A new, extensible notification architecture is now partially in place, capable of routing medical alerts through email, SMS, or push channels from a single place, with full context about the patient, sample, or epidemiological trigger attached.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;The current system handles notifications service by service with no shared standard. As the number of alert types grows, maintaining consistency across services becomes harder. Without a unified foundation, a missed alert in one service would require investigating six codebases to understand why.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: Design reviewed with colleagues before implementation began — a deliberate decision. The architecture document went through several iterations to ensure the routing model is correct before any code was written.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-weekly-arbovirus-surveillance-report-made-configurable&quot;&gt;4. Weekly arbovirus surveillance report made configurable&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The automated weekly report for arbovirus monitoring now supports flexible recipient targeting, custom date ranges, and bilingual content. Country teams can now receive tailored reports without requiring a code change or redeployment.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Previously the report was hardcoded. Adapting it for Sierra Leone vs. Togo required a developer to intervene. Any urgency around a specific country&#x27;s surveillance window would wait on engineering availability.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: One day of implementation, including internationalization of email content and recipient configuration via command-line parameters.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;5-dependency-tooling-standardised-across-all-six-services&quot;&gt;5. Dependency tooling standardised across all six services&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: All backend services now use the same modern package manager (uv), cutting environment setup from ~2 minutes to under 10 seconds and eliminating version drift between services.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Version drift between services — where the same library is pinned to different versions across codebases — has caused unexplained production failures in the past. A standardised toolchain closes this class of bug permanently.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Effort&lt;&#x2F;strong&gt;: One to two days per service, running in parallel across the week of April 12–16. Each migration required validating that all existing tests still passed.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;6-reusable-deployment-pipeline-templates&quot;&gt;6. Reusable deployment pipeline templates&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Impact&lt;&#x2F;strong&gt;: The continuous deployment configuration for all Django (our web framework) backend services is now consolidated in a shared library. Any new service adopts the full pipeline in one line.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Risk removed&lt;&#x2F;strong&gt;: &lt;em&gt;Previously, each service maintained its own copy of the pipeline configuration. Configuration drift between copies has caused silent differences in how services are tested and deployed — a risk that grows every time a service is updated independently.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-was-prevented&quot;&gt;What Was Prevented&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-silent-breakdown-of-all-automated-medical-notifications&quot;&gt;1. Silent breakdown of all automated medical notifications&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;Microsoft&#x27;s SMTP Basic Auth shutdown would have cut all automated email delivery with no visible error in our systems. Field teams would have stopped receiving surveillance reports without anyone knowing why.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Proactive migration based on the vendor&#x27;s advance deprecation notice, completed before the shutdown date.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-draft-emails-left-permanently-unsent&quot;&gt;2. Draft emails left permanently unsent&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;A specific failure mode caused emails to be composed and saved as drafts in the mailbox but never sent. For a medical surveillance system, a notification that appears sent but was not is worse than a visible error — there is no alert, no retry, no trace.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Identified during the email backend hardening work; fixed alongside the main migration.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;3-production-admin-backdoor&quot;&gt;3. Production admin backdoor&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;Development utility commands that create admin accounts and generate test data were present in all six production services. These commands have no legitimate use in a production environment and represent unnecessary attack surface.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Systematic audit across all services; removed in a coordinated cleanup on April 17.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;4-document-generation-crash-from-a-dependency-conflict&quot;&gt;4. Document generation crash from a dependency conflict&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What almost happened&lt;&#x2F;strong&gt;: &lt;em&gt;A library used to generate Word documents (laboratory reports sent to health centres) was silently broken by an upstream package version change. Affected reports would have failed to generate with no clear error message to the end user.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it was caught&lt;&#x2F;strong&gt;: Identified during routine dependency work; version pinned to restore stability while the upstream library is updated.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;what-is-in-progress-and-why-it-takes-time&quot;&gt;What Is In Progress and Why It Takes Time&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-notification-system-v2-full-routing-engine&quot;&gt;1. Notification System V2 — full routing engine&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;&#x2F;strong&gt;: The data models and application scaffolding are in place. The routing engine — channel selection, retry logic, delivery receipts — is the next phase.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why it cannot be rushed&lt;&#x2F;strong&gt;: The system carries patient identifiers, sample IDs, and epidemiological triggers. A routing bug could mean a missed alert reaching a field team too late. Each routing rule needs to be tested against real data shapes before being deployed.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;2-migrating-remaining-services-to-the-shared-notification-library&quot;&gt;2. Migrating remaining services to the shared notification library&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;What it is&lt;&#x2F;strong&gt;: The analyses service was connected to the new library on April 20. Five other services — patient records, organisations, consultation, bio bank, and forms — need the same migration.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why it cannot be rushed&lt;&#x2F;strong&gt;: Each service has existing notification behaviour that must be preserved exactly during the transition. Field teams must not receive duplicate or missing alerts because of how the migration was sequenced.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;Report covers git activity across 8 repositories and engineering work sessions from April 7–21, 2026.&lt;&#x2F;em&gt;
&lt;em&gt;Generated 2026-04-21.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>From rsync to CI&#x2F;CD: automating a static site deployment</title>
        <published>2026-03-05T00:00:00+00:00</published>
        <updated>2026-03-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/mvln2/"/>
        <id>https://nskm.xyz/posts/mvln2/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/mvln2/">&lt;img style=&quot;display: block; margin: 0 auto; width: 700px&quot; src=&quot;&#x2F;images&#x2F;praying_ci_god.jpeg&quot; alt=&quot;Praying the CI&#x2F;CD god&quot; title=&quot;Praying the CI&#x2F;CD god&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;&#x2F;h2&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Opinions&lt;&#x2F;strong&gt;: The views expressed here are my own unless otherwise specified. They do not represent any employer, organization, or affiliated group.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scope&lt;&#x2F;strong&gt;: This case study documents my personal journey automating a static Zola site. Your infrastructure needs may differ.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audience&lt;&#x2F;strong&gt;: This article assumes DevOps familiarity. You should be comfortable with Docker, shell scripts, git workflows, and Linux administration.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing environment&lt;&#x2F;strong&gt;: Everything in this article was tested on Ubuntu (WSL2 on Windows) running locally, and deployed to the cheapest DigitalOcean.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Thanks a million to &lt;a href=&quot;https:&#x2F;&#x2F;morgan.zoemp.be&#x2F;about&#x2F;&quot;&gt;Morgan&lt;&#x2F;a&gt; alias &lt;em&gt;SansGuidon&lt;&#x2F;em&gt; online. He took the time to tell me that I broke my atom.xml file during this experiment.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;If I recall correctly, I started writing tech articles somewhere around 2014. During all those years, my deployment workflow was delightfully simple: some Markdown files, two &lt;code&gt;make&lt;&#x2F;code&gt; commands, and my static site was live. It worked. It was fast. It required zero external infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;The irony? I spent years and years toying with CI&#x2F;CD pipelines for employers, using all the modern &lt;em&gt;(and all the very old)&lt;&#x2F;em&gt; tooling. Yet my &lt;em&gt;own&lt;&#x2F;em&gt; site ran like it was 2005. &lt;em&gt;What a world!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I sincerely believe that there was no good reason to change. I only did it for fun and to entertain myself a little (&lt;em&gt;and maybe, maybe, to improve things a little bit&lt;&#x2F;em&gt;). This is the story of how I did it: from a &lt;code&gt;git push&lt;&#x2F;code&gt; on my local machine to a fully built, containerized, deployed site on a fresh server, with automatic TLS. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=82-P9ZNYnik&quot;&gt;Music \o&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#journey&quot;&gt;The journey: where we were vs where we are going&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-ci&quot;&gt;GitLab CI pipeline&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-ci-config&quot;&gt; The GitLab CI configuration file&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-ci-vars&quot;&gt; Required GitLab CI&#x2F;CD variables&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#gitlab-registry&quot;&gt; GitLab container registry&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#notification&quot;&gt; Notification mechanism: GitLab CI SSHes directly into VPS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#container-image&quot;&gt;The Container image&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#dockerfile&quot;&gt; The multi-stage Container file&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#nginx-config&quot;&gt; The Nginx configuration file&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#vps-provisioning&quot;&gt;The VPS provisioning&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#droplet&quot;&gt; Droplet recommendation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#provisioning-steps&quot;&gt; Provisioning steps&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#vps-hardening&quot;&gt; VPS security hardening&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#doctl&quot;&gt; Going further: one-command provisioning with doctl&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#deploy-script&quot;&gt; Deploy script&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#podman-critical&quot;&gt; Critical: rootless Podman and SSH session lifecycle&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#ssl-tls&quot;&gt;SSL &amp;amp; Let&#x27;s Encrypt&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#caddy&quot;&gt; Decision: Caddy&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#letsencrypt-ip&quot;&gt; Let&#x27;s Encrypt IP address certificates&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#operations&quot;&gt;Operations&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#rollback&quot;&gt; Rollback procedure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#image-scanning&quot;&gt; Container image security scanning&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#monitoring&quot;&gt; Uptime monitoring&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#zero-downtime&quot;&gt; Zero-downtime deploys&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;mvln2&#x2F;#more&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;journey&quot;&gt;The journey&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;where-i-was-simple-short-deployment&quot;&gt;Where I was, simple&#x2F;short deployment&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;publish:
&lt;&#x2F;span&gt;&lt;span&gt;	zola build
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;rsync_deploy_site:
&lt;&#x2F;span&gt;&lt;span&gt;	zola build
&lt;&#x2F;span&gt;&lt;span&gt;	find public -name &amp;quot;*.xml&amp;quot; -o -name &amp;quot;*.html&amp;quot; | xargs sed -i -e &amp;#39;&#x2F;\&amp;amp;lt;!--.*--\&amp;amp;gt;&#x2F;d&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;	rsync -P -a -v --recursive -e &amp;quot;ssh -p $(SSH_PORT)&amp;quot; $(OUTPUTDIR)&#x2F; $(SSH_NICK):$(SSH_SITE_DIR) --cvs-exclude
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.PHONY: help publish rsync_deploy_site 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simple deployment because it involved 3 tools. Short deployment because there was a straight, direct path between my laptop and the server. I built the site locally and pushed the output directly to the VPS via rsync over SSH. The Makefile orchestrates everything — it runs &lt;code&gt;zola build&lt;&#x2F;code&gt; and then calls &lt;code&gt;rsync&lt;&#x2F;code&gt; to copy the &lt;code&gt;public&#x2F;&lt;&#x2F;code&gt; directory to the server. That&#x27;s it.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;[Local Machine]
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | 1. make publish
&lt;&#x2F;span&gt;&lt;span&gt;      |    └─ zola build  →  generates public&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | 2. make rsync_deploy_site
&lt;&#x2F;span&gt;&lt;span&gt;      |    └─ rsync -a public&#x2F; mlvn@1.2.3.4:&#x2F;home&#x2F;mlvn&#x2F;public (via SSH, port 1022)
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[DigitalOcean VPS]
&lt;&#x2F;span&gt;&lt;span&gt;  &#x2F;home&#x2F;mlvn&#x2F;public&#x2F;   ← raw static files on disk that are served by Nginx
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Nginx&#x2F;web server on VPS]
&lt;&#x2F;span&gt;&lt;span&gt;  Handles TLS (Let&amp;#39;s Encrypt, auto-renewed)
&lt;&#x2F;span&gt;&lt;span&gt;  serves files directly from disk
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Visitor&amp;#39;s browser]
&lt;&#x2F;span&gt;&lt;span&gt;  https:&#x2F;&#x2F;nskm.xyz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There were no external dependencies, no container images to build, no container registries to manage, no GitLab CI runners to wait for. Life was beautiful.&lt;&#x2F;p&gt;
&lt;p&gt;But... I did realize, &lt;em&gt;maaybe&lt;&#x2F;em&gt; I need a way to roll back a bad deployment. &lt;em&gt;Maaaybe&lt;&#x2F;em&gt; I need some version control. &lt;em&gt;Maaaaaybe&lt;&#x2F;em&gt; it&#x27;s not a good idea to have the source code living only on my laptop. &lt;em&gt;Maaaaaaaaybe&lt;&#x2F;em&gt; I need the build process to be reproducible. I mean, &lt;em&gt;come on man, I can do better&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;was_not_that_bad.png&quot; alt=&quot;When you take a step back, you realise that we have come a very long way.&quot; title=&quot;When you take a step back, you realise that we have come a very long way.&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;where-i-am-right-now-slightly-more-complex-deployment&quot;&gt;Where I am right now, slightly more complex deployment&lt;&#x2F;h3&gt;
&lt;p&gt;I do a git push to &lt;a href=&quot;https:&#x2F;&#x2F;raccoon.onyxbits.de&#x2F;blog&#x2F;why-not-use-github&quot;&gt;GitLab&lt;&#x2F;a&gt;. Everything else happens automagically: CI builds the HTML pages from the Markdown files, CI builds a Docker image containing the compiled site, then pushes it to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;user&#x2F;packages&#x2F;container_registry&#x2F;&quot;&gt;GitLab Container Registry&lt;&#x2F;a&gt; and finally, SSHes into the VPS to pull and run the new image. &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt; on the VPS handles TLS termination and proxies traffic to the container.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;[Local Machine]
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | git push origin master
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[GitLab.com]
&lt;&#x2F;span&gt;&lt;span&gt;  Repository stores all source: content&#x2F;, templates&#x2F;, sass&#x2F;, themes&#x2F;, config.toml
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      | .gitlab-ci.yml triggers pipeline automatically
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      ├─ Stage 1: build-and-push-image
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ docker:dind runner
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ zola build  (inside Dockerfile, Stage 1: debian:bookworm-slim)
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ output copied into nginx:alpine image  (Stage 2)
&lt;&#x2F;span&gt;&lt;span&gt;      |    ├─ image built and tagged: registry.gitlab.com&#x2F;USERNAME&#x2F;proj:&amp;lt;commit-sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      |    └─ image pushed to GitLab Container Registry
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      └─ Stage 2: deploy-to-vps
&lt;&#x2F;span&gt;&lt;span&gt;           ├─ alpine runner with openssh-client
&lt;&#x2F;span&gt;&lt;span&gt;           └─ SSH into VPS → runs &#x2F;home&#x2F;mlvn&#x2F;deploy.sh &amp;lt;commit-sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;                |
&lt;&#x2F;span&gt;&lt;span&gt;                v
&lt;&#x2F;span&gt;&lt;span&gt;[DigitalOcean VPS — new Droplet]
&lt;&#x2F;span&gt;&lt;span&gt;  deploy.sh:
&lt;&#x2F;span&gt;&lt;span&gt;    podman pull registry.gitlab.com&#x2F;USERNAME&#x2F;proj:&amp;lt;sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    podman stop nskm-site  (old container)
&lt;&#x2F;span&gt;&lt;span&gt;    podman run -d --name nskm-site -p 8080:80 IMAGE:&amp;lt;sha&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Caddy on VPS host]
&lt;&#x2F;span&gt;&lt;span&gt;  Handles TLS (Let&amp;#39;s Encrypt, auto-renewed)
&lt;&#x2F;span&gt;&lt;span&gt;  Caddyfile: reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span&gt;      |
&lt;&#x2F;span&gt;&lt;span&gt;      v
&lt;&#x2F;span&gt;&lt;span&gt;[Visitor&amp;#39;s browser]
&lt;&#x2F;span&gt;&lt;span&gt;  https:&#x2F;&#x2F;nskm.xyz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Pros of the CI&#x2F;CD approach&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I just git push code, site deploys itself&lt;&#x2F;li&gt;
&lt;li&gt;Version controlled: full git history, every change is tracked and auditable&lt;&#x2F;li&gt;
&lt;li&gt;Rollback: any previous image tag can be redeployed in seconds&lt;&#x2F;li&gt;
&lt;li&gt;Immutable deploys: each deploy is a fresh container from a known image, no partial file transfers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Cons of the CI&#x2F;CD approach&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;More moving parts, more things that can break: GitLab, container registry, Docker&#x2F;Podman, Caddy, deploy script&lt;&#x2F;li&gt;
&lt;li&gt;Slower feedback loop: pipeline takes more minutes&lt;&#x2F;li&gt;
&lt;li&gt;Registry storage to manage: images accumulate (mitigated by cleanup policy)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;ci_down.webp&quot; alt=&quot;CI is down&quot; title=&quot;CI is down&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;gitlab-ci&quot;&gt;GitLab CI pipeline&lt;&#x2F;h2&gt;
&lt;p&gt;TODO: gitlab ci file ???&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gitlab-ci-config&quot;&gt;The GitLab CI configuration file: &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Nothing fancy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker:24.0.5-cli&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;services&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker:24.0.5-dind&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;variables&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_TLS_CERTDIR&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;certs&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_TLS_VERIFY&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_CERT_PATH&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$DOCKER_TLS_CERTDIR&#x2F;client&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_DRIVER&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;overlay2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DOCKER_BUILDKIT&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;IMAGE_NAME&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;registry.gitlab.com&#x2F;$CI_PROJECT_NAMESPACE&#x2F;$CI_PROJECT_NAME&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;IMAGE_TAG&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_SHORT_SHA&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stages&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;build-and-push-image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;before_script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker login -u &amp;quot;$CI_REGISTRY_USER&amp;quot; -p &amp;quot;$CI_REGISTRY_PASSWORD&amp;quot; &amp;quot;$CI_REGISTRY&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker build&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--cache-from &amp;quot;${IMAGE_NAME}:latest&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--build-arg BUILDKIT_INLINE_CACHE=1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-t &amp;quot;${IMAGE_NAME}:${IMAGE_TAG}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-t &amp;quot;${IMAGE_NAME}:latest&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker push &amp;quot;${IMAGE_NAME}:${IMAGE_TAG}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;docker push &amp;quot;${IMAGE_NAME}:latest&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_BRANCH == &amp;quot;master&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;deploy-to-vps&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;alpine:3.19&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;before_script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apk add --no-cache openssh-client&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eval $(ssh-agent -s)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;echo &amp;quot;$MLVN_SSH_PRIVATE_KEY&amp;quot; | tr -d &amp;#39;\r&amp;#39; | base64 -d | ssh-add -&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;mkdir -p ~&#x2F;.ssh &amp;amp;&amp;amp; chmod 700 ~&#x2F;.ssh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;echo &amp;quot;$MLVN_SSH_KNOWN_HOST&amp;quot; &amp;gt;&amp;gt; ~&#x2F;.ssh&#x2F;known_hosts&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ssh -p 1234 mlvn@$MLVN_IP &amp;quot;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh ${IMAGE_TAG}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;needs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push-image&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_BRANCH == &amp;quot;master&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;https:&#x2F;&#x2F;nskm.xyz&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;gitlab-ci-vars&quot;&gt;Required GitLab CI&#x2F;CD variables&lt;&#x2F;h3&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Variable&lt;&#x2F;th&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Protected&lt;&#x2F;th&gt;&lt;th&gt;Masked&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;VPS_SSH_PRIVATE_KEY&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable (private key content)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;VPS_IP&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable (new Droplet IP once known)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;VPS_IP&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Variable (new Droplet IP once known)&lt;&#x2F;td&gt;&lt;td&gt;Yes&lt;&#x2F;td&gt;&lt;td&gt;No&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;All other needed variables (&lt;code&gt;CI_REGISTRY_USER&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY_PASSWORD&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY&lt;&#x2F;code&gt;, &lt;code&gt;CI_COMMIT_SHORT_SHA&lt;&#x2F;code&gt;, etc.) are injected automatically by GitLab.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gitlab-registry&quot;&gt;GitLab container registry&lt;&#x2F;h3&gt;
&lt;p&gt;Every GitLab project has a &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;user&#x2F;packages&#x2F;container_registry&#x2F;&quot;&gt;registry&lt;&#x2F;a&gt; at &lt;code&gt;registry.gitlab.com&#x2F;USERNAME&#x2F;PROJECT&lt;&#x2F;code&gt;. This allows me to store, manage, and distribute my &lt;a href=&quot;https:&#x2F;&#x2F;opencontainers.org&#x2F;&quot;&gt;OCI&lt;&#x2F;a&gt; images, alongside the source code and the CI&#x2F;CD pipelines. The authentication from the pipeline to the registry is automatic: GitLab injects &lt;code&gt;CI_REGISTRY_USER&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY_PASSWORD&lt;&#x2F;code&gt;, &lt;code&gt;CI_REGISTRY&lt;&#x2F;code&gt; environment variables into every pipeline.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;vps-authentication-to-pull-images&quot;&gt;VPS authentication to pull images&lt;&#x2F;h4&gt;
&lt;p&gt;The VPS serving my website need to be able to pull the container image to run it. And for being able to pull the image, it also need to authenticate itself to the container registry. This is where Gitlab deploy token enters the play.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;user&#x2F;project&#x2F;deploy_tokens&#x2F;&quot;&gt;GitLab deploy token&lt;&#x2F;a&gt; is a non-user specific credential used to authenticate automated tasks, such as &lt;em&gt;a VPS&lt;&#x2F;em&gt;, to access GitLab resources &lt;em&gt;like registries&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I created one GitLab deploy token, I picked the &lt;code&gt;read_registry&lt;&#x2F;code&gt; scope, I stored the credentials in &lt;code&gt;~&#x2F;.config&#x2F;containers&#x2F;auth.json&lt;&#x2F;code&gt;. This file stores your base64 encoded credentials to facilitate future registry operation.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;mlvn@mlvn:~$ cat ~&#x2F;.config&#x2F;containers&#x2F;auth.json
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;auths&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;registry.gitlab.com&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;auth&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;XZwczpnbGR0LUdQeEg2M3pjeWlcGxveS10nskmb2tlbi1tbHZuLo2QnBGeXo1eDR0Z2l0bGFiK2&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;container-registry-cleanup-policy&quot;&gt;Container registry cleanup policy&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;user&#x2F;packages&#x2F;container_registry&#x2F;reduce_container_registry_storage&#x2F;&quot;&gt;Container registries&lt;&#x2F;a&gt; can grow in size if you don&#x27;t manage your registry usage. Retrieving the list of available tags or images becomes slower. Images could take up a large amount of storage space on the server. So I defined a cleanup policy to keep last 5 tags, run weekly, remove tags older than 14 days.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;notification&quot;&gt;Notification mechanism:&lt;&#x2F;h3&gt;
&lt;p&gt;I decided, GitLab CI will SSHes directly into VPS. There was two other options. The first one being a webhook receiver on VPS, which required installing &amp;amp; managing a webhook daemon and opening an extra port. The second one being polling. Why ?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No extra service to install on VPS&lt;&#x2F;li&gt;
&lt;li&gt;No extra ports to open&lt;&#x2F;li&gt;
&lt;li&gt;Deploy action is visible in GitLab pipeline logs&lt;&#x2F;li&gt;
&lt;li&gt;SSH is already used and understood&lt;&#x2F;li&gt;
&lt;li&gt;No polling delay&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I generated a dedicated ED25519 key pair for GitLab CI, different from my personal key. I stored the private key in GitLab CI variable marked &lt;code&gt;Protected&lt;&#x2F;code&gt; + &lt;code&gt;Masked&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;container-image&quot;&gt;The Container image&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;dockerfile&quot;&gt;The multi-stage Container file&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;dockerfile&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-dockerfile &quot;&gt;&lt;code class=&quot;language-dockerfile&quot; data-lang=&quot;dockerfile&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Stage 1: Build static site with Zola
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; docker.io&#x2F;library&#x2F;debian:bookworm-slim &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;AS &lt;&#x2F;span&gt;&lt;span&gt;builder
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;ARG &lt;&#x2F;span&gt;&lt;span&gt;ZOLA_VERSION=0.18.0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y --no-install-recommends \
&lt;&#x2F;span&gt;&lt;span&gt;    wget ca-certificates \
&lt;&#x2F;span&gt;&lt;span&gt;    jpegoptim optipng gifsicle libimage-exiftool-perl \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; rm -rf &#x2F;var&#x2F;lib&#x2F;apt&#x2F;lists&#x2F;*
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;wget -q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;github.com&#x2F;getzola&#x2F;zola&#x2F;releases&#x2F;download&#x2F;v${ZOLA_VERSION}&#x2F;zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; \
&lt;&#x2F;span&gt;&lt;span&gt;    -O &#x2F;tmp&#x2F;zola.tar.gz \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; tar -xzf &#x2F;tmp&#x2F;zola.tar.gz -C &#x2F;usr&#x2F;local&#x2F;bin&#x2F; \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; chmod +x &#x2F;usr&#x2F;local&#x2F;bin&#x2F;zola \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; rm &#x2F;tmp&#x2F;zola.tar.gz
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;WORKDIR &lt;&#x2F;span&gt;&lt;span&gt;&#x2F;site
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; config.toml .
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; themes&#x2F; themes&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; static&#x2F; static&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; templates&#x2F; templates&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; content&#x2F; content&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;zola build \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; find public -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.xml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -o -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.html&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; | xargs sed -i -e &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;lt;!--.*--&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;gt;&#x2F;d&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Strip metadata (EXIF, GPS, IPTC, ICC profiles) from all images
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;exiftool -all= -overwrite_original -recurse public
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Optimize images (lossless)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# For lossy JPEG (visually identical, ~60-80% smaller): add --max=85
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;find public -type f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\(&lt;&#x2F;span&gt;&lt;span&gt; -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.jpg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -o -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.jpeg&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;\)&lt;&#x2F;span&gt;&lt;span&gt; -print0 | xargs -0 -r jpegoptim --strip-all \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; find public -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.png&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -print0 | xargs -0 -r optipng -o2 -strip all \
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;amp;&amp;amp; find public -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.gif&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -print0 | xargs -0 -r gifsicle -O3 --batch
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Stage 2: Serve with minimal Nginx
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; docker.io&#x2F;library&#x2F;nginx:1.25-alpine &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;AS &lt;&#x2F;span&gt;&lt;span&gt;serve
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;RUN &lt;&#x2F;span&gt;&lt;span&gt;rm -rf &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder &#x2F;site&#x2F;public&#x2F; &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; nginx.conf &#x2F;etc&#x2F;nginx&#x2F;conf.d&#x2F;default.conf
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;EXPOSE &lt;&#x2F;span&gt;&lt;span&gt;80
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;CMD &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nginx&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-g&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;daemon off;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;nginx-config&quot;&gt;The Nginx configuration file&lt;&#x2F;h3&gt;
&lt;p&gt;Why using Nginx inside the container and not Caddy ? Nginx inside the container serves HTTP only on port 80. SSL is handled by Caddy on the VPS host outside the container. Caddy&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;features&quot;&gt;killer features&lt;&#x2F;a&gt;, &lt;em&gt;you might want to sit down for this&lt;&#x2F;em&gt;, are completely wasted inside a container that only serves static files over plain HTTP to localhost. &lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;_&#x2F;nginx&quot;&gt;Nginx Alpine&lt;&#x2F;a&gt; is very small and purpose-built for this job.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;nsukami@IPD-DDSI5:~&#x2F;GIT&#x2F;nskm2$ podman images &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep nginx
&lt;&#x2F;span&gt;&lt;span&gt;docker.io&#x2F;library&#x2F;nginx                                                  1.29.5-alpine-slim  a68d27696acb  3 weeks ago    13.5 MB
&lt;&#x2F;span&gt;&lt;span&gt;docker.io&#x2F;library&#x2F;nginx                                                  1.25-alpine         501d84f5d064  22 months ago  50.1 MB
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;nginx&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-nginx &quot;&gt;&lt;code class=&quot;language-nginx&quot; data-lang=&quot;nginx&quot;&gt;&lt;span&gt;server {
&lt;&#x2F;span&gt;&lt;span&gt;    listen 80;
&lt;&#x2F;span&gt;&lt;span&gt;    root &#x2F;usr&#x2F;share&#x2F;nginx&#x2F;html;
&lt;&#x2F;span&gt;&lt;span&gt;    index index.html;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    gzip on;
&lt;&#x2F;span&gt;&lt;span&gt;    gzip_types text&#x2F;plain text&#x2F;css application&#x2F;json application&#x2F;javascript
&lt;&#x2F;span&gt;&lt;span&gt;               text&#x2F;xml application&#x2F;xml text&#x2F;javascript image&#x2F;svg+xml;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|webp|mp4|pdf)$ {
&lt;&#x2F;span&gt;&lt;span&gt;        expires 1y;
&lt;&#x2F;span&gt;&lt;span&gt;        add_header Cache-Control &amp;quot;public, immutable&amp;quot;;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    location &#x2F; {
&lt;&#x2F;span&gt;&lt;span&gt;        try_files $uri $uri&#x2F; $uri.html =404;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    error_page 404 &#x2F;404.html;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;vps-provisioning&quot;&gt;The VPS provisioning&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;droplet&quot;&gt;Droplet recommendation&lt;&#x2F;h3&gt;
&lt;p&gt;I am a proud DigitalOcean user since 2011. At that time, I was looking for ways to learn about a real server with a real IP address, the one that are publicly accessible. At that time, I had no credit card, &lt;em&gt;no money to be honest&lt;&#x2F;em&gt;. My first server on this platform was offered to me by a very good friend. He paid for the VPS and gave me the root credentials, then, asked me to correctly harden the server, the rest is history.&lt;&#x2F;p&gt;
&lt;p&gt;For this experiment, 1 vCPU, 1GB RAM, 25GB SSD, Ubuntu 24.04 LTS should be more than enough. Keep the old Droplet running (rsync deploys still work) while you set up the new one, update DNS to the new IP once it&#x27;s ready, then decommission the old one.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;provisioning-steps&quot;&gt;Provisioning steps (in order)&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 1. Update packages
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get update &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get upgrade -y
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 2. Firewall
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install -y ufw
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw allow 1234&#x2F;tcp   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# SSH on custom port
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw allow 80&#x2F;tcp     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# HTTP (Caddy ACME challenge + redirect)
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw allow 443&#x2F;tcp    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# HTTPS
&lt;&#x2F;span&gt;&lt;span&gt;sudo ufw enable
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 3. Install Podman
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get -y install podman
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 4. Install Caddy
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https
&lt;&#x2F;span&gt;&lt;span&gt;curl -1sLf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;gpg.key&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;sudo gpg --dearmor -o &#x2F;usr&#x2F;share&#x2F;keyrings&#x2F;caddy-stable-archive-keyring.gpg
&lt;&#x2F;span&gt;&lt;span&gt;curl -1sLf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;debian.deb.txt&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;sudo tee &#x2F;etc&#x2F;apt&#x2F;sources.list.d&#x2F;caddy-stable.list
&lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get update &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo apt-get install -y caddy
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 5. Configure Caddy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# edit &#x2F;etc&#x2F;caddy&#x2F;Caddyfile with the following content:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#   nskm.xyz {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#       reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#   }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 6. enable and start the service
&lt;&#x2F;span&gt;&lt;span&gt;sudo systemctl enable caddy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo systemctl start caddy
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 7. Authenticate Podman to GitLab registry
&lt;&#x2F;span&gt;&lt;span&gt;podman login registry.gitlab.com -u DEPLOY_TOKEN_USER -p DEPLOY_TOKEN_VALUE
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;vps-hardening&quot;&gt;VPS security hardening&lt;&#x2F;h3&gt;
&lt;p&gt;There are &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;community&#x2F;tutorials?q=%5Bsecurity%5D+harden&quot;&gt;lots of tutorials&lt;&#x2F;a&gt; explaining how you should harden the security of your server. I think, there is no need to discuss the matter here.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;doctl&quot;&gt;Going further: one-command provisioning with doctl&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.digitalocean.com&#x2F;reference&#x2F;doctl&#x2F;&quot;&gt;doctl&lt;&#x2F;a&gt; is DigitalOcean&#x27;s CLI tool that I&#x27;ve never used. &lt;a href=&quot;https:&#x2F;&#x2F;cloud-init.io&#x2F;&quot;&gt;Cloud-init&lt;&#x2F;a&gt; is a standard way to run scripts on first boot that I&#x27;ve never used too. I absolutely must find a way to use both tools more often.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A cloud-init script&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It is essentially the provisioning steps from above, packed into a single file that runs automatically when the Droplet first boots. Create a file called &lt;code&gt;cloud-init.sh&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#cloud-config
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;users&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;mlvn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;shell&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ALL=(ALL) NOPASSWD:ALL&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ssh_authorized_keys&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ssh-ed25519 AAAA... your-public-key-here&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;package_update&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;package_upgrade&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;packages&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;podman&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;fail2ban&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;unattended-upgrades&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;debian-keyring&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;debian-archive-keyring&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apt-transport-https&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;write_files&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;etc&#x2F;caddy&#x2F;Caddyfile&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      nskm.xyz {
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;etc&#x2F;fail2ban&#x2F;jail.d&#x2F;sshd.conf&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      [sshd]
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      enabled = true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      port    = 1234
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;etc&#x2F;ssh&#x2F;sshd_config.d&#x2F;hardening.conf&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      PermitRootLogin no
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      PasswordAuthentication no
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      Port 1234
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;permissions&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0755&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;owner&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;mlvn:mlvn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;content&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      #!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      set -euo pipefail
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      IMAGE=&amp;quot;registry.gitlab.com&#x2F;USERNAME&#x2F;proj&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      TAG=&amp;quot;${1:-latest}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      CONTAINER=&amp;quot;nskm-site&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      PORT=8080
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      echo &amp;quot;Deploying ${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker pull &amp;quot;${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker stop &amp;quot;${CONTAINER}&amp;quot; 2&amp;gt;&#x2F;dev&#x2F;null || true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker rm &amp;quot;${CONTAINER}&amp;quot; 2&amp;gt;&#x2F;dev&#x2F;null || true
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker run -d --name &amp;quot;${CONTAINER}&amp;quot; --restart unless-stopped -p &amp;quot;${PORT}:80&amp;quot; &amp;quot;${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      docker image prune -f
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      echo &amp;quot;Done: ${IMAGE}:${TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runcmd&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Firewall
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw allow 1234&#x2F;tcp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw allow 80&#x2F;tcp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw allow 443&#x2F;tcp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ufw --force enable&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Install Podman
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y podman&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Install Caddy
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;curl -1sLf &amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;gpg.key&amp;#39; | gpg --dearmor -o &#x2F;usr&#x2F;share&#x2F;keyrings&#x2F;caddy-stable-archive-keyring.gpg&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;curl -1sLf &amp;#39;https:&#x2F;&#x2F;dl.cloudsmith.io&#x2F;public&#x2F;caddy&#x2F;stable&#x2F;debian.deb.txt&amp;#39; | tee &#x2F;etc&#x2F;apt&#x2F;sources.list.d&#x2F;caddy-stable.list&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y caddy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;systemctl enable caddy &amp;amp;&amp;amp; systemctl start caddy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Security
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;systemctl enable fail2ban --now&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;systemctl restart ssh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;dpkg-reconfigure --priority=low unattended-upgrades&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Enable linger for rootless containers (if using Podman later)
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;loginctl enable-linger mlvn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Create the Droplet using the doctl command&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;doctl compute droplet create nskm-vps \
&lt;&#x2F;span&gt;&lt;span&gt;  --image ubuntu-24-04-x64 \
&lt;&#x2F;span&gt;&lt;span&gt;  --size s-1vcpu-1gb \
&lt;&#x2F;span&gt;&lt;span&gt;  --region ams3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --ssh-keys $(doctl compute ssh-key list --format ID --no-header &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;head -1) \
&lt;&#x2F;span&gt;&lt;span&gt;  --user-data-file .&#x2F;cloud-init.sh \
&lt;&#x2F;span&gt;&lt;span&gt;  --wait
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And voilà!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;deploy-script&quot;&gt;Deploy script: &lt;code&gt;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This is the script that will be called by Gitlab whenever a new image is built:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;set -euo pipefail
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;IMAGE=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;registry.gitlab.com&#x2F;USERNAME&#x2F;nskm2&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TAG=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;1:-&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;latest}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;nskm-site&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Deploying ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;docker pull &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;docker stop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;docker rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;docker run -d --name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;CONTAINER&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; --restart unless-stopped -p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:80&amp;quot; &amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;docker image prune -f
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Done: ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;chmod +x &#x2F;home&#x2F;mlvn&#x2F;deploy.sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;podman-critical&quot;&gt;Critical: rootless Podman and SSH session lifecycle&lt;&#x2F;h3&gt;
&lt;p&gt;During my various tests, I noticed some strange behaviour. The deploy log shows success and the health check passes, but the site returns 502 immediately after the CI job finishes:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ # Job succeeded....
&lt;&#x2F;span&gt;&lt;span&gt;$ ssh -p 1234 mlvn@$MLVN_IP &amp;quot;&#x2F;home&#x2F;mlvn&#x2F;deploy.sh ${IMAGE_TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;Deploying registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fg2abf
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;Running health check...
&lt;&#x2F;span&gt;&lt;span&gt;Done: registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fg2abf is live
&lt;&#x2F;span&gt;&lt;span&gt;Job succeeded
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;$ # Yet...
&lt;&#x2F;span&gt;&lt;span&gt;$ curl -I &amp;quot;http:&#x2F;&#x2F;1.2.3.4&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;HTTP&#x2F;1.1 502 Bad Gateway
&lt;&#x2F;span&gt;&lt;span&gt;Server: Caddy
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even more confusing...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;podman ps -a&lt;&#x2F;code&gt; shows the container in &lt;code&gt;Exited (0)&lt;&#x2F;code&gt; state, and &lt;code&gt;podman logs nskm-site&lt;&#x2F;code&gt; confirms it received SIGTERM seconds after the health check passed:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;22:03:54 — container starts
&lt;&#x2F;span&gt;&lt;span&gt;22:03:57 — health check hits it: &amp;quot;GET &#x2F; HTTP&#x2F;1.1&amp;quot; 200  ✓
&lt;&#x2F;span&gt;&lt;span&gt;22:04:07 — signal 15 (SIGTERM) received, exiting       ← WTF?!
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;kanye_wtf.gif&quot; alt=&quot;wtf&quot; title=&quot;wtf&quot;&#x2F;&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lists.podman.io&#x2F;archives&#x2F;list&#x2F;podman@lists.podman.io&#x2F;thread&#x2F;CQTZAORZXW6UWDNAV5TAWAV6PTDJFW6V&#x2F;&quot;&gt;The problem&lt;&#x2F;a&gt;: When using rootless Podman (Podman running as a regular user, not root), containers are tied to the user&#x27;s login session. When a CI job SSHes into the VPS, runs &lt;code&gt;deploy.sh&lt;&#x2F;code&gt;, and disconnects, the SSH session ends and systemd cleans up the session, sending SIGTERM to all processes in it, including the running container.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.freedesktop.org&#x2F;software&#x2F;systemd&#x2F;man&#x2F;latest&#x2F;loginctl.html&quot;&gt;The solution&lt;&#x2F;a&gt;: enabling lingering for the user running the container:**&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;loginctl enable-linger mlvn  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# run once on the VPS
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This instructs systemd to keep the &lt;code&gt;mlvn&lt;&#x2F;code&gt; user session alive permanently, even after logout. Containers started by this user will survive SSH disconnection.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Verify:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;loginctl show-user mlvn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep Linger
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Expected output: Linger=yes
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;This must be run before the first real deploy.&lt;&#x2F;strong&gt; Without it, every CI deploy will appear to succeed but the site will go down immediately after the SSH session closes.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;ssl-tls&quot;&gt;SSL &amp;amp; Let&#x27;s Encrypt&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;caddy&quot;&gt;Decision: Caddy&lt;&#x2F;h3&gt;
&lt;p&gt;Caddy handles everything automatically with a single config line:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm.xyz {
&lt;&#x2F;span&gt;&lt;span&gt;    reverse_proxy localhost:8080
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In 3 lines, Caddy:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Obtains Let&#x27;s Encrypt cert on first request automatically&lt;&#x2F;li&gt;
&lt;li&gt;Renews before expiry (auto, no cron needed, no certbot)&lt;&#x2F;li&gt;
&lt;li&gt;Redirects HTTP → HTTPS automatically&lt;&#x2F;li&gt;
&lt;li&gt;Stores certs in &lt;code&gt;&#x2F;var&#x2F;lib&#x2F;caddy&#x2F;.local&#x2F;share&#x2F;caddy&#x2F;&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I remember the time when I had to &lt;em&gt;get my geek on&lt;&#x2F;em&gt; and do eveything myself, &lt;em&gt;as a proud Linux user&lt;&#x2F;em&gt;: certbot install, cron job, renewal hooks, manual intervention when things break. &lt;em&gt;Phew&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;jpoesen.png&quot; alt=&quot;A very looooooong time ago&quot; title=&quot;A very looooooong time ago&quot;&#x2F;&gt;
&lt;br&gt;
&lt;h3 id=&quot;letsencrypt-ip&quot;&gt;Let&#x27;s Encrypt IP address certificates (January 2026)&lt;&#x2F;h3&gt;
&lt;p&gt;Amazing how few years ago, it was something you didn&#x27;t think about. Today, Let&#x27;s Encrypt now issues &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;2026&#x2F;01&#x2F;15&#x2F;6day-and-ip-general-availability&quot;&gt;certificates for raw IP addresses&lt;&#x2F;a&gt;. I was thinking about using it for the new VPS, before updating the DNS to the new IP address. Then I learned IP address certs are &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;2026&#x2F;01&#x2F;15&#x2F;6day-and-ip-general-availability&quot;&gt;short-lived certificates&lt;&#x2F;a&gt; — they are valid only for &lt;strong&gt;160 hours (≈6 days)&lt;&#x2F;strong&gt; instead of the usual 90 days. Not a problem in practice, just worth knowing.&lt;&#x2F;p&gt;
&lt;p&gt;Where this could be useful on this VPS ? Maybe ....&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;YOUR_VPS_IP {
&lt;&#x2F;span&gt;&lt;span&gt;    reverse_proxy localhost:SOME_PORT
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;operations&quot;&gt;Operations&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;rollback&quot;&gt;Rollback procedure&lt;&#x2F;h3&gt;
&lt;p&gt;One of the reasons &lt;em&gt;(probably the main reason)&lt;&#x2F;em&gt; I moved to CI&#x2F;CD was the ability to rollback a deployment. With rsync, rolling back meant &quot;do you still have the old files somewhere?&quot;. With container images, every deploy is tagged with its commit SHA and stored in the GitLab registry.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Available image tags on the VPS:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;mlvn@mlvn:~$ podman login registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Authenticating with existing credentials for registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Existing credentials are valid. Already logged in to registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$ podman images --format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{.Repository}}:{{.Tag}}  {{.CreatedAt}}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep nskm
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:6c08ce72  2026-03-03 06:59:24 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:latest  2026-03-01 21:46:30 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf  2026-03-01 21:46:30 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:9a326e8c  2026-03-01 21:30:53 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;registry.gitlab.com&#x2F;nskm&#x2F;mlvn:005ba0d9  2026-03-01 17:21:40 +0000 UTC
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Roll back to a previous version:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;mlvn@mlvn:~$ .&#x2F;deploy.sh b7fb2abf
&lt;&#x2F;span&gt;&lt;span&gt;Login in to the Gitlab container registry
&lt;&#x2F;span&gt;&lt;span&gt;Authenticating with existing credentials for registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Existing credentials are valid. Already logged in to registry.gitlab.com
&lt;&#x2F;span&gt;&lt;span&gt;Deploying registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf
&lt;&#x2F;span&gt;&lt;span&gt;Trying to pull registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf...
&lt;&#x2F;span&gt;&lt;span&gt;Getting image source signatures
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 5406ed7b06d9 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 4abcf2066143 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob fc21a1d387f5 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob e6ef242c1570 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 13fcfbc94648 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob d4bca490e609 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 8a3742a9529d skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 0d0c16747d2c skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob f7809d4c4360 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob 3ee6c312ca9b skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying blob ed4f6e59d232 skipped: already exists
&lt;&#x2F;span&gt;&lt;span&gt;Copying config 632bfe60dc done   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span&gt;Writing manifest to image destination
&lt;&#x2F;span&gt;&lt;span&gt;632bfe60dce5626a87db391496d017ed1dc7d5f805af81fa5936cbb0323c0099
&lt;&#x2F;span&gt;&lt;span&gt;nskm-site
&lt;&#x2F;span&gt;&lt;span&gt;nskm-site
&lt;&#x2F;span&gt;&lt;span&gt;ef7a0a78ee6b047b5fbb0c5b4e6622fff4769096d12ec21384c36149d000f669
&lt;&#x2F;span&gt;&lt;span&gt;Running health check...
&lt;&#x2F;span&gt;&lt;span&gt;Done: registry.gitlab.com&#x2F;nskm&#x2F;mlvn:b7fb2abf is live
&lt;&#x2F;span&gt;&lt;span&gt;mlvn@mlvn:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s it. The deploy script pulls the old image (already cached locally if it was recently used), stops the current container, and starts a new one based on the old image. The site is back to its previous state in seconds.&lt;&#x2F;p&gt;
&lt;p&gt;If the image has been pruned locally, Podman pulls it from the GitLab registry; as long as it&#x27;s within the cleanup policy window.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;image-scanning&quot;&gt;Container image security scanning&lt;&#x2F;h3&gt;
&lt;p&gt;Every container image inherits vulnerabilities from its base image. While &lt;code&gt;debian:bookworm-slim&lt;&#x2F;code&gt; and &lt;code&gt;nginx:1.25-alpine&lt;&#x2F;code&gt; are well-maintained, they still ship with system libraries that occasionally have known CVEs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;trivy.dev&#x2F;&quot;&gt;Trivy&lt;&#x2F;a&gt; is a free, open-source scanner that checks container images against vulnerability databases. Adding it as a CI stage between build and deploy means a vulnerable image never reaches the VPS.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;scan-image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;scan&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aquasec&#x2F;trivy:latest&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;entrypoint&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;script&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;trivy image&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--exit-code 1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--severity HIGH,CRITICAL&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;--no-progress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${IMAGE_NAME}:${IMAGE_TAG}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;needs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;build-and-push-image&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$CI_COMMIT_BRANCH == &amp;quot;master&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;allow_failure&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;--exit-code 1&lt;&#x2F;code&gt; makes the pipeline fail if HIGH or CRITICAL vulnerabilities are found. &lt;code&gt;allow_failure: true&lt;&#x2F;code&gt; means the deploy can still proceed — it&#x27;s a warning, not a blocker. Remove &lt;code&gt;allow_failure&lt;&#x2F;code&gt; once you&#x27;re confident in your base images.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;monitoring&quot;&gt;Uptime monitoring&lt;&#x2F;h3&gt;
&lt;p&gt;The CI pipeline can succeed and the site can still go down — I learned that the hard way with the Podman linger issue. The pipeline reports success, you go to bed, and the site has been returning 502 for hours. Nobody notices until someone tries to visit.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;uptimerobot.com&#x2F;&quot;&gt;UptimeRobot&lt;&#x2F;a&gt; pings your site every 5 minutes and notifies you when it&#x27;s unreachable. In this real, there is also &lt;a href=&quot;#&quot;&gt;Hetrix&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;StatusCake&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Odown&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Uptime Kuma&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Better Stack&lt;&#x2F;a&gt;. Never tried none of them.&lt;&#x2F;p&gt;
&lt;p&gt;This is just a way to close the &lt;a href=&quot;https:&#x2F;&#x2F;www.dynatrace.com&#x2F;news&#x2F;blog&#x2F;what-is-observability-2&#x2F;&quot;&gt;observability&lt;&#x2F;a&gt; gap: the CI watches the deploy process, and &lt;em&gt;something&lt;&#x2F;em&gt; watches the &lt;strong&gt;deployed result&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 350px&quot; src=&quot;&#x2F;images&#x2F;observability.gif&quot; alt=&quot;observing&quot; title=&quot;Observing&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;zero-downtime&quot;&gt;Zero-downtime deploys&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lpalmieri.com&#x2F;posts&#x2F;zero-downtime-deployments&#x2F;&quot;&gt;Zero downtime deployment&lt;&#x2F;a&gt; (ZDD) is the art of updating applications without interrupting service by running &lt;strong&gt;new&lt;&#x2F;strong&gt; and &lt;strong&gt;old&lt;&#x2F;strong&gt; versions simultaneously.&lt;&#x2F;p&gt;
&lt;p&gt;The current deploy script has a brief downtime window: stop old container, start new one. For a personal blog, nobody notices. But it&#x27;s a fun problem to solve and a useful pattern to know.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What I did:&lt;&#x2F;strong&gt; run two containers on two ports (8080 and 8081). Caddy &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;caddyfile&#x2F;directives&#x2F;reverse_proxy&quot;&gt;reverse proxies&lt;&#x2F;a&gt; to both. At any given time, only one is alive.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated Caddyfile:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm.xyz {
&lt;&#x2F;span&gt;&lt;span&gt;    reverse_proxy localhost:8080 localhost:8081
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Caddy with multiple upstreams does &lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;caddyfile&#x2F;directives&#x2F;reverse_proxy#passive-health-checks&quot;&gt;passive health checking&lt;&#x2F;a&gt;, meaning, if one upstream doesn&#x27;t respond, it routes to the other. If a request hits a dead upstream, Caddy retries on the next one before returning an error.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Updated deploy script:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;set -euo pipefail
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;IMAGE=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;registry.gitlab.com&#x2F;USERNAME&#x2F;proj&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TAG=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;1:-&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;latest}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;podman pull &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Which port is currently in use?
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;podman ps --format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{.Names}}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;grep -q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-8080&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;    OLD_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8081&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;    OLD_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8081&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8080&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Deploying ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;} on port ${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Start new container on the free port
&lt;&#x2F;span&gt;&lt;span&gt;podman run -d --name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;    --restart unless-stopped -p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:80&amp;quot; &amp;quot;${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Health check
&lt;&#x2F;span&gt;&lt;span&gt;sleep 2
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if ! &lt;&#x2F;span&gt;&lt;span&gt;curl -sf --max-time 5 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;localhost:${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; then
&lt;&#x2F;span&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Health check FAILED — old container still live on port ${&lt;&#x2F;span&gt;&lt;span&gt;OLD_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    podman rm -f &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    exit 1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Stop old container (Caddy automatically routes to the new one)
&lt;&#x2F;span&gt;&lt;span&gt;podman stop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;OLD_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;podman rm &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;nskm-site-${&lt;&#x2F;span&gt;&lt;span&gt;OLD_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&#x2F;dev&#x2F;null &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;podman image prune -f
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Done: ${&lt;&#x2F;span&gt;&lt;span&gt;IMAGE&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span&gt;TAG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;} live on port ${&lt;&#x2F;span&gt;&lt;span&gt;NEW_PORT&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;}&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;What happens during a deploy:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Time ──────────────────────────────────────────────────►
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Old container (:8080)  ████████████████████████████████████▓░░░░░░░░░░
&lt;&#x2F;span&gt;&lt;span&gt;New container (:8081)              ░░░░▓████████████████████████████████
&lt;&#x2F;span&gt;&lt;span&gt;Caddy routes to        ──8080────────────────────────────┐
&lt;&#x2F;span&gt;&lt;span&gt;                                                            └──8081───────
&lt;&#x2F;span&gt;&lt;span&gt;Health check                       ✓
&lt;&#x2F;span&gt;&lt;span&gt;                                          ▲
&lt;&#x2F;span&gt;&lt;span&gt;                                     old stopped here
&lt;&#x2F;span&gt;&lt;span&gt;                                     zero downtime
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Both containers run simultaneously during the transition. Caddy&#x27;s health checking handles the routing. The deploy script only needs to know what is the port Podman is currently running on.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;more&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;The shift from manual rsync deployments to automated CI&#x2F;CD took few hours of research, mistakes, and refinement. The hardest part wasn&#x27;t the Docker setup or GitLab CI — it was that subtle Podman session lifecycle issue that made the site silently disappear after every successful deploy.&lt;&#x2F;p&gt;
&lt;p&gt;But now, deploying is automagic. My site has a full audit trail. I can rollback to any previous version in seconds. And, now that I&#x27;m looking at it, I&#x27;m no longer tethered to one computer.&lt;&#x2F;p&gt;
&lt;p&gt;The trade-offs are real: the pipeline takes longer and there are more moving parts. Yet, I would like to go even further, and make things even funnier: running a Pod inside the VPS, and inside the Pod, having 2 containers, one for the website, and another for, I don&#x27;t know, collect &amp;amp; ship the logs ?! We&#x27;ll see.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 350px&quot; src=&quot;&#x2F;images&#x2F;moving_parts.gif&quot; alt=&quot;Too many moving parts&quot; title=&quot;Too many moving parts&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Here is the big picture showing what has been done:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;+-------------+        git push           +-----------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;|             | ------------------------&amp;gt; |                GitLab.com               |
&lt;&#x2F;span&gt;&lt;span&gt;|             |                           |                                         |
&lt;&#x2F;span&gt;&lt;span&gt;|   Laptop    |    email on failure       |                                         |
&lt;&#x2F;span&gt;&lt;span&gt;|             | &amp;lt;------------------------ |  +-----------------------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;+-------------+                           |  |          CI&#x2F;CD Pipeline           |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |  1. build-and-push-image          |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     docker build                  |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     docker push -----------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |  2. scan-image (Trivy)            |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     checks for CVEs               |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |  3. deploy-to-vps                 |  |       |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |     SSH ---------------------------------+   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |                                   |  |   |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  +-----------------------------------+  |   |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +-----------------------------------------+   |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                                                                        |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +--------------------------------------+      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |       GitLab Container Registry      |      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |                                      |      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  IMAGE:abc1234f                      |      |   |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  IMAGE:def5678a                      | &amp;lt;--------+
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  IMAGE:latest                        |      |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |                                      |      |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +-----------------+--------------------+      |
&lt;&#x2F;span&gt;&lt;span&gt;                                                            |                           |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       podman pull                      |
&lt;&#x2F;span&gt;&lt;span&gt;                                                            |                           |
&lt;&#x2F;span&gt;&lt;span&gt;                                                            v                           |
&lt;&#x2F;span&gt;&lt;span&gt;+--------------+    pings every 5 min     +--------------------------------------+      |
&lt;&#x2F;span&gt;&lt;span&gt;|              | ----------------------&amp;gt;  |          DigitalOcean VPS            |      |
&lt;&#x2F;span&gt;&lt;span&gt;|  UptimeRobot |                          |                                      | &amp;lt;----+
&lt;&#x2F;span&gt;&lt;span&gt;|              |  &amp;lt;-- site unreachable    |  +--------+    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;|  alerts via  |                          |  | Caddy  |    | Nginx container  |  |
&lt;&#x2F;span&gt;&lt;span&gt;|  email&#x2F;SMS   |                          |  | :443   +---&amp;gt;| :8080            |  |
&lt;&#x2F;span&gt;&lt;span&gt;+--------------+                          |  |        |    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  | TLS    |    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  | HTTPS  +---&amp;gt;| Nginx container  |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  |        |    | :8081            |  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |  +---+----+    +------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +------+-------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                            HTTPS :443
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +------+-------+
&lt;&#x2F;span&gt;&lt;span&gt;                                          |   Visitor    |
&lt;&#x2F;span&gt;&lt;span&gt;                                          |   Browser    |
&lt;&#x2F;span&gt;&lt;span&gt;                                          +--------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you learned something, please &lt;em&gt;like, share and subscribe&lt;&#x2F;em&gt;. Here are some resources to deepen your understanding:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;devops&#x2F;comments&#x2F;1p8vyxi&#x2F;zero_downtime_deployments_without_kubernetes&#x2F;&quot;&gt;Zero downtime deploymets without K8s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.podman.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;What is Podman&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;ci&#x2F;&quot;&gt;GitLab CI&#x2F;CD documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=yxNpIL2MqEY&quot;&gt;We use containers now. Here is why&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;certbot.eff.org&#x2F;&quot;&gt;Certbot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;docs&#x2F;&quot;&gt;Caddy documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=w_lLt4lLplE&quot;&gt;The intro to Docker I wish I had when I started&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.docker.com&#x2F;resources&#x2F;what-is-container-registry&#x2F;&quot;&gt;Container registries 101&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;how-it-works&#x2F;&quot;&gt;Let&#x27;s encrypt how it works&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=W3EoZpCr1O8&quot;&gt;Playing with Caddy server&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola Documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;status.gitlab.com&#x2F;&quot;&gt;Gitlab system status&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Vectors</title>
        <published>2026-02-26T00:00:00+00:00</published>
        <updated>2026-02-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/vctrs/"/>
        <id>https://nskm.xyz/posts/vctrs/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/vctrs/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;vectors.png&quot; alt=&quot;vectors&quot; title=&quot;vectors&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Opinions&lt;&#x2F;strong&gt;: The views expressed here are my own unless otherwise specified. They do not represent any employer, organization, or affiliated group.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code examples&lt;&#x2F;strong&gt;: All code examples are educational. Production use requires careful consideration of performance, security, and your specific data characteristics.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Model choice&lt;&#x2F;strong&gt;: The &lt;code&gt;all-MiniLM-L6-v2&lt;&#x2F;code&gt; model is a practical default, but embedding model selection should depend on your domain. Consider fine-tuning for specialized use cases.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;This article is for&lt;&#x2F;strong&gt;: Django developers curious about semantic search and vector embeddings, or anyone wanting to understand how vectors fit alongside traditional structured data.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;**This article was written on a Framework laptop 16, &lt;em&gt;yeah&lt;&#x2F;em&gt;!
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;When I start a new &lt;a href=&quot;#&quot;&gt;Django&lt;&#x2F;a&gt; project, the instinct is immediate and familiar: open &lt;code&gt;models.py&lt;&#x2F;code&gt; and start writing &lt;a href=&quot;#&quot;&gt;classes&lt;&#x2F;a&gt;. I think about my entity, its attributes, its relationships, and I translate that mental model almost directly into Python. That&#x27;s great. It works. Since so many years. It&#x27;s readable. It&#x27;s what Django was built for. Amazing. Perfect. Flawless.&lt;&#x2F;p&gt;
&lt;p&gt;If you follow my amazing and colossal work, you know that since more that two years now, I&#x27;m working on a project in the public health sector. I&#x27;m handling lots and lots and lots of data. I have to answer interesting questions like... Yet, I&#x27;m still reprensenting my data using classes and attributes. Reflexes.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s another way to represent data that&#x27;s been quietly powering search engines, recommendation systems, and AI applications for years, it&#x27;s increasingly accessible to application developers like me. I should learn to use it more often. Instead of describing data as a collection of named attributes, I can describe it as a &lt;strong&gt;point in a high-dimensional space&lt;&#x2F;strong&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Vector_(mathematics_and_physics)&quot;&gt;vector&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This article walks through what that actually means, when it matters, and how to implement both approaches side by side in a real Django project. To increase your chances of understanding, it is recommended that you listen to this &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=amBBO4PqJKo&quot;&gt;track&lt;&#x2F;a&gt; while reading the article. Enjoy!&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#classical-approach&quot;&gt;The classical approach&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#vector-approach&quot;&gt;The vector approach&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#why-not-ai&quot;&gt;Why this is not just for AI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#both-approaches&quot;&gt;Both approaches in Django&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#going-further&quot;&gt;Going further&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#broader-landscape&quot;&gt;Representation models&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;vctrs&#x2F;#how-to-practice&quot;&gt;How to practice&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;classical-approach&quot;&gt;The classical approach: data as structure&lt;&#x2F;h2&gt;
&lt;p&gt;When you model a medical facility in a &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;surveillance platform&lt;&#x2F;a&gt;, you probably write something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;HealthFacility(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    region = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    facility_type = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# hospital, clinic, health_post
&lt;&#x2F;span&gt;&lt;span&gt;    capacity = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    services = models.ManyToManyField(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Service&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is &lt;strong&gt;structured representation&lt;&#x2F;strong&gt;. Data lives in named slots. Querying it means matching those slots exactly:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Find clinics in Dakar with pediatric services
&lt;&#x2F;span&gt;&lt;span&gt;HealthFacility.objects.filter(
&lt;&#x2F;span&gt;&lt;span&gt;    region=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Dakar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    facility_type=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clinic&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    services__name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pediatrics&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is powerful for what it is. You know exactly what you&#x27;re looking for, the schema enforces consistency, and &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;&quot;&gt;SQL&lt;&#x2F;a&gt; is extraordinarily good at these kinds of exact, predicate-based lookups.&lt;&#x2F;p&gt;
&lt;p&gt;The limitation reveals itself the moment your questions become fuzzy. What if you want facilities that are &lt;em&gt;similar&lt;&#x2F;em&gt; to a given one — without being able to define exactly what &quot;similar&quot; means? What if a user types &quot;district hospital with maternal care near the coast&quot; and you need to find the best match? Predicate-based filtering breaks down because similarity isn&#x27;t a predicate. It&#x27;s a geometry problem.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;vector-approach&quot;&gt;The vector approach: data as position&lt;&#x2F;h2&gt;
&lt;p&gt;A vector is simply an ordered list of numbers:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;[0.82, 0.14, 0.67, 0.03, 0.91, ...]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The idea is that you can encode the &lt;em&gt;meaning&lt;&#x2F;em&gt; or &lt;em&gt;characteristics&lt;&#x2F;em&gt; of any piece of data as a point in a high-dimensional space, such that &lt;strong&gt;things which are semantically similar end up close together&lt;&#x2F;strong&gt;, and things that are different end up far apart.&lt;&#x2F;p&gt;
&lt;p&gt;This is not hand-crafted feature engineering &lt;em&gt;(though it can be)&lt;&#x2F;em&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;spaces&#x2F;mteb&#x2F;leaderboard&quot;&gt;Modern embedding models&lt;&#x2F;a&gt; — neural networks trained on massive datasets — can take a sentence, a document, even an image, and produce a dense vector that captures its semantic content. The model has learned, from context, what concepts relate to each other. &quot;Maternal health clinic&quot; and &quot;obstetric care center&quot; will produce vectors that are very close. &quot;Warehouse&quot; will be far away.&lt;&#x2F;p&gt;
&lt;p&gt;The distance between two vectors is typically measured with &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cosine_similarity&quot;&gt;cosine similarity&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;similarity = cos(θ) = (A · B) &#x2F; (||A|| × ||B||)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A value of 1 means identical direction &lt;em&gt;(semantically equivalent)&lt;&#x2F;em&gt;. A value of 0 means orthogonal &lt;em&gt;(unrelated)&lt;&#x2F;em&gt;. This single number replaces the entire predicate matching logic.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;why-not-ai&quot;&gt;Why this is not just for AI projects&lt;&#x2F;h2&gt;
&lt;p&gt;You might think: &quot;I don&#x27;t need semantic search. I need to store patient records.&quot; That&#x27;s fair. This is exactly how I&#x27;ve done it on the &lt;a href=&quot;https:&#x2F;&#x2F;rh.pasteur.sn&#x2F;en&#x2F;research-and-public-health&#x2F;epidemiology-clinical-research-and-data-science&#x2F;fever-surveillance-syndromic-sentinel-surveillance-senegal-4s-network&quot;&gt;4S project&lt;&#x2F;a&gt;. But I&#x27;m more and more facing these new types of scenarios:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Duplicate detection.&lt;&#x2F;strong&gt; Two users register &quot;Hôpital Principal de Dakar&quot; and &quot;hopital principal dakar&quot;. Exact matching fails. Vector similarity catches them as near-duplicates.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Recommendation.&lt;&#x2F;strong&gt; &quot;Users who viewed this report also found these relevant.&quot; You don&#x27;t need a collaborative filtering setup — you can just find the reports whose vectors are closest to the one currently being read.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Free-text search that actually works.&lt;&#x2F;strong&gt; Users don&#x27;t search with your field names. They type natural language. Vectors let you match that intent.... &lt;em&gt;This one stung me very badly recently.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Clustering without labels.&lt;&#x2F;strong&gt; You have 10,000 epidemiological case reports. You want to discover natural groupings without writing filtering rules. Find neighborhoods in vector space.... We are working in this particular topic. I look at how we are implementing this feature and I am already disgusted by the direction we are taking. &lt;em&gt;Marvelous&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anomaly detection.&lt;&#x2F;strong&gt; A new weekly report has a vector that is very far from all historical ones. Flag it for review.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;both-approaches&quot;&gt;Both approaches in Django: a concrete example&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s build a very small project that models epidemiological reports using both approaches. We&#x27;ll use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgvector&#x2F;pgvector&quot;&gt;pgvector&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;docs&#x2F;current&#x2F;extend.html&quot;&gt;PostgreSQL extension&lt;&#x2F;a&gt;, so vectors live right next to our traditional Django models. No separate &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Vector_database&quot;&gt;vector databases&lt;&#x2F;a&gt;, no need for new infrastructure if you&#x27;re already on the amazing &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;&quot;&gt;Postgres&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;pip install django pgvector sentence-transformers psycopg2-binary  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# easy peasy
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Enable the extension in a Django migration:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pgvector.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;VectorExtension
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Migration(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;migrations.Migration&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    operations = [
&lt;&#x2F;span&gt;&lt;span&gt;        VectorExtension(),
&lt;&#x2F;span&gt;&lt;span&gt;    ]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-traditional-model&quot;&gt;The traditional model&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;models.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pgvector.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;VectorField
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;EpiReport(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Classical structured representation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Every piece of information lives in a named, typed field.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;255&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    region = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    disease = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    week = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    year = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;    case_count = models.IntegerField(default=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    severity = models.CharField(
&lt;&#x2F;span&gt;&lt;span&gt;        max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        choices=[(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;low&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Low&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;moderate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Moderate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;high&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;High&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    summary = models.TextField()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The vector representation lives alongside the structured one.
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 384 dimensions is the output size of the model we&amp;#39;ll use.
&lt;&#x2F;span&gt;&lt;span&gt;    embedding = VectorField(dimensions=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;384&lt;&#x2F;span&gt;&lt;span&gt;, null=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;, blank=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        indexes = [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Traditional index for structured queries
&lt;&#x2F;span&gt;&lt;span&gt;            models.Index(fields=[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]),
&lt;&#x2F;span&gt;&lt;span&gt;        ]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__str__(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{self.title}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;{self.region}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, W&lt;&#x2F;span&gt;&lt;span&gt;{self.week}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;{self.year}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;)&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that both representations coexist in the same table. This is intentional — we&#x27;re not replacing one with the other. We&#x27;re giving ourselves two different query interfaces into the same data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;generating-the-embedding&quot;&gt;Generating the embedding&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;embeddings.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;sentence_transformers &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;SentenceTransformer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# All-MiniLM-L6-v2 is small (80MB), fast, and produces 384-dim vectors.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# It runs on CPU without issue, which matters in resource-constrained environments.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# See here: https:&#x2F;&#x2F;huggingface.co&#x2F;sentence-transformers&#x2F;all-MiniLM-L6-v2
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_model = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_model():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;global &lt;&#x2F;span&gt;&lt;span&gt;_model
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;_model &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        _model = SentenceTransformer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;all-MiniLM-L6-v2&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;_model
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;embed_report(report: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;EpiReport&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; list[float]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Convert a report&amp;#39;s semantic content into a vector.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    The text we embed is a natural language description of the report,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    so the model can capture the meaning, not just the keywords.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    text = (
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{report.title}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Disease: &lt;&#x2F;span&gt;&lt;span&gt;{report.disease}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Region: &lt;&#x2F;span&gt;&lt;span&gt;{report.region}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Severity: &lt;&#x2F;span&gt;&lt;span&gt;{report.severity}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{report.summary}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    model = get_model()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;model.encode(text).tolist()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;the-two-query-styles-side-by-side&quot;&gt;The two query styles, side by side&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;queries.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pgvector.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;CosineDistance
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;EpiReport
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;embeddings &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;get_model
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ── Approach 1: Structured Query ────────────────────────────────────────────
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_high_severity_reports(region: str, disease: str, year: int):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Classical Django ORM query.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Fast, precise, requires you to know exactly what you want.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;EpiReport.objects.filter(
&lt;&#x2F;span&gt;&lt;span&gt;        region=region,
&lt;&#x2F;span&gt;&lt;span&gt;        disease=disease,
&lt;&#x2F;span&gt;&lt;span&gt;        year=year,
&lt;&#x2F;span&gt;&lt;span&gt;        severity=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;high&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    ).order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-week&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ── Approach 2: Semantic Vector Query ───────────────────────────────────────
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;find_similar_reports(query: str, top_k: int = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Vector similarity search.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    The query is natural language. No schema knowledge required.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Returns the most semantically similar reports.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    model = get_model()
&lt;&#x2F;span&gt;&lt;span&gt;    query_vector = model.encode(query).tolist()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        EpiReport.objects
&lt;&#x2F;span&gt;&lt;span&gt;        .annotate(distance=CosineDistance(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;embedding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, query_vector))
&lt;&#x2F;span&gt;&lt;span&gt;        .order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)[:top_k]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;find_similar_to_report(report: EpiReport, top_k: int = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Given an existing report, find others that are semantically similar.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Useful for &amp;quot;related reports&amp;quot; features or duplicate detection.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        EpiReport.objects
&lt;&#x2F;span&gt;&lt;span&gt;        .exclude(pk=report.pk)
&lt;&#x2F;span&gt;&lt;span&gt;        .annotate(distance=CosineDistance(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;embedding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, report.embedding))
&lt;&#x2F;span&gt;&lt;span&gt;        .order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)[:top_k]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;wiring-it-into-views&quot;&gt;Wiring it into views&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# surveillance&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.http &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;EpiReport
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;queries &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;get_high_severity_reports, find_similar_reports
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;structured_search(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Traditional form-based search.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    reports = get_high_severity_reports(
&lt;&#x2F;span&gt;&lt;span&gt;        region=request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        disease=request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;        year=int(request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2024&lt;&#x2F;span&gt;&lt;span&gt;)),
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse({
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;approach&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;structured&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;results&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: list(reports.values(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;severity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;semantic_search(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Free-text semantic search.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    query = request.GET.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;q&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    reports = find_similar_reports(query, top_k=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse({
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;approach&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;vector&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;query&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: query,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;results&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: r.title,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;region&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: r.region,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;disease&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: r.disease,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;similarity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: round(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;- r.distance, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;),  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# convert distance to similarity
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;reports
&lt;&#x2F;span&gt;&lt;span&gt;        ]
&lt;&#x2F;span&gt;&lt;span&gt;    })
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now try these two requests:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;GET &#x2F;search&#x2F;structured&#x2F;?region=Dakar&amp;amp;disease=cholera&amp;amp;year=2024
&lt;&#x2F;span&gt;&lt;span&gt;GET &#x2F;search&#x2F;semantic&#x2F;?q=waterborne disease outbreaks in coastal areas
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The structured search finds exactly what you specified. The semantic search finds what you &lt;em&gt;meant&lt;&#x2F;em&gt;, even if those exact words don&#x27;t appear anywhere in your data. The world is beautiful.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;when-to-use&quot;&gt;When to use which&lt;&#x2F;h2&gt;
&lt;p&gt;On top of my tiny experience, and as a software engineer who has never used this technique on &lt;em&gt;on production&lt;&#x2F;em&gt;, I would say the right answer for most systems is both. And pgvector makes that even more practical without adding infrastructure complexity.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Lean on structured queries&lt;&#x2F;strong&gt; when you need exactness: filtering by date range, counting cases, producing regulatory reports, joining across tables. SQL is unbeatable here.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Lean on vector queries&lt;&#x2F;strong&gt; when you need semantic understanding: search boxes, recommendation engines, duplicate detection, anomaly flagging, clustering, or any time a user&#x27;s intent can&#x27;t be reduced to a dropdown value.&lt;&#x2F;p&gt;
&lt;p&gt;Even more interesting, &lt;strong&gt;hybrid search&lt;&#x2F;strong&gt;: use structured filters to narrow the candidate set, then rank the survivors by vector similarity:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;hybrid_search(region: str, query: str, top_k: int = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    Filter structurally, then rank semantically.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    This is typically the most useful approach in production.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    model = get_model()
&lt;&#x2F;span&gt;&lt;span&gt;    query_vector = model.encode(query).tolist()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        EpiReport.objects
&lt;&#x2F;span&gt;&lt;span&gt;        .filter(region=region)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# hard filter: only this region
&lt;&#x2F;span&gt;&lt;span&gt;        .annotate(distance=CosineDistance(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;embedding&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, query_vector))
&lt;&#x2F;span&gt;&lt;span&gt;        .order_by(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)[:top_k]
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;going-further&quot;&gt;Going further&lt;&#x2F;h2&gt;
&lt;p&gt;Once you&#x27;ve internalized the two-lens model, here&#x27;s where to take it next:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-fine-tune-your-own-embedding-model-on-domain-data&quot;&gt;1. Fine-tune your own embedding model on domain data&lt;&#x2F;h3&gt;
&lt;p&gt;The &lt;code&gt;all-MiniLM-L6-v2&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.sbert.net&#x2F;&quot;&gt;model&lt;&#x2F;a&gt; was trained on general English text. It has no idea that &quot;paludisme&quot; and &quot;malaria&quot; are the same thing, or that &quot;cas suspects&quot; and &quot;suspected cases&quot; are equivalent in my context. Training a domain-specific embedding model on my own epidemiological corpus — even with a small dataset using contrastive learning — would make similarity search dramatically more meaningful.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-retrieval-augmented-generation-rag-on-top-of-our-vector-store&quot;&gt;2. Retrieval-augmented generation (RAG) on top of our vector store&lt;&#x2F;h3&gt;
&lt;p&gt;Once we have a vector store of reports, we&#x27;re one step away from a system that can &lt;em&gt;answer questions&lt;&#x2F;em&gt; about your data in natural language. A user asks: &lt;em&gt;&quot;What were the major respiratory disease trends in Guinea-Bissau in 2023?&quot;&lt;&#x2F;em&gt; — our system retrieves the most relevant reports by vector similarity, then feeds them as context to an &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Large_language_model&quot;&gt;LLM&lt;&#x2F;a&gt; that synthesizes a coherent answer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-vectors-for-anomaly-detection-in-surveillance-data&quot;&gt;3. Vectors for anomaly detection in surveillance data&lt;&#x2F;h3&gt;
&lt;p&gt;Every week a new batch of case reports comes in. &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#engineers&quot;&gt;We&lt;&#x2F;a&gt; can embed each report and compare it to the historical distribution of vectors for that region and disease. A report that lands far from the cluster is a statistical anomaly, potentially a real &lt;a href=&quot;https:&#x2F;&#x2F;www.who.int&#x2F;activities&#x2F;epidemic-and-pandemic-monitoring&quot;&gt;outbreak signal&lt;&#x2F;a&gt;. This turns our vector store into a passive early-warning system without writing any explicit outbreak-detection rules.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;4-multimodal-embeddings&quot;&gt;4. Multimodal embeddings&lt;&#x2F;h3&gt;
&lt;p&gt;Text isn&#x27;t the only thing we can embed. We can embed laboratory results, genomic sequences, geographic coordinates combined with case counts, even scanned paper forms via vision models. The moment we have multiple modalities in the same vector space, we can do cross-modal search: &lt;em&gt;find reports whose geographic spread pattern resembles this map image.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;placeholder image for brain explosion&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5-the-theory-underneath-why-vector-spaces-work&quot;&gt;5. The theory underneath: why vector spaces work&lt;&#x2F;h3&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;broader-landscape&quot;&gt;Representation models: other ways to represent data&lt;&#x2F;h2&gt;
&lt;p&gt;Structured attributes and vectors are two lenses. And there are other ways to represent data:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot;&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;th style=&quot;border: 1px solid #ddd; padding: 12px; text-align: left;&quot;&gt;Representation&lt;&#x2F;th&gt;
    &lt;th style=&quot;border: 1px solid #ddd; padding: 12px; text-align: left;&quot;&gt;Best question it answers&lt;&#x2F;th&gt;
    &lt;th style=&quot;border: 1px solid #ddd; padding: 12px; text-align: left;&quot;&gt;Tools&lt;&#x2F;th&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Class + attributes&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;What does this thing have?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Django ORM, PostgreSQL&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Vector&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;What is this thing like?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;pgvector, sentence-transformers&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Graph&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How does this thing connect?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Neo4j, networkx&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Event stream&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How did this thing become what it is?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Kafka, EventStoreDB&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Logic &#x2F; facts&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;What can we conclude about this thing?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Prolog, Datalog, RDF&#x2F;OWL&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Probability&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How certain are we about this thing?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;PyMC, Stan&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Spatial&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Where is this thing, relative to what?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;PostGIS, GeoDjango&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
  &lt;tr style=&quot;border: 1px solid #ddd;&quot;&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;Tensor&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;How does this vary across multiple dimensions?&lt;&#x2F;td&gt;
    &lt;td style=&quot;border: 1px solid #ddd; padding: 12px;&quot;&gt;NumPy, PyTorch, Xarray&lt;&#x2F;td&gt;
  &lt;&#x2F;tr&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;how-to-practice&quot;&gt;How to practice&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t need production data to start experimenting with vectors and embeddings:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Local development:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.trychroma.com&#x2F;&quot;&gt;Chroma&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Lightweight vector database that runs locally or in Docker.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;r&#x2F;pgvector&#x2F;pgvector&quot;&gt;pgvector in Docker&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A local PostgreSQL with pgvector extension in seconds.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sbert.net&#x2F;docs&#x2F;pretrained_models.html&quot;&gt;Sentence Transformers Models&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Experiment with domain-specific models beyond all-MiniLM-L6-v2.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Learning resources:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;models&quot;&gt;Hugging Face Hub&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: 100k+ pre-trained models. Read papers, compare benchmark results.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;huggingface.co&#x2F;learn&quot;&gt;Embedding Models Course&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Free, practical introduction to embeddings.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgvector&#x2F;pgvector&quot;&gt;pgvector Documentation&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: All indexing strategies and similarity operators explained.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;As a Django engineer, my mental model of &quot;data as class with attributes&quot; is solid and won&#x27;t stop serving &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;patrick_dikiesse.pdf&quot;&gt;me&lt;&#x2F;a&gt;. But it&#x27;s worth internalizing that it&#x27;s one of at least two valid representations. I should definitely start to think of my data as having a &lt;em&gt;position&lt;&#x2F;em&gt; in semantic space, a whole class of problems (search, similarity, anomaly, clustering) will become natural rather than bespoke.&lt;&#x2F;p&gt;
&lt;p&gt;Here we are, we wanted a banana but we received a gorilla holding the banana and the entire jungle. Here are some links to help you &lt;em&gt;(and me, let&#x27;s be honest)&lt;&#x2F;em&gt; go further and tame the beast:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;dev_kiran&#x2F;embeddings-the-hidden-power-behind-ai-search-21eb&quot;&gt;The hidden power behind AI &amp;amp; search&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sbert.net&#x2F;docs&#x2F;training&#x2F;overview.html&quot;&gt;Fine-tuning sentence transformers&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;vickiboykis.com&#x2F;what_are_embeddings&#x2F;&quot;&gt;Vector database comparison&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lilianweng.github.io&#x2F;posts&#x2F;2021-05-31-contrastive&#x2F;&quot;&gt;Contrastive learning explained&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2005.11401&quot;&gt;Retrieval-Augmented Generation (RAG)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pgvector&#x2F;pgvector#performance&quot;&gt;pgvector performance tuning&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cs.utexas.edu&#x2F;~EWD&#x2F;transcriptions&#x2F;EWD06xx&#x2F;EWD667.html&quot;&gt;On the foolishness of &quot;natural language programming&quot;&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you found this article useful, &lt;em&gt;please like, share and subscribe&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;while-i-still-have-your-attention&quot;&gt;While I still have your attention&lt;&#x2F;h2&gt;
&lt;p&gt;The Norwegian Consumer Council is an independent, governmentally funded organisation that advocates for consumer’s rights. It should be easy for consumers to make sustainable choices every day. Consumers have the right to be protected against exploitation – both financially and digitally. To ensure this, we work to provide easy access to information, enforceable rights, and sufficient redress options when something goes wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Digital products and services keep getting worse. In the new report Breaking Free: Pathways to a fair technological future, the Norwegian Consumer Council has delved into &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=T4Upf_B9RLQ&quot;&gt;enshittification&lt;&#x2F;a&gt; and how to resist it. The report shows how this phenomenon affects both consumers and society at large, but that it is possible to &lt;a href=&quot;https:&#x2F;&#x2F;www.forbrukerradet.no&#x2F;breakingfree&quot;&gt;turn the tide.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Geez&lt;&#x2F;em&gt;, I would have loved to see African leaders do the same....&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Recap)</title>
        <published>2026-02-12T00:00:00+00:00</published>
        <updated>2026-02-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-recap/"/>
        <id>https://nskm.xyz/posts/aws-recap/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-recap/">&lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;proud_of_you.gif&quot; alt=&quot;Proud of myself&quot; title=&quot;Proud of myself&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers:&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece. If you catch any errors, please reach out — I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Structural truth about intensive training formats: you can cover a lot of ground in a week, but covering ground is not the same as owning it. There is a fundamental difference between &lt;em&gt;understanding&lt;&#x2F;em&gt; the concepts and &lt;em&gt;having debugged a deployment issue at 11pm before a production deployment&lt;&#x2F;em&gt;. The gap between &quot;I understand this&quot; and &quot;I can do this under pressure&quot; is filled only by practice — and eight days of excellent training doesn&#x27;t close it.&lt;&#x2F;p&gt;
&lt;p&gt;10 days of training, a lot of diagrams drawn on whiteboards, 5 instructors who clearly knew their material. I would like to thank them very much; I have learnt a great deal thanks to them.&lt;&#x2F;p&gt;
&lt;p&gt;With this article, I would like to take a step back to look at what we built, what was, &lt;em&gt;imho&lt;&#x2F;em&gt;, missing and what is the next step.... &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=75wmW7xjyog&quot;&gt;Music&lt;&#x2F;a&gt; please!&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#the-platform-we-built&quot;&gt;The platform we built&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#why-in-this-order&quot;&gt;Why in this order&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#day-7-the-piece-thats-missing&quot;&gt;Ansible: the piece that&#x27;s missing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#what-we-didnt-cover&quot;&gt;What we didn&#x27;t cover&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#where-to-go-from-here&quot;&gt;Where to go from here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-recap&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-platform-we-built&quot;&gt;The platform we built&lt;&#x2F;h2&gt;
&lt;p&gt;This 10 days training series actually produced a concrete thing: how to build Django REST APIs handling patient analyses and clinical consultation data, running on a K8s cluster on AWS, secured at every layer, deployable in any environment in minutes, and fully observable.&lt;&#x2F;p&gt;
&lt;p&gt;Here is what that means in practice:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;private VPC&lt;&#x2F;strong&gt; in a region with public subnets for load balancers and private subnets for everything else&lt;&#x2F;li&gt;
&lt;li&gt;An &lt;strong&gt;EKS cluster&lt;&#x2F;strong&gt; provisioned with managed node groups, with etcd encrypted at rest using a KMS key&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;IAM roles&lt;&#x2F;strong&gt; for every component that needs AWS access, &lt;strong&gt;IRSA or EKS Pod Identity&lt;&#x2F;strong&gt; for pods&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RBAC&lt;&#x2F;strong&gt; scoped to namespaces: the genomics team can only touch the genomics namespace, the clinical trials team theirs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Network policies&lt;&#x2F;strong&gt; enforcing zero-trust between pods: no pod talks to another unless explicitly allowed&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Secrets&lt;&#x2F;strong&gt; stored in AWS Secrets Manager, synced into Kubernetes at runtime by the External Secrets Operator&lt;&#x2F;li&gt;
&lt;li&gt;The entire infrastructure &lt;strong&gt;provisioned by Terraform&lt;&#x2F;strong&gt; — reproducible in any environment&lt;&#x2F;li&gt;
&lt;li&gt;The Django Rest APIs &lt;strong&gt;packaged as a Helm charts&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The charts stored in &lt;strong&gt;ECR alongside the Docker images&lt;&#x2F;strong&gt;, accessible to any teammate with the right IAM permissions&lt;&#x2F;li&gt;
&lt;li&gt;Platform &lt;strong&gt;instrumented with OpenTelemetry&lt;&#x2F;strong&gt;: metrics sent to &lt;strong&gt;Prometheus&lt;&#x2F;strong&gt;, logs to &lt;strong&gt;Loki&lt;&#x2F;strong&gt;, traces to &lt;strong&gt;Jaeger&lt;&#x2F;strong&gt;, all visualised in &lt;strong&gt;Grafana&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;SLOs&lt;&#x2F;strong&gt; defined for the Rest APIs, with Alertmanager firing when the error budget burns too fast&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-in-this-order&quot;&gt;What we built, why in this order&lt;&#x2F;h2&gt;
&lt;p&gt;Layers on layers on layers. Each layer depended on the one before it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;Foundations&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — VPC, compute, storage, regions. Before anything else, you need to understand the environment your workloads will run in. Network topology is a first-class architectural decision.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;Identity and access&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — IAM, OIDC, KMS, CloudTrail. IAM roles and encryption are established &lt;em&gt;before&lt;&#x2F;em&gt; the cluster exists, because the cluster will inherit them from day one. It&#x27;s difficult to retroactively secure a system that was built without security in mind.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Orchestration&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Kubernetes, EKS, pods, deployments, services. To run workloads at scale, self-heal them, and expose them, without managing individual servers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;Workload security&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — RBAC, network policies, pod security, secrets management. You have a running cluster. Now lock down what runs inside it. The defaults are permissive by design; the hardening is your responsibility.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;Automation&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Terraform, Helm. You have built &amp;amp; secured a cluster you understand. Now make it reproducible. The goal is to never click through the console again — for infrastructure or for deployments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;&quot;&gt;Observability&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Prometheus, Loki, Jaeger, OpenTelemetry, SLOs. The platform runs, is secured, and is automated. Now make it visible. You cannot maintain what you cannot see.&lt;&#x2F;p&gt;
&lt;p&gt;Mental model: &lt;strong&gt;build → orchestrate → secure → automate → observe&lt;&#x2F;strong&gt;. Each verb assumes the previous one is done. You cannot automate what you have not secured. And you do not observe what you have not deployed. &lt;em&gt;Phew!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;day-7-the-piece-thats-missing&quot;&gt;Ansible: the piece that&#x27;s missing&lt;&#x2F;h2&gt;
&lt;p&gt;Somewhere during the training, we covered &lt;strong&gt;Ansible&lt;&#x2F;strong&gt;. I chose to not talk about it as part of this series.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, Ansible is useful and complementary to Terraform, Helm &amp;amp; Kubernetes, but not strictly essential. If you are using fully managed Kubernetes services (like AWS EKS or GKE) where the cloud provider manages the underlying node configuration, the need for Ansible is reduced.&lt;&#x2F;p&gt;
&lt;p&gt;On Kubernetes, the configuration management layer is largely handled by Helm values, ConfigMaps, and Secrets. Ansible&#x27;s strengths shine on EC2 instances, bastion hosts, and hybrid environments — which were not the primary focus of this training.&lt;&#x2F;p&gt;
&lt;p&gt;In all the cases, I&#x27;m not saying Ansible is worthless, it is absolutely worth learning. The &lt;a href=&quot;https:&#x2F;&#x2F;docs.ansible.com&#x2F;&quot;&gt;official documentation&lt;&#x2F;a&gt; and the &lt;a href=&quot;https:&#x2F;&#x2F;www.ansiblefordevops.com&#x2F;&quot;&gt;Ansible for DevOps book&lt;&#x2F;a&gt; by Jeff Geerling are the right starting points.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-we-didnt-cover&quot;&gt;What we didn&#x27;t cover&lt;&#x2F;h2&gt;
&lt;p&gt;While I agree the instructors gave the best they could, while I agree we cannot cover everything in 10 days, the following topics are the ones I wish were addressed:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CI&#x2F;CD pipelines&lt;&#x2F;strong&gt; — how does a git push become a Docker image in ECR and a Helm upgrade on the cluster? I know 1 or 2 things about this topic but I wish the instructors had said a few words about that.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;GitOps&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;argoproj.github.io&#x2F;cd&#x2F;&quot;&gt;ArgoCD&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;fluxcd.io&#x2F;&quot;&gt;Flux&lt;&#x2F;a&gt; take Helm one step further: Git becomes the single source of truth, and the cluster continuously reconciles itself against what&#x27;s in the repository. This is how most mature platform teams deploy today.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Service mesh&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;&quot;&gt;Istio&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;linkerd.io&#x2F;&quot;&gt;Linkerd&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;cilium.io&#x2F;&quot;&gt;Cilium&lt;&#x2F;a&gt; add mTLS between services, fine-grained traffic management, and advanced observability at the network layer. Once your platform has dozens of services, a service mesh stops being optional.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Backup and restore&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;velero.io&#x2F;&quot;&gt;Velero&lt;&#x2F;a&gt; backs up Kubernetes resources and persistent volumes. What happens when someone deletes the wrong namespace in production?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Multi-region and disaster recovery&lt;&#x2F;strong&gt; — what happens when &lt;code&gt;eu-west-3&lt;&#x2F;code&gt; has an incident? For a platform handling patient data, this is a compliance question as much as a technical one.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Image scanning in CI&lt;&#x2F;strong&gt; — &lt;a href=&quot;https:&#x2F;&#x2F;trivy.dev&#x2F;&quot;&gt;Trivy&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;snyk.io&#x2F;&quot;&gt;Snyk&lt;&#x2F;a&gt; scan Docker images for known vulnerabilities before they ever reach the cluster. Security in the build pipeline, not just at runtime.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-to-go-from-here&quot;&gt;Where to go from here&lt;&#x2F;h2&gt;
&lt;p&gt;Then, explore &lt;strong&gt;ArgoCD&lt;&#x2F;strong&gt;. Point it at an Helm chart repository in ECR, and let it manage deployments declaratively. That&#x27;s the missing link between Day 6 and a production-grade deployment workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, set up the observability stack from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;&quot;&gt;Day 8&lt;&#x2F;a&gt; and use it to actually find out why&#x2F;when something broke. Today, I&#x27;ll be honest, if something break, The only thing I have to help me sort this out are the &lt;a href=&quot;https:&#x2F;&#x2F;i.programmerhumor.io&#x2F;2025&#x2F;11&#x2F;6d58f6fc8886c2da6ee0215f5a2e00207595c36ef43031d9e9ec33741120dcc3.jpg&quot;&gt;logs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;writing.gif&quot; alt=&quot;Planning the next step&quot; title=&quot;Planning the next step&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Ten days of excellent content, delivered by people who clearly knew what they were talking about, thanks a million to them. I know the vocabulary, I still need to pratice, a lot, to own the skills. Writing these articles was the first step in that direction. Now &lt;em&gt;I need a credit card.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;You know the drill.... see ya o&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;CI&#x2F;CD and GitOps:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;actions&quot;&gt;GitHub Actions documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;argo-cd.readthedocs.io&#x2F;&quot;&gt;ArgoCD documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fluxcd.io&#x2F;docs&#x2F;&quot;&gt;Flux documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MeU5_k9ssrs&quot;&gt;GitOps with ArgoCD — tutorial&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Service mesh:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;istio.io&#x2F;latest&#x2F;docs&#x2F;&quot;&gt;Istio documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;linkerd.io&#x2F;docs&#x2F;&quot;&gt;Linkerd documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.cilium.io&#x2F;&quot;&gt;Cilium documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Cost and autoscaling:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kubecost.com&#x2F;&quot;&gt;Kubecost&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;karpenter.sh&#x2F;docs&#x2F;&quot;&gt;Karpenter documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Backup and resilience:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;velero.io&#x2F;docs&#x2F;&quot;&gt;Velero documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Going deeper on what was covered:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;AWS EKS best practices guide&lt;&#x2F;a&gt; — the authoritative reference for everything in Days 4 and 5&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;table-of-contents&#x2F;&quot;&gt;Google SRE book&lt;&#x2F;a&gt; — the canonical text behind the SLI&#x2F;SLO&#x2F;SLA framework from Day 8&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ansiblefordevops.com&#x2F;&quot;&gt;Ansible for DevOps&lt;&#x2F;a&gt; — Jeff Geerling&#x27;s book, the right starting point for Day 7&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;terraformbook.com&#x2F;&quot;&gt;The Terraform Book&lt;&#x2F;a&gt; — for going deeper on Day 6&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;modern_infrastructure.webp&quot; alt=&quot;Modern infrastructure&quot; title=&quot;Modern infrastructure&quot;&#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 8)</title>
        <published>2026-02-11T00:00:00+00:00</published>
        <updated>2026-02-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-8/"/>
        <id>https://nskm.xyz/posts/aws-8/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-8/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;observability2.gif&quot; alt=&quot;Me, observing&quot; title=&quot;Me observing&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;. The examples are intentionally simplified for clarity. All tools featured here are free and open-source software — they run identically on EKS, GKE, bare metal, or your laptop.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece. If you catch any errors, please reach out — I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A special thank you to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&#x2F;&quot;&gt;Mame Astou&lt;&#x2F;a&gt; aka &quot;Madame La Directrice&quot; for taking the time to review this article.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;The genomics API is running. &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;Terraform provisioned the cluster&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#helm-kubernetes-package-manager&quot;&gt;Helm deployed the application&lt;&#x2F;a&gt;. From the outside, everything looks fine.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Then, a researcher reports that their variant analysis job submitted two hours ago still hasn&#x27;t returned results. You check Kubernetes: the pods are running. You check the load balancer: it&#x27;s healthy. The deployment logs show no errors. But &lt;em&gt;something&lt;&#x2F;em&gt; is wrong, and you have absolutely no idea where to start looking.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s the moment you realise your system is &lt;strong&gt;blind&lt;&#x2F;strong&gt;. You built the infrastructure. You secured it. You automated its deployment. And then you flew it into production with no instruments.&lt;&#x2F;p&gt;
&lt;p&gt;This article is about fixing that. Not by adding monitoring as an afterthought, but by building the kind of visibility that lets you answer three questions before your users even notice a problem: &lt;strong&gt;what is happening, why is it happening, and where exactly is it happening?&lt;&#x2F;strong&gt; No worries, I&#x27;m not there yet. Lord knows how much 4s misses observability &amp;amp; monitoring :\&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#observability-vs-monitoring&quot;&gt;Observability vs monitoring&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#the-four-pillars&quot;&gt;The four pillars&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#the-tooling-landscape&quot;&gt;The tooling landscape&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#opentelemetry-the-collection-standard&quot;&gt;OpenTelemetry: the collection standard&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#sli-slo-sla-from-data-to-accountability&quot;&gt;SLI, SLO, SLA: from data to accountability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-8&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;observability-vs-monitoring&quot;&gt;Observability vs monitoring&lt;&#x2F;h2&gt;
&lt;p&gt;These two words are often used interchangeably. They shouldn&#x27;t be.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Monitoring&lt;&#x2F;strong&gt; is about watching &lt;em&gt;known&lt;&#x2F;em&gt; failure modes. You define thresholds — CPU above 80%, error rate above 1% — and you alert when they&#x27;re crossed. It answers the question: &lt;em&gt;&quot;is this thing I already know about happening?&quot;&lt;&#x2F;em&gt; Monitoring is reactive: you first have to know what can go wrong before you can monitor for it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Observability&lt;&#x2F;strong&gt; is about understanding &lt;em&gt;unknown&lt;&#x2F;em&gt; failure modes from the outside. A system is observable if you can ask arbitrary questions about its internal state — without having predicted those questions in advance. It answers: &lt;em&gt;&quot;why is this behaving the way it is?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In practice, you need both. Monitoring te dit &quot;quelque chose est cassé&quot;. Observability te permet de répondre à &quot;pourquoi est-ce cassé, exactement, pour qui, depuis quand, et dans quel contexte&quot; — même pour des pannes que tu n&#x27;avais pas anticipées.&lt;&#x2F;p&gt;
&lt;p&gt;In a K8s cluster, failures are often not the ones you predicted. A genomic analysis pipeline stalls not because of high CPU, but because a database connection pool is exhausted by a single slow query in one namespace — and your monitoring threshold was on the wrong metric entirely. Observability gives you the tools to discover that. Monitoring alone doesn&#x27;t.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;observability_diagram.svg&quot; alt=&quot;observability&quot; title=&quot;observability&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;monitoring_diagram.svg&quot; alt=&quot;monitoring&quot; title=&quot;monitoring&quot;&#x2F;&gt;  
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-four-pillars&quot;&gt;The four pillars&lt;&#x2F;h2&gt;
&lt;p&gt;Cloud-native observability is built on four pillars. Together, they give you a complete picture of a running system.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;logs-what-happened&quot;&gt;Logs — what happened&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;signals&#x2F;logs&#x2F;&quot;&gt;Logs&lt;&#x2F;a&gt; are timestamped records of discrete events: a request came in, a query failed, a job completed. They are the most familiar signal and the easiest to produce — every Django app already writes logs.&lt;&#x2F;p&gt;
&lt;p&gt;On Kubernetes, logs have a structural challenge: pods are ephemeral. When a pod crashes and restarts, its logs disappear. You need a &lt;strong&gt;log aggregation layer&lt;&#x2F;strong&gt; that collects logs from all pods, across all nodes, and stores them centrally before they vanish.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;What exactly happened at 14:32:07 in the genomics namespace?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;metrics-how-much&quot;&gt;Metrics — how much&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;signals&#x2F;metrics&#x2F;&quot;&gt;Metrics&lt;&#x2F;a&gt; are numeric measurements sampled over time: request rate, error rate, latency percentiles, CPU usage, memory consumption, active database connections. They are cheap to store, fast to query, and ideal for alerting and dashboards.&lt;&#x2F;p&gt;
&lt;p&gt;Metrics don&#x27;t tell you &lt;em&gt;why&lt;&#x2F;em&gt; something is slow — but they tell you &lt;em&gt;that&lt;&#x2F;em&gt; it is slow and &lt;em&gt;when&lt;&#x2F;em&gt; it started.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;How many analysis requests failed in the last hour, and is that number growing?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;traces-the-full-journey&quot;&gt;Traces — the full journey&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;concepts&#x2F;signals&#x2F;traces&#x2F;&quot;&gt;trace&lt;&#x2F;a&gt; follows a single request through every service it touches. In a microservices or multi-component architecture, a single API call might touch a Django view, a Celery task, a PostgreSQL query, and an S3 upload. A trace connects all of these into a single timeline, with durations for each step.&lt;&#x2F;p&gt;
&lt;p&gt;Traces are the pillar that answers the question logs and metrics can&#x27;t: &lt;em&gt;&quot;the request was slow — but which part of it was slow?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;The variant analysis request took 4.2 seconds — 3.8 seconds of which was a single database query in the pipeline.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;kubernetes-events-what-the-cluster-decided&quot;&gt;Kubernetes events — what the cluster decided&lt;&#x2F;h3&gt;
&lt;p&gt;Kubernetes &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;kubernetes-api&#x2F;cluster-resources&#x2F;event-v1&#x2F;&quot;&gt;emits events&lt;&#x2F;a&gt; for everything it does: pod scheduled, pod evicted, image pull failed, node pressure detected, HPA scaled up. These events are not logs (they come from the control plane, not the application) and not metrics (they are discrete, not continuous). They are a fourth pillar that explains &lt;em&gt;cluster-level&lt;&#x2F;em&gt; behaviour.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Answers: &quot;The pod restarted three times because the node ran out of memory — not because the application crashed.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-tooling-landscape&quot;&gt;The tooling landscape&lt;&#x2F;h2&gt;
&lt;p&gt;Two paths exist for implementing this stack on Kubernetes.&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Signal&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS-native&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Open source&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Logs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Logs&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Loki + Promtail&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Metrics&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Metrics&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Prometheus + node-exporter&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Traces&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS X-Ray&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Jaeger&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Visualisation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Dashboards&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Grafana&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Instrumentation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS Distro for OpenTelemetry&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;OpenTelemetry&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Alerting&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch Alarms&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Prometheus Alertmanager&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;We are going with the &lt;strong&gt;open-source stack&lt;&#x2F;strong&gt;. These tools run identically on EKS, GKE, bare metal, or your laptop. They have no vendor lock-in, no per-metric pricing, and a massive community behind each of them. If the genomics platform ever moves off AWS, the observability layer moves with it unchanged.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-the-pieces-fit-together&quot;&gt;How the pieces fit together&lt;&#x2F;h3&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Django app
&lt;&#x2F;span&gt;&lt;span&gt;  └─ OTel SDK (auto-instrumentation)
&lt;&#x2F;span&gt;&lt;span&gt;       └─ OTel Collector
&lt;&#x2F;span&gt;&lt;span&gt;            ├─ metrics ──→ Prometheus ──→ Grafana
&lt;&#x2F;span&gt;&lt;span&gt;            ├─ logs ─────→ Loki ─────────→ Grafana
&lt;&#x2F;span&gt;&lt;span&gt;            └─ traces ───→ Jaeger ────────→ Grafana
&lt;&#x2F;span&gt;&lt;span&gt;                                    Alertmanager ──→ PagerDuty &#x2F; Slack
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A single &lt;strong&gt;OTel Collector&lt;&#x2F;strong&gt; acts as the central routing layer — your application sends all three signal types to one endpoint, and the collector fans them out to the right backends. Grafana sits on top of all three, giving you a unified view. This architecture means your application code only knows about one destination: the collector.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deploying-the-stack-with-helm&quot;&gt;Deploying the stack with Helm&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;From Day 6&lt;&#x2F;a&gt;, you already know how to use Helm. The entire observability stack is available as Helm charts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;helm repo add prometheus-community https:&#x2F;&#x2F;prometheus-community.github.io&#x2F;helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add grafana https:&#x2F;&#x2F;grafana.github.io&#x2F;helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add jaegertracing https:&#x2F;&#x2F;jaegertracing.github.io&#x2F;helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add open-telemetry https:&#x2F;&#x2F;open-telemetry.github.io&#x2F;opentelemetry-helm-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo update
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Prometheus + Grafana + Alertmanager — all in one chart
&lt;&#x2F;span&gt;&lt;span&gt;helm install kube-prometheus-stack \
&lt;&#x2F;span&gt;&lt;span&gt;  prometheus-community&#x2F;kube-prometheus-stack \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Loki + Promtail (log collection from all pods)
&lt;&#x2F;span&gt;&lt;span&gt;helm install loki grafana&#x2F;loki-stack \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring \
&lt;&#x2F;span&gt;&lt;span&gt;  --set promtail.enabled=true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Jaeger (distributed tracing backend)
&lt;&#x2F;span&gt;&lt;span&gt;helm install jaeger jaegertracing&#x2F;jaeger \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# OpenTelemetry Collector (the routing layer)
&lt;&#x2F;span&gt;&lt;span&gt;helm install otel-collector \
&lt;&#x2F;span&gt;&lt;span&gt;  open-telemetry&#x2F;opentelemetry-collector \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace monitoring \
&lt;&#x2F;span&gt;&lt;span&gt;  --values otel-collector-values.yaml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;opentelemetry-the-collection-standard&quot;&gt;OpenTelemetry: the collection standard&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;&quot;&gt;OpenTelemetry&lt;&#x2F;a&gt; (OTel) is a CNCF project that provides a single, vendor-neutral standard for producing and collecting observability data. Before OTel, you needed separate SDKs for Prometheus, Jaeger, and your logging library — each with different APIs and configuration. OTel unifies them: one SDK, one wire protocol, one collector.&lt;&#x2F;p&gt;
&lt;p&gt;It has two parts: the &lt;strong&gt;SDK&lt;&#x2F;strong&gt; (what you add to your application to produce telemetry) and the &lt;strong&gt;Collector&lt;&#x2F;strong&gt; (the agent that receives, processes, and exports it).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-otel-collector-central-routing&quot;&gt;The OTel Collector: central routing&lt;&#x2F;h3&gt;
&lt;p&gt;The collector is configured as a pipeline: receivers → processors → exporters. Here is the configuration for our stack (&lt;code&gt;otel-collector-values.yaml&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;protocols&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;grpc&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;0.0.0.0:4317&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;0.0.0.0:4318&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;: {}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limit_mib&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;512
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;prometheus&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0.0.0.0:8889&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;loki&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;http:&#x2F;&#x2F;loki:3100&#x2F;loki&#x2F;api&#x2F;v1&#x2F;push&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;jaeger&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoint&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;jaeger-collector:14250&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tls&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;insecure&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pipelines&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metrics&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prometheus&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;logs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;loki&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;traces&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;receivers&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;otlp&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;processors&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;memory_limiter&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;exporters&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;jaeger&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Three pipelines, three backends — your application only talks to port 4317.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;instrumenting-the-django-api&quot;&gt;Instrumenting the Django API&lt;&#x2F;h3&gt;
&lt;p&gt;The genomics API needs two things: a way to produce telemetry (the OTel SDK) and a way to expose metrics for Prometheus to scrape (the &lt;code&gt;django-prometheus&lt;&#x2F;code&gt; package).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Dependencies:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;pip install \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-sdk \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-instrumentation-django \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-instrumentation-psycopg2 \
&lt;&#x2F;span&gt;&lt;span&gt;  opentelemetry-exporter-otlp-proto-grpc \
&lt;&#x2F;span&gt;&lt;span&gt;  django-prometheus
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Auto-instrumentation setup&lt;&#x2F;strong&gt; — the right place to call this is &lt;code&gt;AppConfig.ready()&lt;&#x2F;code&gt; in your app&#x27;s &lt;code&gt;apps.py&lt;&#x2F;code&gt;, which runs exactly once on startup regardless of whether you&#x27;re using &lt;code&gt;manage.py&lt;&#x2F;code&gt;, a WSGI server, or an ASGI server:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;trace
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.sdk.trace &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;TracerProvider
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.sdk.trace.export &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;BatchSpanProcessor
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.exporter.otlp.proto.grpc.trace_exporter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;OTLPSpanExporter
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.instrumentation.django &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;DjangoInstrumentor
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry.instrumentation.psycopg2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Psycopg2Instrumentor
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;configure_tracing():
&lt;&#x2F;span&gt;&lt;span&gt;    provider = TracerProvider()
&lt;&#x2F;span&gt;&lt;span&gt;    exporter = OTLPSpanExporter(
&lt;&#x2F;span&gt;&lt;span&gt;        endpoint=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;http:&#x2F;&#x2F;otel-collector.monitoring:4317&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        insecure=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;    provider.add_span_processor(BatchSpanProcessor(exporter))
&lt;&#x2F;span&gt;&lt;span&gt;    trace.set_tracer_provider(provider)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Auto-instrument Django HTTP requests and PostgreSQL queries
&lt;&#x2F;span&gt;&lt;span&gt;    DjangoInstrumentor().instrument()
&lt;&#x2F;span&gt;&lt;span&gt;    Psycopg2Instrumentor().instrument()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# yourapp&#x2F;apps.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.apps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;AppConfig
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;YourAppConfig(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;AppConfig&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;yourapp&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;ready(self):
&lt;&#x2F;span&gt;&lt;span&gt;        configure_tracing()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this in place, every HTTP request and every database query is automatically traced — no manual instrumentation needed for the infrastructure layer.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Custom spans for business logic&lt;&#x2F;strong&gt; — the above covers HTTP and database calls automatically. For domain-specific visibility into your own code, add manual spans:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# analysis&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;opentelemetry &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;trace
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;tracer = trace.get_tracer(__name__)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;run_variant_analysis(request, patient_id):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;tracer.start_as_current_span(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;variant-analysis&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;span:
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;patient.id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, patient_id)
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;analysis.type&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;variant-calling&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        result = VariantCallingPipeline.run(patient_id)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;analysis.variants_found&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, result.variant_count)
&lt;&#x2F;span&gt;&lt;span&gt;        span.set_attribute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;analysis.duration_ms&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, result.duration_ms)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;JsonResponse(result.to_dict())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now when an analysis is slow, the trace shows exactly where the time went: Django view setup, PostgreSQL query, pipeline execution, response serialisation — each as a separate span with its own duration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;exposing-metrics-for-prometheus&quot;&gt;Exposing metrics for Prometheus&lt;&#x2F;h3&gt;
&lt;p&gt;Add &lt;code&gt;django-prometheus&lt;&#x2F;code&gt; to &lt;code&gt;INSTALLED_APPS&lt;&#x2F;code&gt; and wire up the metrics endpoint:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# settings.py
&lt;&#x2F;span&gt;&lt;span&gt;INSTALLED_APPS = [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;MIDDLEWARE = [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus.middleware.PrometheusBeforeMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus.middleware.PrometheusAfterMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# urls.py
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;path, include
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django_prometheus.urls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)),  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# exposes &#x2F;metrics
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then tell Prometheus to scrape it with a &lt;code&gt;ServiceMonitor&lt;&#x2F;code&gt; (from the &lt;code&gt;kube-prometheus-stack&lt;&#x2F;code&gt; CRDs):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;monitoring.coreos.com&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ServiceMonitor&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;monitoring&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespaceSelector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchNames&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;endpoints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;metrics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;interval&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;30s&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Prometheus now automatically discovers and scrapes the genomics API every 30 seconds. No manual configuration when pods are rescheduled.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sli-slo-sla-from-data-to-accountability&quot;&gt;SLI, SLO, SLA: from data to accountability&lt;&#x2F;h2&gt;
&lt;p&gt;Collecting telemetry is pointless without defining what &lt;em&gt;good&lt;&#x2F;em&gt; looks like. &lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;&quot;&gt;SLI, SLO, and SLA&lt;&#x2F;a&gt; are the framework for turning raw observability data into meaningful commitments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;#indicators-o8seIAcZ&quot;&gt;SLI (Service Level Indicator)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — a measurement. A specific, quantifiable signal that reflects the user experience:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;The percentage of analysis API requests that return in under 2 seconds.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;#objectives-g0s1tdzt&quot;&gt;SLO (Service Level Objective)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — the target you set for that indicator:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;99% of analysis requests should return in under 2 seconds, measured over a rolling 30-day window.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;#agreements-ub9SGXig&quot;&gt;SLA (Service Level Agreement)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — the formal commitment to external parties, with consequences:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&quot;If availability drops below 99.5% in any calendar month, affected institutions receive a service credit.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The gap between your SLO (99%) and 100% is your &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;embracing-risk&#x2F;#id-n9ITyhxZ&quot;&gt;error budget&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — the room you have to take risks, deploy changes, and absorb incidents without breaching your commitment. If you have a 1% error budget over 30 days, that&#x27;s about 7 hours of degraded service you can afford. Spend it wisely.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;measuring-the-sli-in-prometheus&quot;&gt;Measuring the SLI in Prometheus&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api.sli&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;record&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;job:genomics_api_p99_latency_seconds&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;expr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      histogram_quantile(0.99,
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        rate(django_http_requests_latency_seconds_by_view_method_bucket{
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          job=&amp;quot;genomics-api&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          view=&amp;quot;run_variant_analysis&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        }[5m])
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;alerting-when-the-error-budget-burns-too-fast&quot;&gt;Alerting when the error budget burns too fast&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;groups&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api.slo&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alert&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;AnalysisAPIErrorBudgetBurn&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;expr&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      (
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        rate(django_http_responses_total_by_status_view_method_total{
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          job=&amp;quot;genomics-api&amp;quot;,
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          status=~&amp;quot;5..&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        }[1h])
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        &#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        rate(django_http_responses_total_by_status_view_method_total{
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;          job=&amp;quot;genomics-api&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        }[1h])
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;      ) &amp;gt; 0.01
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;5m&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;severity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;warning&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;team&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-platform&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;annotations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Genomics API error rate above SLO threshold&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;description&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        Error rate is {{ $value | humanizePercentage }}.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        At this rate, the monthly error budget will be exhausted in
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;        {{ printf &amp;quot;%.1f&amp;quot; (div 0.01 $value | mul 720) }} hours.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This alert doesn&#x27;t just tell you &lt;em&gt;that&lt;&#x2F;em&gt; the error rate is high — it tells you how quickly you are burning through your error budget, so you can decide whether to roll back immediately or investigate first.&lt;&#x2F;p&gt;
&lt;p&gt;A good alerting rule alerts on &lt;strong&gt;user impact&lt;&#x2F;strong&gt;, not on infrastructure symptoms. &quot;Error budget burning at 10x&quot; is more actionable than &quot;CPU at 78%&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;A deployed system that you can&#x27;t observe is a system you don&#x27;t fully control. Logs tell you what happened. Metrics tell you how much and how often. Traces tell you where exactly things went wrong. Kubernetes events tell you what the cluster itself was doing. Together, they answer the question that every production incident eventually raises: &lt;em&gt;&quot;what on earth is going on in there?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The open-source stack — Prometheus, Grafana, Loki, Jaeger, OpenTelemetry — gives you all of this without vendor lock-in. It runs on EKS today, on bare metal tomorrow, on a laptop for local debugging when you need it. The investment in learning these tools pays dividends regardless of which cloud you&#x27;re on.&lt;&#x2F;p&gt;
&lt;p&gt;And SLI&#x2F;SLO&#x2F;SLA takes that data one step further: it turns raw signals into a shared language between the people who build the system and the people who depend on it. Error budgets make the trade-off between reliability and velocity explicit, instead of leaving it as a permanent source of tension.&lt;&#x2F;p&gt;
&lt;p&gt;The platform is now provisioned, secured, deployed, and observable. That&#x27;s a complete stack — and the knowledge to rebuild it anywhere.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry.io&#x2F;docs&#x2F;&quot;&gt;OpenTelemetry documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentelemetry-python.readthedocs.io&#x2F;&quot;&gt;OpenTelemetry Python SDK&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;introduction&#x2F;overview&#x2F;&quot;&gt;Prometheus documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;&quot;&gt;Grafana documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;docs&#x2F;loki&#x2F;latest&#x2F;&quot;&gt;Loki documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.jaegertracing.io&#x2F;docs&#x2F;&quot;&gt;Jaeger documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;docs&#x2F;alerting&#x2F;latest&#x2F;alertmanager&#x2F;&quot;&gt;Prometheus Alertmanager&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;prometheus-community&#x2F;helm-charts&#x2F;tree&#x2F;main&#x2F;charts&#x2F;kube-prometheus-stack&quot;&gt;kube-prometheus-stack Helm chart&lt;&#x2F;a&gt; — Prometheus + Grafana + Alertmanager in one chart&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;korfuri&#x2F;django-prometheus&quot;&gt;django-prometheus&lt;&#x2F;a&gt; — Prometheus metrics for Django&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;opentelemetry-instrumentation-django&#x2F;&quot;&gt;opentelemetry-instrumentation-django&lt;&#x2F;a&gt; — auto-instrumentation for Django&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sre.google&#x2F;sre-book&#x2F;service-level-objectives&#x2F;&quot;&gt;Google SRE book — SLI&#x2F;SLO&#x2F;SLA chapter&lt;&#x2F;a&gt; — the canonical reference&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=r8UvWSX3KA8&quot;&gt;OpenTelemetry explained in 10 minutes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=QoDqxm7ybLc&quot;&gt;Prometheus &amp;amp; Grafana on Kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=EW9GMAWsyQU&quot;&gt;Distributed tracing with Jaeger&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tEylFyxbDLE&quot;&gt;SLOs, SLAs, and Error Budgets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 6)</title>
        <published>2026-02-09T00:00:00+00:00</published>
        <updated>2026-02-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-6/"/>
        <id>https://nskm.xyz/posts/aws-6/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-6/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;helm.gif&quot; alt=&quot;Helm&quot; title=&quot;Helm&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;. The examples are intentionally simplified for clarity. Before using these patterns in production, consult the &lt;a href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;terraform&#x2F;docs&quot;&gt;Terraform documentation&lt;&#x2F;a&gt;, the &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;&quot;&gt;Helm documentation&lt;&#x2F;a&gt;, and your platform team.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece. If you catch any errors, please reach out — I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;&quot;We need to set up a new environment for the epidemiology team. Can you have something running by yesterday?&quot;&lt;&#x2F;em&gt; That question is why this article exists: &lt;em&gt;how to easily repeat, redo, reiterate, duplicate, replicate, recreate, remake, reduplicate, the infrastructure we just built?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The previous episodes were focused on the theory: &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;VPCs and compute&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;IAM and encryption&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Kubernetes and EKS&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;cluster security&lt;&#x2F;a&gt;. A colleague who missed the training would get the cluster up by hand: click through the console, type commands, copy-paste YAML files, and call it done. And it would &lt;em&gt;work&lt;&#x2F;em&gt;. Until he had to do it again for staging, for recette and again for production, and then a third time months later for a deployment in another country.&lt;&#x2F;p&gt;
&lt;p&gt;Deploying &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;4s&lt;&#x2F;a&gt; for a new lab for a new country inside West Africa is something we&#x27;ve done many time in the last couple of months. Hopefully, deploying 4s &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=avbNOjCOHJE&quot;&gt;will be done&lt;&#x2F;a&gt; for all the countries in Africa. Let me present to you 2 tools to solve that problem at two different layers: &lt;strong&gt;Terraform&lt;&#x2F;strong&gt; for provisioning the infrastructure, &lt;strong&gt;Helm&lt;&#x2F;strong&gt; for deploying the applications that run on it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#the-problem-reproducibility-at-two-layers&quot;&gt;The problem: reproducibility at two layers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#terraform-infrastructure-as-code&quot;&gt;Terraform: infrastructure as code&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#helm-kubernetes-package-manager&quot;&gt;Helm: Kubernetes package manager&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#where-does-the-chart-live-chart-registries&quot;&gt;Where does the chart live? Chart registries&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#putting-it-together-one-pipeline&quot;&gt;Putting it together&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-reproducibility-at-two-layers&quot;&gt;The problem: reproducibility at two layers&lt;&#x2F;h2&gt;
&lt;p&gt;Imagine you&#x27;ve just finished reading &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;Day 5&lt;&#x2F;a&gt;. You know how to secure an EKS cluster. Now you need to actually create one and deploy a Django REST API onto it.&lt;&#x2F;p&gt;
&lt;p&gt;You could do it manually, click through the EKS console, create a node group, write a few dozen YAML manifests, copy-paste the right &lt;code&gt;kubectl apply&lt;&#x2F;code&gt; commands. But we could do better. We should be able to easily redo what we&#x27;ve done.&lt;&#x2F;p&gt;
&lt;p&gt;Before we even get to the issue of reproducibility, we want to record, keep and preserve what has been done, if only so that we can review it later or go back and read through what has been achieved. As for me, throughout the workshop, I didn’t just type in commands; I wrote Bash scripts....&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;bash
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Environment Variables
&lt;&#x2F;span&gt;&lt;span&gt;AWS_REGION=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;eu-west-1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;CLUSTER_NAME=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;ptrck-foundation-training&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ACCOUNT_ID=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;546732826958&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ID of the EKS Admin role
&lt;&#x2F;span&gt;&lt;span&gt;ROLE_ARN=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:iam::${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;ACCOUNT_ID&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}:role&#x2F;EKSAdminRole&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ARN of the EKS Admin role
&lt;&#x2F;span&gt;&lt;span&gt;CLUSTER_ARN=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:eks:${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}:${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;ACCOUNT_ID&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}:cluster&#x2F;${&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;CLUSTER_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;}&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I need to create this ECR repository
&lt;&#x2F;span&gt;&lt;span&gt;ECR_REPO=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;ecr-repo-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEMO_NS=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;demo-ns-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEMO_DEPLOYMENT=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;demo-dply-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEMO_CONTAINER=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;app-ptrck&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Helper function to print things with some separation
&lt;&#x2F;span&gt;&lt;span&gt;section() {
&lt;&#x2F;span&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;=====&amp;gt; $&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Configure AWS CLI credentials&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Identity &amp;amp; role assume
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Verify identity&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws sts get-caller-identity
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Verify role exists&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam get-role --role-name EKSAdminRole
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List all roles in account (if you have permissions)&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-roles \
&lt;&#x2F;span&gt;&lt;span&gt;  --query &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Roles[].RoleName&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  --output text
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List user Policies&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-user-policies --user-name $(aws sts get-caller-identity --query &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Arn&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; --output text &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;cut -d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -f 6)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List attached policies&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;CURRENT_USER=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;aws&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; sts get-caller-identity&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt; --query &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;#39;Arn&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt; --output&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; text &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;cut -d&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt; -f&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt; 6)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-attached-user-policies --user-name $CURRENT_USER
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Check current default region&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure get region
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(Re)configure AWS CLI credentials&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Assume EKS admin role &amp;amp; retrieve the token&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws sts assume-role \
&lt;&#x2F;span&gt;&lt;span&gt;    --role-session-name iam-eks-admin-role \
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# was working nice until sunday 7PM ?!
&lt;&#x2F;span&gt;&lt;span&gt;    --role-arn &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;ROLE_ARN&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;    --duration-seconds 43200
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Configure the &amp;#39;iam-eks-admin-role&amp;#39; profile with the temporary credentials&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws configure --profile iam-eks-admin-role
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;What are the available roles ?&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-roles
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;What are the available policies?&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam list-policies
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Check if there is a K8s cluster available
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List all EKS clusters&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws eks list-clusters
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;List clusters in my region&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;aws eks list-clusters --region &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;At this point, there is no clusters available whaaaaaa ?! lol&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;section &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Let&amp;#39;s create our K8s cluster&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;eksctl create cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;CLUSTER_NAME&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  --region &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;$&lt;&#x2F;span&gt;&lt;span&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes 3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --node-type t2.micro \
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# --with-oidc: no need to separately call eksctl utils associate-iam-oidc-provider
&lt;&#x2F;span&gt;&lt;span&gt;  --with-oidc \
&lt;&#x2F;span&gt;&lt;span&gt;  --enable-auto-mode
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the &lt;strong&gt;reproducibility problem&lt;&#x2F;strong&gt;, and it lives at two distinct layers:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure layer&lt;&#x2F;strong&gt;: &lt;em&gt;Who created the VPC? What are the exact subnet CIDRs? Which KMS key encrypts etcd?&lt;&#x2F;em&gt; If the answer lives in someone&#x27;s memory or a Confluence page, you have a problem.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Application layer&lt;&#x2F;strong&gt;: &lt;em&gt;Which version of the Django app is running in staging? How do I roll back if the new release breaks something?&lt;&#x2F;em&gt; If the answer is &quot;look at the kubectl commands in the README&quot;, you have a different problem.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Terraform&lt;&#x2F;strong&gt; solves the first. &lt;strong&gt;Helm&lt;&#x2F;strong&gt; solves the second.&lt;&#x2F;p&gt;
&lt;p&gt;Bash scripts are fine for exploration and one-off tasks, but they fall short once you need state tracking, idempotence, error handling, drift detection, and dependency management — which is exactly what infrastructure provisioning requires.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;terraform-infrastructure-as-code&quot;&gt;Terraform: infrastructure as code&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;a-brief-history&quot;&gt;A brief history&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.terraform.io&#x2F;&quot;&gt;Terraform&lt;&#x2F;a&gt; was created by &lt;a href=&quot;https:&#x2F;&#x2F;www.hashicorp.com&#x2F;&quot;&gt;HashiCorp&lt;&#x2F;a&gt; and first released in &lt;strong&gt;2014&lt;&#x2F;strong&gt;. The problem it solved: AWS had CloudFormation, GCP had Deployment Manager, Azure had ARM templates — but if you used more than one cloud, you had three completely different tools, three syntaxes, three mental models. Terraform &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;927&#x2F;&quot;&gt;unified them&lt;&#x2F;a&gt; under a single declarative language: &lt;strong&gt;HCL&lt;&#x2F;strong&gt; (HashiCorp Configuration Language).&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;standards.png&quot; alt=&quot;Standards&quot; title=&quot;Standards&quot;&#x2F;&gt;
&lt;p&gt;Core idea: &lt;em&gt;describe the desired state of your infrastructure, and Terraform figures out how to get there&lt;&#x2F;em&gt;. It maintains a &lt;strong&gt;state file&lt;&#x2F;strong&gt; tracking what it has created, so it can calculate the diff between current state and desired state on every run.&lt;&#x2F;p&gt;
&lt;p&gt;One important note: &lt;em&gt;as a free software advocate&lt;&#x2F;em&gt;, I should talk about the Terraform fork called &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentofu.org&#x2F;&quot;&gt;OpenTofu&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. OpenTofu is &lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;projects&#x2F;opentofu&#x2F;&quot;&gt;CNCF&lt;&#x2F;a&gt; project, API-compatible with Terraform — same HCL, same providers, same workflow, &lt;em&gt;same everything&lt;&#x2F;em&gt;. For most teams, the choice between them is a licensing and governance question. The examples below work identically on both. &lt;em&gt;I hope.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternatives-why-terraform&quot;&gt;Alternatives &amp;amp; why Terraform&lt;&#x2F;h3&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Tool&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Approach&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;When to prefer it&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS CloudFormation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS-native, JSON&#x2F;YAML templates&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS-only shops that want native integration and no external tooling&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS CDK&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;TypeScript&#x2F;Python constructs that compile to CloudFormation&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Developer-heavy teams who want real programming languages for infrastructure&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pulumi&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Multi-cloud, uses Python&#x2F;TypeScript&#x2F;Go directly&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Teams that find HCL limiting and want full programming language expressiveness&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Ansible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Procedural YAML playbooks&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Configuration management and server setup; less suited for cloud resource provisioning&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;OpenTofu&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Terraform fork, identical syntax&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Teams that want open-source governance and no BSL licensing constraints&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;Why we chose Terraform? It&#x27;s multi-cloud (we&#x27;re on AWS now, but that may change, lol), it has &lt;a href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;browse&#x2F;providers&quot;&gt;over 4000 providers&lt;&#x2F;a&gt;, it has a mature module ecosystem, and it&#x27;s the most widely adopted IaC tool in the industry.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;provisioning-an-eks-cluster&quot;&gt;Provisioning an EKS cluster&lt;&#x2F;h3&gt;
&lt;p&gt;The goal: reproduce the EKS cluster from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;Day 4&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;&quot;&gt;Day 5&lt;&#x2F;a&gt; — VPC, private subnets, encrypted etcd, managed node group — using Terraform. Every time. Identically.&lt;&#x2F;p&gt;
&lt;p&gt;Project structure:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;infra&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── main.tf           # providers, backend, modules
&lt;&#x2F;span&gt;&lt;span&gt;├── variables.tf      # input variables
&lt;&#x2F;span&gt;&lt;span&gt;├── outputs.tf        # cluster name, endpoint (consumed by Helm later)
&lt;&#x2F;span&gt;&lt;span&gt;└── terraform.tfvars  # environment-specific values (not committed to Git)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;main.tf&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — the core:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hcl&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-hcl &quot;&gt;&lt;code class=&quot;language-hcl&quot; data-lang=&quot;hcl&quot;&gt;&lt;span&gt;terraform {
&lt;&#x2F;span&gt;&lt;span&gt;  required_providers {
&lt;&#x2F;span&gt;&lt;span&gt;    aws = {
&lt;&#x2F;span&gt;&lt;span&gt;      source  = &amp;quot;hashicorp&#x2F;aws&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      version = &amp;quot;~&amp;gt; 5.0&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  # Remote state: shared, locked, versioned
&lt;&#x2F;span&gt;&lt;span&gt;  backend &amp;quot;s3&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;    bucket         = &amp;quot;genomics-platform-tfstate&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    key            = &amp;quot;eks&#x2F;terraform.tfstate&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    region         = &amp;quot;eu-west-3&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    dynamodb_table = &amp;quot;terraform-locks&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    encrypt        = true
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;provider &amp;quot;aws&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  region = var.region
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# KMS key for etcd encryption (Day 5 best practice)
&lt;&#x2F;span&gt;&lt;span&gt;resource &amp;quot;aws_kms_key&amp;quot; &amp;quot;eks&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description             = &amp;quot;EKS secrets encryption&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  deletion_window_in_days = 7
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# VPC: private subnets for nodes, public subnets for load balancers
&lt;&#x2F;span&gt;&lt;span&gt;module &amp;quot;vpc&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  source  = &amp;quot;terraform-aws-modules&#x2F;vpc&#x2F;aws&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  version = &amp;quot;~&amp;gt; 5.0&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  name = &amp;quot;${var.cluster_name}-vpc&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  cidr = &amp;quot;10.0.0.0&#x2F;16&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  azs             = [&amp;quot;${var.region}a&amp;quot;, &amp;quot;${var.region}b&amp;quot;, &amp;quot;${var.region}c&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;  private_subnets = [&amp;quot;10.0.1.0&#x2F;24&amp;quot;, &amp;quot;10.0.2.0&#x2F;24&amp;quot;, &amp;quot;10.0.3.0&#x2F;24&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;  public_subnets  = [&amp;quot;10.0.101.0&#x2F;24&amp;quot;, &amp;quot;10.0.102.0&#x2F;24&amp;quot;, &amp;quot;10.0.103.0&#x2F;24&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  enable_nat_gateway = true
&lt;&#x2F;span&gt;&lt;span&gt;  single_nat_gateway = true
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  tags = {
&lt;&#x2F;span&gt;&lt;span&gt;    &amp;quot;kubernetes.io&#x2F;cluster&#x2F;${var.cluster_name}&amp;quot; = &amp;quot;shared&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    Environment                                 = var.environment
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;# EKS cluster
&lt;&#x2F;span&gt;&lt;span&gt;module &amp;quot;eks&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  source  = &amp;quot;terraform-aws-modules&#x2F;eks&#x2F;aws&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  version = &amp;quot;~&amp;gt; 20.0&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_name    = var.cluster_name
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_version = &amp;quot;1.30&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  vpc_id     = module.vpc.vpc_id
&lt;&#x2F;span&gt;&lt;span&gt;  subnet_ids = module.vpc.private_subnets
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  # Private endpoint only (Day 5 best practice)
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_endpoint_public_access = false
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  # etcd encryption with the KMS key above
&lt;&#x2F;span&gt;&lt;span&gt;  cluster_encryption_config = {
&lt;&#x2F;span&gt;&lt;span&gt;    resources        = [&amp;quot;secrets&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;    provider_key_arn = aws_kms_key.eks.arn
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  eks_managed_node_groups = {
&lt;&#x2F;span&gt;&lt;span&gt;    genomics = {
&lt;&#x2F;span&gt;&lt;span&gt;      instance_types = [&amp;quot;m5.large&amp;quot;]
&lt;&#x2F;span&gt;&lt;span&gt;      min_size       = 2
&lt;&#x2F;span&gt;&lt;span&gt;      max_size       = 10
&lt;&#x2F;span&gt;&lt;span&gt;      desired_size   = 3
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;variables.tf&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hcl&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-hcl &quot;&gt;&lt;code class=&quot;language-hcl&quot; data-lang=&quot;hcl&quot;&gt;&lt;span&gt;variable &amp;quot;region&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description = &amp;quot;AWS region&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  type        = string
&lt;&#x2F;span&gt;&lt;span&gt;  default     = &amp;quot;eu-west-3&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;variable &amp;quot;cluster_name&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description = &amp;quot;EKS cluster name&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  type        = string
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;variable &amp;quot;environment&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  description = &amp;quot;Deployment environment (dev, staging, prod)&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  type        = string
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;outputs.tf&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — what other tools will need:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;hcl&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-hcl &quot;&gt;&lt;code class=&quot;language-hcl&quot; data-lang=&quot;hcl&quot;&gt;&lt;span&gt;output &amp;quot;cluster_name&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  value = module.eks.cluster_name
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;output &amp;quot;cluster_endpoint&amp;quot; {
&lt;&#x2F;span&gt;&lt;span&gt;  value = module.eks.cluster_endpoint
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Deploy it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;terraform init          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# download providers and modules
&lt;&#x2F;span&gt;&lt;span&gt;terraform plan          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# preview what will be created
&lt;&#x2F;span&gt;&lt;span&gt;terraform apply         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create the infrastructure
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Voilà.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;helm-kubernetes-package-manager&quot;&gt;Helm: Kubernetes package manager&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;a-brief-history-1&quot;&gt;A brief history&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;&quot;&gt;Helm&lt;&#x2F;a&gt; was first presented at &lt;strong&gt;KubeCon 2015&lt;&#x2F;strong&gt; by the team at &lt;a href=&quot;https:&#x2F;&#x2F;deis.com&#x2F;&quot;&gt;Deis&lt;&#x2F;a&gt; (notably &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;technosophos&quot;&gt;Matt Butcher&lt;&#x2F;a&gt;). The problem it solved: writing raw Kubernetes manifests for a real application means dozens of YAML files, lots of copy-paste across environments, no concept of versioning, and no clean way to roll back. Helm introduced the &lt;strong&gt;chart&lt;&#x2F;strong&gt; — a package of Kubernetes manifests with templating and versioning built in.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;strong&gt;2016&lt;&#x2F;strong&gt;, Google and Deis merged their Kubernetes packaging work, and Helm was donated to the Kubernetes project. It became a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;projects&#x2F;helm&#x2F;&quot;&gt;CNCF graduated project&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; in 2020 — the same tier as Kubernetes, Prometheus, and Envoy.&lt;&#x2F;p&gt;
&lt;p&gt;Helm 2 (the first widely adopted version) required a server-side component called &lt;strong&gt;Tiller&lt;&#x2F;strong&gt; running inside the cluster. Tiller had broad cluster-admin permissions and became a well-known security liability. &lt;strong&gt;Helm 3&lt;&#x2F;strong&gt; (released in 2019) removed Tiller entirely — all operations now happen client-side, and permissions come from your own kubeconfig. Simpler and significantly more secure.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alternatives-why-helm&quot;&gt;Alternatives &amp;amp; why Helm&lt;&#x2F;h3&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Tool&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Approach&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;When to prefer it&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Kustomize&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Overlay-based patching, built into kubectl&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Simple apps where you want no templating and native kubectl support&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Plain manifests&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Raw YAML + &lt;code&gt;kubectl apply&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Very small projects, learning environments, one-off deployments&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Skaffold&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Dev-focused workflow: build + push + deploy&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Inner-loop development with fast local iteration cycles&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Carvel &#x2F; ytt&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Structured YAML templating&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;VMware&#x2F;Tanzu ecosystems&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;We chose Helm because: versioned releases let you see exactly what is running in each namespace with &lt;code&gt;helm list&lt;&#x2F;code&gt;, atomic upgrades roll back automatically on failure, &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;charts_hooks&#x2F;&quot;&gt;hooks&lt;&#x2F;a&gt; let you run jobs before or after install (crucial for Django migrations — more on this below), and &lt;a href=&quot;https:&#x2F;&#x2F;artifacthub.io&#x2F;&quot;&gt;ArtifactHub&lt;&#x2F;a&gt; hosts thousands of ready-made charts for databases, ingress controllers, monitoring stacks, and more. When you need to install cert-manager or the AWS Load Balancer Controller into your cluster, it&#x27;s a one-liner.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;packaging-a-django-rest-api&quot;&gt;Packaging a Django REST API&lt;&#x2F;h3&gt;
&lt;p&gt;Our syndromic surveillance platform is a Django REST API that processes public health data. Here&#x27;s how to package it as a Helm chart.&lt;&#x2F;p&gt;
&lt;p&gt;Chart structure:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;syndromic-surveillance-api&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── Chart.yaml            # chart metadata
&lt;&#x2F;span&gt;&lt;span&gt;├── values.yaml           # default configuration values
&lt;&#x2F;span&gt;&lt;span&gt;└── templates&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    ├── _helpers.tpl      # reusable template snippets
&lt;&#x2F;span&gt;&lt;span&gt;    ├── deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;    ├── service.yaml
&lt;&#x2F;span&gt;&lt;span&gt;    └── migrate-job.yaml  # Django migration hook
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Chart.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;syndromic-surveillance-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;description&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Django REST API for genomic data processing&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;application&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;version&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.1.0       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# chart version — bump when the chart itself changes
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;appVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;1.0.0&amp;quot;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# application version — overridden at deploy time
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;values.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — the defaults, overridable per environment:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicaCount&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;123456789012.dkr.ecr.eu-west-3.amazonaws.com&#x2F;syndromic-surveillance-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pullPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;IfNotPresent&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tag&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# overridden at deploy time: --set image.tag=v1.2.3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ClusterIP&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;500m&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;512Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;100m&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;256Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DJANGO_SETTINGS_MODULE&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;config.settings.production&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DB_HOST&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rds.syndromic-surveillance-platform.internal&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DB_NAME&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;syndromic-surveillance&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;templates&#x2F;deployment.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.fullname&amp;quot; .&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.labels&amp;quot; . | nindent 4&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Values.replicaCount&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.selectorLabels&amp;quot; . | nindent 6&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.selectorLabels&amp;quot; . | nindent 8&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsNonRoot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Day 5 best practice
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsUser&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Chart.Name&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;range $key&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val := .Values.env&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$key&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val | quote&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;toYaml .Values.resources | nindent 10&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;readinessProbe&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;httpGet&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;healthz&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;initialDelaySeconds&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;periodSeconds&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When, 2 years ago, I was first getting to grips with K8s, I remember using side containers to apply Django database migrations. Nowadays, I use “init containers” to do Django database migrations. And whilst doing some research on Helm, specifically to write &lt;em&gt;this article&lt;&#x2F;em&gt;, I was very surprised to discover that this thing exists. A &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;charts_hooks&#x2F;&quot;&gt;pre-upgrade hook&lt;&#x2F;a&gt; that runs &lt;code&gt;manage.py migrate&lt;&#x2F;code&gt; &lt;em&gt;before&lt;&#x2F;em&gt; any new pods are started:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;templates&#x2F;migrate-job.yaml&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; — I really need to try this&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;batch&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Job&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;include &amp;quot;syndromic-surveillance-api.fullname&amp;quot; .&lt;&#x2F;span&gt;&lt;span&gt; }}&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;-migrate&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;annotations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;helm.sh&#x2F;hook&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;pre-install,pre-upgrade&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;helm.sh&#x2F;hook-delete-policy&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;before-hook-creation&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;restartPolicy&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Never&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsNonRoot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsUser&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;migrate&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;command&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;manage.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;migrate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;--noinput&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;range $key&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val := .Values.env&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$key&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;$val | quote&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        {{- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Phew!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Deploy it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# First deploy
&lt;&#x2F;span&gt;&lt;span&gt;helm install syndromic-surveillance-api .&#x2F;syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace \
&lt;&#x2F;span&gt;&lt;span&gt;  --set image.tag=v1.0.0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Upgrade to a new version
&lt;&#x2F;span&gt;&lt;span&gt;helm upgrade syndromic-surveillance-api .&#x2F;syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --set image.tag=v1.2.3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Something broke — roll back to the previous release
&lt;&#x2F;span&gt;&lt;span&gt;helm rollback syndromic-surveillance-api -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# See what is currently running
&lt;&#x2F;span&gt;&lt;span&gt;helm list -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;where-does-the-chart-live-chart-registries&quot;&gt;Where does the chart live? Chart registries&lt;&#x2F;h2&gt;
&lt;p&gt;So far the chart lives in a local &lt;code&gt;.&#x2F;syndromic-surveillance-api&#x2F;&lt;&#x2F;code&gt; directory. That works on your machine. It doesn&#x27;t work for your teammates, your CI pipeline, or your staging environment.&lt;&#x2F;p&gt;
&lt;p&gt;Just like Docker images have registries (Docker Hub, ECR...), Helm charts have registries too.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;OCI registries — the recommended modern approach&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Since Helm 3.8 (2022), charts can be &lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;blog&#x2F;storing-charts-in-oci&#x2F;&quot;&gt;stored as OCI artifacts&lt;&#x2F;a&gt;. This means the &lt;em&gt;same registry you already use for containers images&lt;&#x2F;em&gt; can store your charts. On AWS, a single ECR repository holds both:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# package and push the chart
&lt;&#x2F;span&gt;&lt;span&gt;helm package .&#x2F;syndromic-surveillance-api
&lt;&#x2F;span&gt;&lt;span&gt;helm push syndromic-surveillance-api-0.1.0.tgz \
&lt;&#x2F;span&gt;&lt;span&gt;  oci:&#x2F;&#x2F;123456789012.dkr.ecr.eu-west-3.amazonaws.com&#x2F;charts
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# teammates pull and install directly from ECR
&lt;&#x2F;span&gt;&lt;span&gt;helm install syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  oci:&#x2F;&#x2F;123456789012.dkr.ecr.eu-west-3.amazonaws.com&#x2F;charts&#x2F;syndromic-surveillance-api \
&lt;&#x2F;span&gt;&lt;span&gt;  --version 0.1.0 \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;What I recommend&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I decided to not talk about &lt;strong&gt;classic Helm repositories&lt;&#x2F;strong&gt; &amp;amp; &lt;strong&gt;public Helm registries&lt;&#x2F;strong&gt;. Since we are learning about the AWS cloud, just use ECR with OCI. You are already paying for it, IAM controls access (the same permissions model from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;Day 2-3&lt;&#x2F;a&gt;), no extra infrastructure to maintain, and it works for both Docker images and Helm charts. Your teammates authenticate once via &lt;code&gt;aws ecr get-login-password&lt;&#x2F;code&gt; and pull charts the same way they pull images.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-it-together-one-pipeline&quot;&gt;Putting it together: one pipeline&lt;&#x2F;h2&gt;
&lt;p&gt;Terraform provisions the platform. Helm deploys the application. Here is the full sequence, end to end:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 1. Provision the EKS cluster
&lt;&#x2F;span&gt;&lt;span&gt;cd infra&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;terraform init
&lt;&#x2F;span&gt;&lt;span&gt;terraform apply \
&lt;&#x2F;span&gt;&lt;span&gt;  -var=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cluster_name=syndromic-surveillance-platform&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  -var=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;environment=staging&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 2. Configure kubectl to talk to the new cluster
&lt;&#x2F;span&gt;&lt;span&gt;aws eks update-kubeconfig \
&lt;&#x2F;span&gt;&lt;span&gt;  --region eu-west-3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --name syndromic-surveillance-platform
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 3. Verify the nodes are ready
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get nodes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 4. Deploy the Django API
&lt;&#x2F;span&gt;&lt;span&gt;cd ..&#x2F;syndromic-surveillance-api&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;helm upgrade --install syndromic-surveillance-api . \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace syndromic-surveillance \
&lt;&#x2F;span&gt;&lt;span&gt;  --create-namespace \
&lt;&#x2F;span&gt;&lt;span&gt;  --set image.tag=v1.0.0
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# 5. Verify
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;span&gt;helm list -n syndromic-surveillance
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Five steps. New environment, new cluster, application running. The same sequence works for dev, staging, and prod — with a different &lt;code&gt;environment&lt;&#x2F;code&gt; variable and &lt;code&gt;image.tag&lt;&#x2F;code&gt; each time.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Two tools, one principle: &lt;em&gt;write once, run anywhere&lt;&#x2F;em&gt;. &lt;em&gt;(I’ve got some old memories coming back to me, lol – it was the Javaboyz who used to talk like that way back then in 1995).&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Infrastructure and deployments should be like code: version-controlled, peer-reviewed, auditable, and repeatable. There is no alternative, we should adopt this way of working.&lt;&#x2F;p&gt;
&lt;p&gt;The learning curve is real. HCL takes time to learn. Helm templates can grow verbose. But the payoff is worth it every single time. As always, the subject is huge and cannot be covered in one tiny article. Here are some links you can use to learn more:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.hashicorp.com&#x2F;terraform&#x2F;docs&quot;&gt;Terraform documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opentofu.org&#x2F;docs&#x2F;&quot;&gt;OpenTofu documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;providers&#x2F;hashicorp&#x2F;aws&#x2F;latest&#x2F;docs&quot;&gt;Terraform AWS provider&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;registry.terraform.io&#x2F;modules&#x2F;terraform-aws-modules&#x2F;eks&#x2F;aws&#x2F;latest&quot;&gt;terraform-aws-modules&#x2F;eks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;&quot;&gt;Helm documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;charts_hooks&#x2F;&quot;&gt;Helm chart hooks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;artifacthub.io&#x2F;&quot;&gt;ArtifactHub — public Helm chart repository&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;chartmuseum.com&#x2F;&quot;&gt;ChartMuseum — self-hosted Helm chart repository&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;docs&#x2F;topics&#x2F;registries&#x2F;&quot;&gt;Helm OCI support documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aquasecurity.github.io&#x2F;tfsec&#x2F;&quot;&gt;tfsec&lt;&#x2F;a&gt; — static analysis for Terraform security misconfigurations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.infracost.io&#x2F;&quot;&gt;Infracost&lt;&#x2F;a&gt; — cost estimation for Terraform plans before you apply them&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;norwoodj&#x2F;helm-docs&quot;&gt;helm-docs&lt;&#x2F;a&gt; — auto-generate documentation for Helm charts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;helm&#x2F;chart-testing&quot;&gt;chart-testing&lt;&#x2F;a&gt; — lint and test Helm charts in CI&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fy8SHvNZGeE&quot;&gt;What&#x27;s Helm?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tomUWcQ0P3k&quot;&gt;Terraform in 100 seconds&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=7xngnjfIlK4&quot;&gt;Complete Terraform course&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=-ykwb1d0DXU&quot;&gt;Helm and Kubernetes tutorial&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MNt2HGxClZ0&quot;&gt;Terraform EKS cluster from scratch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 5)</title>
        <published>2026-02-06T00:00:00+00:00</published>
        <updated>2026-02-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-5/"/>
        <id>https://nskm.xyz/posts/aws-5/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-5/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;get_out.gif&quot; alt=&quot;Security checkpoint&quot; title=&quot;Security checkpoint&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;, not a production hardening guide. Before securing a real EKS cluster, consult the &lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;AWS EKS best practices guide&lt;&#x2F;a&gt; and involve your security teams.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Today&#x27;s topic feels like the natural conclusion of the entire week. We spent Day 1 building the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;foundation&lt;&#x2F;a&gt;: regions, VPCs, compute, storage. Days 2-3 were about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;&quot;&gt;who can do what and how to prove it&lt;&#x2F;a&gt;: IAM, OIDC, encryption, audit. Day 4 introduced &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;K8s and EKS&lt;&#x2F;a&gt;: the orchestration layer. Now we answer the question that matters most: &lt;strong&gt;how do you make sure nobody breaks into the thing you just built?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Security in K8s is not a feature you turn on. It&#x27;s a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=_GgfLZoLuGY&quot;&gt;layer&lt;&#x2F;a&gt; you build, piece by piece. And the uncomfortable truth is: K8s, out of the box, is &lt;em&gt;not&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.tigera.io&#x2F;blog&#x2F;kubernetes-is-powerful-but-not-secure-at-least-not-by-default&#x2F;&quot;&gt;secure&lt;&#x2F;a&gt;. It gives you the &lt;em&gt;mechanisms&lt;&#x2F;em&gt; — but the defaults are permissive, and the responsibility is yours.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s talk about what that means.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#k8s-security-concepts-traditional-infrastructure&quot;&gt;K8s security concepts → traditional infrastructure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#how-secure-is-k8s-by-default&quot;&gt;How secure is K8s by default?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#authentication-who-are-you&quot;&gt;Authentication: who are you?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#authorization-what-can-you-do&quot;&gt;Authorization: what can you do?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#network-security&quot;&gt;Network security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#pod-security&quot;&gt;Pod security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#secrets-management&quot;&gt;Secrets management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#resource-quotas-limitranges&quot;&gt;Resource quotas &amp;amp; LimitRanges&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#audit-observability&quot;&gt;Audit &amp;amp; observability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#best-practices-checklist&quot;&gt;Best practices checklist&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-5&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;k8s-security-concepts-traditional-infrastructure&quot;&gt;K8s security concepts → traditional infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been securing Linux servers, you already know these concepts. K8s just applies them at orchestration scale:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;K8s Security Concept&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;What&#x27;s Different?&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;RBAC (Roles &amp; RoleBindings)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Linux users, groups, sudo, &lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Scoped to namespaces or cluster-wide; applies to API verbs (get, create, delete), not file permissions&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Service Accounts&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;System users (&lt;code&gt;www-data&lt;&#x2F;code&gt;, &lt;code&gt;postgres&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Identity for pods, not humans; auto-mounted tokens; can map to cloud IAM roles&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Network Policies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt;, firewall rules&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Declarative YAML; enforced by the CNI plugin; scoped by pod labels and namespaces&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pod Security Admission&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AppArmor, SELinux, seccomp profiles&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster-level enforcement of what containers can do (run as root, mount host paths, etc.)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Secrets&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;shadow&lt;&#x2F;code&gt;, SSH keys, environment variables&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Stored in etcd; base64-encoded (not encrypted!) by default; can integrate with external vaults&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Resource Quotas&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;ulimit&lt;&#x2F;code&gt;, cgroups, disk quotas&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Applied per namespace; limits CPU, memory, pod count, storage claims&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Audit Logging&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;var&#x2F;log&#x2F;auth.log&lt;&#x2F;code&gt;, syslog&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;API server records every request; configurable verbosity levels; integrates with cloud logging&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Namespaces&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;chroot, Linux namespaces, separate VMs&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Logical isolation only — not a security boundary by themselves without RBAC + Network Policies&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The mental model is: &lt;strong&gt;K8s security = Linux security concepts, applied declaratively, at the API level, across a fleet of containers.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-secure-is-k8s-by-default&quot;&gt;How secure is K8s by default?&lt;&#x2F;h2&gt;
&lt;p&gt;The short answer: &lt;strong&gt;not very&lt;&#x2F;strong&gt;. You have to actively tighten things.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-you-get-out-of-the-box&quot;&gt;What you get out of the box&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API server authentication&lt;&#x2F;strong&gt;: The API server requires authentication — anonymous requests are rejected for most operations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Namespaces&lt;&#x2F;strong&gt;: Logical separation exists from the start (&lt;code&gt;default&lt;&#x2F;code&gt;, &lt;code&gt;kube-system&lt;&#x2F;code&gt;, &lt;code&gt;kube-public&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;etcd is only accessible from the control plane&lt;&#x2F;strong&gt;: In a properly set up cluster, etcd isn&#x27;t exposed to worker nodes or external networks&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RBAC is enabled&lt;&#x2F;strong&gt;: The authorization mode includes RBAC (in modern K8s versions)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;what-is-not-secure-by-default&quot;&gt;What is NOT secure by default&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;No network policies enforced.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; By default, every pod can talk to every other pod in the cluster. Your frontend pod can reach your database pod. Your staging namespace can reach your production namespace. It&#x27;s like running all your servers in the same network segment with no firewall.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;secret&#x2F;&quot;&gt;Secrets are not encrypted at rest.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; K8s Secrets are stored as base64-encoded values in etcd. Base64 is &lt;em&gt;encoding&lt;&#x2F;em&gt;, not &lt;em&gt;encryption&lt;&#x2F;em&gt;. Anyone with access to etcd can read every secret in your cluster. This is like storing passwords in a text file and calling it security.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;security-context&#x2F;&quot;&gt;Containers run as root by default.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; Unless you explicitly specify a security context, your container process runs as UID 0 — the same root as on the underlying node. A container escape vulnerability becomes a root-level compromise of the node.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;configure-service-account&#x2F;&quot;&gt;Default service accounts are overly permissive.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; Every namespace gets a &lt;code&gt;default&lt;&#x2F;code&gt; service account that is automatically mounted into every pod. In many setups, this service account has more permissions than needed — and pods that don&#x27;t need API access still get a token.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;debug&#x2F;debug-cluster&#x2F;audit&#x2F;&quot;&gt;No audit logging enabled by default.&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; The API server &lt;em&gt;can&lt;&#x2F;em&gt; log every request, but audit logging is not configured out of the box. Without it, you have no record of who did what in your cluster.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-eks-twist&quot;&gt;The EKS twist&lt;&#x2F;h3&gt;
&lt;p&gt;AWS tightens some things for you when you use EKS:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;etcd encryption at rest&lt;&#x2F;strong&gt; is available (you enable it with a KMS key — it&#x27;s not automatic, but it&#x27;s a one-click option)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The control plane is managed&lt;&#x2F;strong&gt;: You can&#x27;t SSH into it, and AWS handles patching — reducing your attack surface&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;API server endpoint access&lt;&#x2F;strong&gt; can be restricted to your VPC (private endpoint)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;EKS control plane logging&lt;&#x2F;strong&gt; can be sent to CloudWatch (but you have to enable it)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What remains your responsibility: network policies, pod security, RBAC configuration, secrets management, image scanning, and everything at the workload level. AWS secures the &lt;em&gt;infrastructure&lt;&#x2F;em&gt;; you secure the &lt;em&gt;workloads&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authentication-who-are-you&quot;&gt;Authentication: who are you?&lt;&#x2F;h2&gt;
&lt;p&gt;Before K8s can decide what you&#x27;re allowed to do, it needs to know &lt;em&gt;who you are&lt;&#x2F;em&gt;. There are two types of identities in K8s: human users and service accounts.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-service-accounts&quot;&gt;K8s Service Accounts&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;service-accounts&#x2F;&quot;&gt;Service Account&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is an identity for processes running inside pods. Unlike human users (which K8s doesn&#x27;t manage directly), service accounts are native K8s objects:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ServiceAccount&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-pipeline&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Every namespace has a &lt;code&gt;default&lt;&#x2F;code&gt; service account. Every pod that doesn&#x27;t specify a service account gets the &lt;code&gt;default&lt;&#x2F;code&gt; one, along with a mounted token at &lt;code&gt;&#x2F;var&#x2F;run&#x2F;secrets&#x2F;kubernetes.io&#x2F;serviceaccount&#x2F;token&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Best practice&lt;&#x2F;strong&gt;: Create dedicated service accounts for each workload and disable auto-mounting of tokens for pods that don&#x27;t need API access:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ServiceAccount&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-processor&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;automountServiceAccountToken&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;aws-iam-integration-with-eks&quot;&gt;AWS IAM integration with EKS&lt;&#x2F;h3&gt;
&lt;p&gt;In EKS, human authentication flows through AWS IAM. When you run &lt;code&gt;kubectl&lt;&#x2F;code&gt; against an EKS cluster, this is what happens:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;You authenticate to AWS&lt;&#x2F;strong&gt; (IAM user, role, or SSO)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;aws eks get-token&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt; generates a token based on your IAM identity&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The EKS API server&lt;&#x2F;strong&gt; validates this token against the AWS IAM authenticator&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Your IAM identity is mapped&lt;&#x2F;strong&gt; to a K8s user&#x2F;group via the &lt;code&gt;aws-auth&lt;&#x2F;code&gt; ConfigMap or &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;access-entries.html&quot;&gt;EKS access entries&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RBAC takes over&lt;&#x2F;strong&gt; — K8s decides what this user can do&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;For pods that need to call AWS services (S3, DynamoDB, SQS), EKS offers two mechanisms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;iam-roles-for-service-accounts.html&quot;&gt;IRSA (IAM Roles for Service Accounts)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: We covered this in the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;&quot;&gt;previous article&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;pod-identities.html&quot;&gt;EKS Pod Identity&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A newer mechanism that achieves the same thing without needing to configure an OIDC provider yourself.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both eliminate the need to store AWS credentials as K8s Secrets. Temporary credentials are injected automatically and rotated by AWS.&lt;&#x2F;p&gt;
&lt;p&gt;The identity chain looks like this: &lt;strong&gt;AWS IAM&lt;&#x2F;strong&gt; (authenticates the human or CI system) → &lt;strong&gt;K8s RBAC&lt;&#x2F;strong&gt; (authorizes what they can do inside the cluster) → &lt;strong&gt;IRSA&#x2F;Pod Identity&lt;&#x2F;strong&gt; (gives pods AWS permissions without static credentials).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;authorization-what-can-you-do&quot;&gt;Authorization: what can you do?&lt;&#x2F;h2&gt;
&lt;p&gt;Authentication tells K8s &lt;em&gt;who&lt;&#x2F;em&gt; you are. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;access-authn-authz&#x2F;rbac&#x2F;&quot;&gt;RBAC (Role-Based Access Control)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; tells K8s &lt;em&gt;what&lt;&#x2F;em&gt; you&#x27;re allowed to do. It&#x27;s the &lt;code&gt;sudo&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt; of the K8s world — except it operates on API verbs and resources instead of commands and files.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-four-rbac-objects&quot;&gt;The four RBAC objects&lt;&#x2F;h3&gt;
&lt;p&gt;RBAC uses four objects, organized in two pairs:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Object&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Scope&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Purpose&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Role&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Namespace&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Defines &lt;em&gt;what&lt;&#x2F;em&gt; actions are allowed on &lt;em&gt;which&lt;&#x2F;em&gt; resources within a namespace&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;RoleBinding&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Namespace&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Binds a Role to a user, group, or service account&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ClusterRole&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster-wide&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Same as Role, but applies across all namespaces&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ClusterRoleBinding&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster-wide&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Binds a ClusterRole to a user, group, or service account&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;practical-example-biomedical-research-context&quot;&gt;Practical example: biomedical research context&lt;&#x2F;h3&gt;
&lt;p&gt;Imagine a research cluster with two teams: one running genomic analysis pipelines, another managing a clinical trial data platform. You want each team to only access their own namespace:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Role: genomics researchers can manage pods, services, and jobs in their namespace
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Role&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-developer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroups&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pods&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;services&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;configmaps&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;get&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;list&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;watch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroups&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;batch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;jobs&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cronjobs&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;get&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;list&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;watch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroups&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;secrets&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;get&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;list&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Can read secrets but not create&#x2F;modify them
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# RoleBinding: attach this role to the genomics team group
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;RoleBinding&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-team-binding&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;subjects&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Group&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-team&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroup&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;roleRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Role&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-developer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiGroup&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;rbac.authorization.k8s.io&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The clinical trials team gets a similar setup in their own namespace — and &lt;em&gt;cannot&lt;&#x2F;em&gt; see or touch anything in the &lt;code&gt;genomics&lt;&#x2F;code&gt; namespace. This is the same principle as giving each department its own Linux user group with permissions scoped to specific directories — except here the &quot;directories&quot; are K8s namespaces and the &quot;permissions&quot; are API operations.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;network-security&quot;&gt;Network security&lt;&#x2F;h2&gt;
&lt;p&gt;By default, K8s is a flat network: every pod can talk to every other pod. This is convenient for development but a disaster for security. This is like every server in a data center on the same VLAN with no firewall.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network-policies&quot;&gt;Network Policies&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;Network Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are the &lt;code&gt;iptables&lt;&#x2F;code&gt; of the K8s world. They let you control which pods can communicate with which other pods.&lt;&#x2F;p&gt;
&lt;p&gt;A Network Policy selects pods using labels and defines allowed ingress (incoming) and&#x2F;or egress (outgoing) traffic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Default deny all ingress traffic in the namespace
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;NetworkPolicy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;default-deny-ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clinical-trials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;podSelector&lt;&#x2F;span&gt;&lt;span&gt;: {}  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Applies to ALL pods in this namespace
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;policyTypes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This single manifest changes everything: now no pod in &lt;code&gt;clinical-trials&lt;&#x2F;code&gt; can receive traffic unless explicitly allowed. This is the &quot;default deny&quot; approach, like configuring a firewall to block everything, then opening specific ports.&lt;&#x2F;p&gt;
&lt;p&gt;Now allow specific traffic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Allow only the web frontend to talk to the API server
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;NetworkPolicy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;allow-frontend-to-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clinical-trials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;podSelector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;trials-api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;policyTypes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ingress&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;podSelector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;trials-frontend&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;TCP&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Important caveat&lt;&#x2F;strong&gt;: Network Policies only work if your CNI plugin supports them. Calico, Cilium, and Weave support them. The default AWS VPC CNI &lt;em&gt;does not&lt;&#x2F;em&gt; enforce Network Policies natively — you need to install &lt;a href=&quot;https:&#x2F;&#x2F;docs.tigera.io&#x2F;calico&#x2F;latest&#x2F;getting-started&#x2F;kubernetes&#x2F;managed-public-cloud&#x2F;eks&quot;&gt;Calico&lt;&#x2F;a&gt; or enable the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;cni-network-policy.html&quot;&gt;AWS Network Policy Controller&lt;&#x2F;a&gt; (available since EKS v1.25 with VPC CNI v1.14+).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;security-groups-for-pods-eks-specific&quot;&gt;Security Groups for Pods (EKS-specific)&lt;&#x2F;h3&gt;
&lt;p&gt;In EKS, you can also apply &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;security-groups-for-pods.html&quot;&gt;Security Groups directly to pods&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. This bridges the K8s and AWS networking worlds: your pods get the same Security Group enforcement as EC2 instances.&lt;&#x2F;p&gt;
&lt;p&gt;This is useful when you need your pods to interact with AWS resources that use Security Groups for access control (like RDS databases). Instead of opening the database to the entire node&#x27;s Security Group, you assign a specific Security Group to only the pods that need database access.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;comparison-network-policies-vs-security-groups-vs-nacls&quot;&gt;Comparison: Network Policies vs Security Groups vs NACLs&lt;&#x2F;h3&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Feature&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;K8s Network Policies&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS Security Groups&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS NACLs&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Scope&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pod-to-pod within cluster&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;ENI-level (instance or pod)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Subnet-level&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Stateful?&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Depends on CNI&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Yes (return traffic auto-allowed)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;No (must allow both directions)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Default behavior&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Allow all (until a policy is applied)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Deny all inbound, allow all outbound&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Allow all (default NACL)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Selection method&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pod labels, namespace selectors&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Attached to ENIs&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Applied to subnets&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Aware of K8s concepts?&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Yes (pods, namespaces, labels)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;No (IP addresses and ports only)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;No (IP ranges and ports only)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Best for&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Intra-cluster segmentation&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Controlling access to AWS resources&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Subnet-level guardrails&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;In practice, you use &lt;strong&gt;all three layers together&lt;&#x2F;strong&gt;. Network Policies for pod-to-pod rules, Security Groups for pod-to-AWS-resource rules, and NACLs as a coarse subnet-level safety net. Defense in depth.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;eks_security_groups_pod_mapping.svg&quot; alt=&quot;&quot; title=&quot;I am obliged to admit I&#x27;m impressed by this level of orchestration&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pod-security&quot;&gt;Pod security&lt;&#x2F;h2&gt;
&lt;p&gt;Even if your network is locked down, a compromised container running as root with full Linux capabilities is a serious problem. Pod security is about restricting &lt;em&gt;what containers can do&lt;&#x2F;em&gt; on the node.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pod-security-standards-pod-security-admission-psa&quot;&gt;Pod Security Standards &amp;amp; Pod Security Admission (PSA)&lt;&#x2F;h3&gt;
&lt;p&gt;K8s defines three &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;pod-security-standards&#x2F;&quot;&gt;Pod Security Standards&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — profiles that describe increasing levels of restriction:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Profile&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Description&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Use case&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Privileged&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Unrestricted. No security checks.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;System-level workloads (CNI plugins, logging agents)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Baseline&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Prevents known privilege escalations. Blocks hostNetwork, hostPID, privileged containers.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Most application workloads&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Restricted&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Heavily restricted. Must run as non-root, drop all capabilities, read-only root filesystem.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Security-sensitive workloads&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;pod-security-admission&#x2F;&quot;&gt;Pod Security Admission (PSA)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; enforces these standards at the namespace level using labels:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Namespace&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clinical-trials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pod-security.kubernetes.io&#x2F;enforce&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;restricted&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pod-security.kubernetes.io&#x2F;warn&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;restricted&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pod-security.kubernetes.io&#x2F;audit&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;restricted&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this configuration, any pod in &lt;code&gt;clinical-trials&lt;&#x2F;code&gt; that violates the &lt;code&gt;restricted&lt;&#x2F;code&gt; profile will be rejected. The &lt;code&gt;warn&lt;&#x2F;code&gt; and &lt;code&gt;audit&lt;&#x2F;code&gt; modes give you visibility before you enforce.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;securitycontext&quot;&gt;SecurityContext&lt;&#x2F;h3&gt;
&lt;p&gt;For fine-grained control, every pod and container can specify a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;security-context&#x2F;&quot;&gt;SecurityContext&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;secure-analysis-job&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsNonRoot&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;runAsUser&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;fsGroup&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2000
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;analyzer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research-tools:v3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;securityContext&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;allowPrivilegeEscalation&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;false
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;readOnlyRootFilesystem&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;capabilities&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ALL&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;tmp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;data&#x2F;results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tmp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;emptyDir&lt;&#x2F;span&gt;&lt;span&gt;: {}
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;persistentVolumeClaim&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;claimName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;analysis-results&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This pod: runs as a non-root user (UID 1000), cannot escalate privileges, has a read-only root filesystem (with writable &lt;code&gt;&#x2F;tmp&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;data&#x2F;results&lt;&#x2F;code&gt; mounts), and drops all Linux capabilities. A compromised container in this configuration can do &lt;em&gt;very&lt;&#x2F;em&gt; little damage.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;workload-isolation-via-scheduling-constraints&quot;&gt;Workload isolation via scheduling constraints&lt;&#x2F;h3&gt;
&lt;p&gt;For sensitive workloads that should not share nodes with untrusted workloads, you can use &lt;strong&gt;taints and tolerations&lt;&#x2F;strong&gt; along with &lt;strong&gt;node affinity&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Taint a node group for sensitive workloads only
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# kubectl taint nodes -l workload=sensitive sensitive=true:NoSchedule
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Pod that tolerates the taint and prefers sensitive nodes
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tolerations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sensitive&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;operator&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Equal&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;NoSchedule&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;affinity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;nodeAffinity&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requiredDuringSchedulingIgnoredDuringExecution&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;nodeSelectorTerms&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchExpressions&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;workload&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;operator&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;In&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;values&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;sensitive&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is not full multi-tenancy (K8s isn&#x27;t designed for hostile multi-tenancy), but it ensures that your genomic analysis pipelines don&#x27;t share hardware with less trusted workloads.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;secrets-management&quot;&gt;Secrets management&lt;&#x2F;h2&gt;
&lt;p&gt;Every application has secrets: database passwords, API keys, TLS certificates. How you manage them in K8s matters &lt;em&gt;a lot&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-secrets-and-why-they-re-not-really-secret&quot;&gt;K8s Secrets (and why they&#x27;re not really secret)&lt;&#x2F;h3&gt;
&lt;p&gt;K8s has a built-in Secret object:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Secret&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Opaque&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;cG9zdGdyZXM=&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64 of &amp;quot;postgres&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;c3VwZXJzZWNyZXQ=&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64 of &amp;quot;supersecret&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The problem: this is base64 &lt;em&gt;encoding&lt;&#x2F;em&gt;, not encryption. Run &lt;code&gt;echo c3VwZXJzZWNyZXQ= | base64 -d&lt;&#x2F;code&gt; and you get &lt;code&gt;supersecret&lt;&#x2F;code&gt;. Anyone with &lt;code&gt;kubectl get secret -o yaml&lt;&#x2F;code&gt; access can read all your secrets. And in etcd, they&#x27;re stored in plain text (well, base64).&lt;&#x2F;p&gt;
&lt;p&gt;K8s Secrets are useful as &lt;em&gt;a delivery mechanism&lt;&#x2F;em&gt; (mounting credentials into pods), but they are &lt;strong&gt;not a secret store&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;encryption-at-rest-with-kms&quot;&gt;Encryption at rest with KMS&lt;&#x2F;h3&gt;
&lt;p&gt;The minimum you should do: enable &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;administer-cluster&#x2F;encrypt-data&#x2F;&quot;&gt;encryption at rest for etcd&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;. In EKS, this is straightforward — you provide a KMS key when creating or updating the cluster:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws eks create-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --name my-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --encryption-config &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;[{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    &amp;quot;resources&amp;quot;: [&amp;quot;secrets&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    &amp;quot;provider&amp;quot;: {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;      &amp;quot;keyArn&amp;quot;: &amp;quot;arn:aws:kms:eu-west-3:123456789012:key&#x2F;your-kms-key-id&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;  }]&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span&gt;  ...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now secrets are encrypted in etcd using your KMS key. This protects against someone gaining access to the underlying storage — but anyone with RBAC permissions to &lt;code&gt;get secrets&lt;&#x2F;code&gt; can still read them through the API.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;external-secret-stores&quot;&gt;External secret stores&lt;&#x2F;h3&gt;
&lt;p&gt;For production, you should integrate with a dedicated secret management solution:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;secrets-manager&#x2F;&quot;&gt;AWS Secrets Manager&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; or &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;systems-manager&#x2F;latest&#x2F;userguide&#x2F;systems-manager-parameter-store.html&quot;&gt;AWS Systems Manager Parameter Store&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Store secrets in AWS, fetch them into K8s at runtime. The &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;secretsmanager&#x2F;latest&#x2F;userguide&#x2F;integrating_csi_driver.html&quot;&gt;AWS Secrets Store CSI Driver&lt;&#x2F;a&gt; mounts AWS secrets as volumes in your pods.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;external-secrets.io&#x2F;&quot;&gt;External Secrets Operator&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: A K8s operator that syncs secrets from external stores (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager) into K8s Secret objects. You define an &lt;code&gt;ExternalSecret&lt;&#x2F;code&gt; resource, and the operator keeps the K8s Secret in sync:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;external-secrets.io&#x2F;v1beta1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ExternalSecret&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;refreshInterval&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;1h&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;secretStoreRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aws-secrets-manager&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ClusterSecretStore&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;target&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;secretKey&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;remoteRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&#x2F;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;property&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;secretKey&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;remoteRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research&#x2F;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;property&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sealed-secrets.netlify.app&#x2F;&quot;&gt;Sealed Secrets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Encrypts secrets so they can be safely stored in Git. A controller in the cluster decrypts them. Useful for GitOps workflows where you want everything in version control but can&#x27;t commit plain secrets.&lt;&#x2F;p&gt;
&lt;p&gt;The pattern is: &lt;strong&gt;secrets live in a dedicated, encrypted, access-controlled store&lt;&#x2F;strong&gt; (AWS Secrets Manager, Vault); &lt;strong&gt;K8s fetches them at runtime&lt;&#x2F;strong&gt; (via CSI driver or operator); &lt;strong&gt;RBAC limits who can access them&lt;&#x2F;strong&gt; within the cluster.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resource-quotas-limitranges&quot;&gt;Resource quotas &amp;amp; LimitRanges&lt;&#x2F;h2&gt;
&lt;p&gt;This is the security concern people forget: &lt;strong&gt;resource abuse&lt;&#x2F;strong&gt;. A single runaway pod consuming all CPU or memory on a node is a denial-of-service attack — even if it&#x27;s accidental. In a shared cluster (multiple teams, multiple namespaces), resource guardrails are essential.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;resourcequotas&quot;&gt;ResourceQuotas&lt;&#x2F;h3&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;policy&#x2F;resource-quotas&#x2F;&quot;&gt;ResourceQuota&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; sets hard limits on what a namespace can consume:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ResourceQuota&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;research-quota&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;hard&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests.cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;20&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests.memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;40Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits.cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;40&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits.memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;80Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pods&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;50&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;persistentvolumeclaims&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;10&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;services.loadbalancers&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This ensures the genomics team can&#x27;t accidentally (or intentionally) starve the clinical trials team of resources. It&#x27;s the K8s equivalent of disk quotas and &lt;code&gt;ulimit&lt;&#x2F;code&gt; — applied at the namespace level.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;limitranges&quot;&gt;LimitRanges&lt;&#x2F;h3&gt;
&lt;p&gt;While ResourceQuotas cap the &lt;em&gt;total&lt;&#x2F;em&gt; for a namespace, &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;policy&#x2F;limit-range&#x2F;&quot;&gt;LimitRanges&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; set &lt;em&gt;per-pod&lt;&#x2F;em&gt; defaults and limits:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LimitRange&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;default-limits&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;500m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;256Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;defaultRequest&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;100m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;128Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;max&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;4&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;8Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;50m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;64Mi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Container&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If a developer deploys a pod without specifying resource requests&#x2F;limits, LimitRange fills in the defaults. If they request more than the max, the pod is rejected. This prevents the classic &quot;someone deployed a pod with no limits and it ate the entire node&quot; scenario.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;audit-observability&quot;&gt;Audit &amp;amp; observability&lt;&#x2F;h2&gt;
&lt;p&gt;You can&#x27;t secure what you can&#x27;t see. Audit logging answers the question: &lt;strong&gt;who did what, when, and from where?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-audit-logging&quot;&gt;K8s audit logging&lt;&#x2F;h3&gt;
&lt;p&gt;The K8s API server can log every request it receives. Audit events are categorized by stage:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RequestReceived&lt;&#x2F;strong&gt;: The request was received but not yet processed&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ResponseStarted&lt;&#x2F;strong&gt;: Response headers sent, body not yet (for long-running requests like &lt;code&gt;watch&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ResponseComplete&lt;&#x2F;strong&gt;: The full response was sent&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Panic&lt;&#x2F;strong&gt;: Something went very wrong&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And by level:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;None&lt;&#x2F;strong&gt;: Don&#x27;t log&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Metadata&lt;&#x2F;strong&gt;: Log request metadata (user, timestamp, resource, verb) but not body&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Request&lt;&#x2F;strong&gt;: Log metadata + request body&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;RequestResponse&lt;&#x2F;strong&gt;: Log everything (metadata + request body + response body)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;An audit policy defines what to log for different resources:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;audit.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Policy&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Log all changes to secrets at the RequestResponse level
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;RequestResponse&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;group&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;secrets&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Log pod changes at the Request level
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Request&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;group&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pods&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;verbs&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;create&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;patch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;delete&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Log everything else at Metadata level
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Metadata&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;eks-control-plane-logging-cloudwatch&quot;&gt;EKS control plane logging → CloudWatch&lt;&#x2F;h3&gt;
&lt;p&gt;In EKS, you don&#x27;t configure the audit policy directly (the control plane is managed). Instead, you enable &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;control-plane-logs.html&quot;&gt;EKS control plane logging&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; which sends logs to CloudWatch:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws eks update-cluster-config \
&lt;&#x2F;span&gt;&lt;span&gt;  --name my-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --logging &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    &amp;quot;clusterLogging&amp;quot;: [{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;      &amp;quot;types&amp;quot;: [&amp;quot;api&amp;quot;, &amp;quot;audit&amp;quot;, &amp;quot;authenticator&amp;quot;, &amp;quot;controllerManager&amp;quot;, &amp;quot;scheduler&amp;quot;],
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;      &amp;quot;enabled&amp;quot;: true
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;    }]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;  }&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The five log types:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;api&lt;&#x2F;strong&gt;: API server request logs&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;audit&lt;&#x2F;strong&gt;: K8s audit logs (who did what)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;authenticator&lt;&#x2F;strong&gt;: IAM authentication events&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;controllerManager&lt;&#x2F;strong&gt;: Controller decisions (scaling, reconciliation)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;scheduler&lt;&#x2F;strong&gt;: Pod placement decisions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;connecting-to-cloudtrail&quot;&gt;Connecting to CloudTrail&lt;&#x2F;h3&gt;
&lt;p&gt;Here&#x27;s where the AWS training series comes full circle. &lt;a href=&quot;&#x2F;posts&#x2F;aws-2-3&#x2F;#cloudtrail-who-did-what-and-when&quot;&gt;CloudTrail&lt;&#x2F;a&gt; records AWS API calls — &lt;code&gt;CreateCluster&lt;&#x2F;code&gt;, &lt;code&gt;UpdateNodegroup&lt;&#x2F;code&gt;, &lt;code&gt;AssociateEncryptionConfig&lt;&#x2F;code&gt;. CloudWatch Logs receives K8s-level audit events — &lt;code&gt;kubectl apply&lt;&#x2F;code&gt;, &lt;code&gt;kubectl delete&lt;&#x2F;code&gt;, &lt;code&gt;kubectl exec&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Together, they give you the full picture:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CloudTrail&lt;&#x2F;strong&gt;: &quot;Who created the cluster? Who changed the node group? Who modified IAM roles?&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;CloudWatch (K8s audit logs)&lt;&#x2F;strong&gt;: &quot;Who deployed this pod? Who accessed this secret? Who exec&#x27;d into that container?&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a biomedical research environment handling sensitive patient data, this level of traceability isn&#x27;t optional — it&#x27;s often a compliance requirement (HIPAA, GDPR).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;best-practices-checklist&quot;&gt;Best practices checklist&lt;&#x2F;h2&gt;
&lt;p&gt;Here&#x27;s what &quot;secure by default&quot; should look like, organized by layer:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Identity &amp;amp; Access&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Apply least-privilege RBAC: namespace-scoped Roles over ClusterRoles&lt;&#x2F;li&gt;
&lt;li&gt;Create dedicated Service Accounts per workload; disable auto-mount for pods that don&#x27;t need API access&lt;&#x2F;li&gt;
&lt;li&gt;Use IRSA or EKS Pod Identity for AWS access — never store AWS credentials as K8s Secrets&lt;&#x2F;li&gt;
&lt;li&gt;Audit RoleBindings and ClusterRoleBindings regularly&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Network&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Apply default-deny NetworkPolicies to every namespace&lt;&#x2F;li&gt;
&lt;li&gt;Segment namespaces by trust level (production vs staging, team A vs team B)&lt;&#x2F;li&gt;
&lt;li&gt;Use Security Groups for Pods when controlling access to AWS resources&lt;&#x2F;li&gt;
&lt;li&gt;Restrict API server endpoint access (private endpoint in EKS)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Pods&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enforce Pod Security Standards (at least &lt;code&gt;baseline&lt;&#x2F;code&gt;, ideally &lt;code&gt;restricted&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Run containers as non-root, with read-only root filesystem&lt;&#x2F;li&gt;
&lt;li&gt;Drop all Linux capabilities, add back only what&#x27;s needed&lt;&#x2F;li&gt;
&lt;li&gt;Use taints&#x2F;tolerations to isolate sensitive workloads on dedicated nodes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Secrets&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enable etcd encryption at rest (KMS key in EKS)&lt;&#x2F;li&gt;
&lt;li&gt;Use an external secret store (AWS Secrets Manager, Vault) — not raw K8s Secrets&lt;&#x2F;li&gt;
&lt;li&gt;Rotate secrets automatically; never commit secrets to Git in plain text&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Audit &amp;amp; Observability&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enable all EKS control plane log types (api, audit, authenticator, controllerManager, scheduler)&lt;&#x2F;li&gt;
&lt;li&gt;Set up alerts for privilege escalation attempts, &lt;code&gt;kubectl exec&lt;&#x2F;code&gt; into production pods, secret access patterns&lt;&#x2F;li&gt;
&lt;li&gt;Cross-reference K8s audit logs with CloudTrail for full traceability&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Supply Chain&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Scan container images for vulnerabilities (Trivy, Snyk, ECR image scanning)&lt;&#x2F;li&gt;
&lt;li&gt;Use trusted base images from verified registries&lt;&#x2F;li&gt;
&lt;li&gt;Sign and verify container images (cosign, Notation)&lt;&#x2F;li&gt;
&lt;li&gt;Pin image tags to digests (&lt;code&gt;image: my-app@sha256:abc123...&lt;&#x2F;code&gt; instead of &lt;code&gt;image: my-app:latest&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For a comprehensive, opinionated, and up-to-date reference, see the &lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;security&#x2F;docs&#x2F;&quot;&gt;AWS EKS Best Practices Guide&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Security consists of a series of layers that are stacked on top of one another. K8s gives you all the layers: RBAC, Network Policies, Pod Security Admission, audit logging, Secrets encryption. But it doesn&#x27;t stack them on for you. &lt;strong&gt;The defaults are permissive by design&lt;&#x2F;strong&gt;, because K8s optimizes for getting things running.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve got a terrible headache, I&#x27;ve learnt a lot of new concepts this week, but I can tell I haven&#x27;t quite got the hang of them yet. In the mean time, here are resources for you to go further:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;&quot;&gt;K8s security documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;security&#x2F;docs&#x2F;&quot;&gt;AWS EKS best practices guide - Security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;security&#x2F;pod-security-standards&#x2F;&quot;&gt;Pod Security Standards&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;Network Policies&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;access-authn-authz&#x2F;rbac&#x2F;&quot;&gt;RBAC documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;trivy.dev&#x2F;&quot;&gt;Trivy - container image scanner&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;external-secrets.io&#x2F;&quot;&gt;External Secrets Operator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sealed-secrets.netlify.app&#x2F;&quot;&gt;Sealed Secrets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.tigera.io&#x2F;calico&#x2F;latest&#x2F;getting-started&#x2F;kubernetes&#x2F;managed-public-cloud&#x2F;eks&quot;&gt;Calico Network Policies for EKS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;aquasecurity&#x2F;kube-bench&quot;&gt;kube-bench - CIS K8s Benchmark checker&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;falco.org&#x2F;&quot;&gt;Falco - runtime security&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=oBf5lrmquYI&quot;&gt;K8s security best practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=jvhKOAB3Jfk&quot;&gt;RBAC explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=G3R24JSlGjY&quot;&gt;Understand RBAC in k8s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=dTKGkOiVFfA&quot;&gt;Network Policies explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=HRU0aCkhgwg&quot;&gt;7 k8s security best practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;headache.jpg&quot; alt=&quot;Too much concepts to digest&quot; title=&quot;Too much concepts to digest&quot;&#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 4)</title>
        <published>2026-02-05T00:00:00+00:00</published>
        <updated>2026-02-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-4/"/>
        <id>https://nskm.xyz/posts/aws-4/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-4/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;albator84.webp&quot; alt=&quot;Come on maaan, I was obliged&quot; title=&quot;Come on maaan, I was obliged&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;My employer says I don&#x27;t have the right to share the source code I&#x27;ve written in the course of my work. So, I&#x27;ll try to say as much as I can without divulging any specific information.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The interactions between EKS and the broader AWS ecosystem can only be fully understood through &lt;em&gt;real &amp;amp; serious&lt;&#x2F;em&gt; practice. AWS offers a &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;free&#x2F;&quot;&gt;free tier&lt;&#x2F;a&gt; with limited resources. Start small, monitor your costs, and don&#x27;t leave clusters running when you&#x27;re done.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;This article is &lt;strong&gt;educational content&lt;&#x2F;strong&gt;, &lt;em&gt;in case you missed it&lt;&#x2F;em&gt;, not a production deployment guide. Everything was intentionally simplified here for clarity. Before running EKS in production, please consult the &lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;AWS EKS best practices guide&lt;&#x2F;a&gt; and involve your security&#x2F;infrastructure teams.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A special thank you to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;Abdoul Karim&lt;&#x2F;a&gt; for taking the time to re-read this article and for his honest, sharp feedback — he is the one who pointed out that it read more like a Kubernetes tutorial than an EKS article. That observation directly led to the hands-on EKS examples being added. Thanks a million to him.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;This is the day 4 of the training course. The most exhausting part isn&#x27;t the training itself. The most exhausting part is that I have to leave the house earlier than usual in the hope of arriving on time (as someone who usually arrive at work at 10am).&lt;&#x2F;p&gt;
&lt;p&gt;Today will be easier than yesterday, &lt;em&gt;I hope&lt;&#x2F;em&gt;, because I’m not starting from scratch; I already know a thing or two about Kubernetes. I more or less know how to write some manifests files and use them to deploy my Django projects. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=v3oK0yMZzgo&quot;&gt;go&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The name Kubernetes originates from Ancient Greek: κυβερνήτης, romanized: kubernḗtēs, meaning pilot, steersman, navigator, and the etymological root of cybernetics. Kubernetes is often abbreviated as K8s, counting the eight letters between the K and the s (a numeronym).&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-concepts-traditional-infrastructure&quot;&gt;K8S concepts → traditional infrastructure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#why-containers&quot;&gt;Why containers?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#kubernetes-fundamentals&quot;&gt;Kubernetes fundamentals&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-architecture&quot;&gt;K8S architecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-core-objects&quot;&gt;K8S core objects&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#k8s-configuration-tooling&quot;&gt;K8S configuration &amp;amp; tooling&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#enter-eks&quot;&gt;Enter EKS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#eks-networking-iam-integration&quot;&gt;EKS networking &amp;amp; IAM integration&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#practical-example&quot;&gt;Practical example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#eks-vs-alternatives&quot;&gt;EKS vs. alternatives&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-4&#x2F;#more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;k8s-concepts-traditional-infrastructure&quot;&gt;K8S concepts → traditional infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been managing Linux servers and containers, you already know most of these concepts. Kubernetes just orchestrates them at scale with different names:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;K8S Concept&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;What&#x27;s Different?&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Cluster&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A set of servers you SSH into&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Managed as a single unit, self-healing&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Control Plane&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Your Ansible&#x2F;Puppet master server&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manages scheduling, state, API; you don&#x27;t run workloads on it&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Worker Node&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A Linux server running your apps&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;K8S schedules pods onto it automatically&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pod&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A process or &lt;code&gt;systemd&lt;&#x2F;code&gt; unit&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Ephemeral, gets its own IP, holds containers&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Deployment&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;systemd&lt;&#x2F;code&gt; service + rolling restart script&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Declarative desired state, automatic rollback, self-healing&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;StatefulSet&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manually managed database instances&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Ordered startup, stable network identity, persistent storage per replica&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;DaemonSet&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A service enabled on every server (&lt;code&gt;systemctl enable&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Ensures one pod per node, useful for log collectors, monitoring agents&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Service&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;DNS entry + &lt;code&gt;iptables&lt;&#x2F;code&gt; rules &#x2F; HAProxy&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Stable endpoint for ephemeral pods, built-in load balancing&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Ingress&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Nginx or HAProxy reverse proxy config&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Declarative HTTP&#x2F;HTTPS routing, TLS termination, path-based rules&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ConfigMap&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;export, .env file, configuration files in &#x2F;etc&#x2F;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Decoupled from the container image, injectable as env vars or mounted files&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Secret&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;gpg&lt;&#x2F;code&gt;-encrypted files, &lt;code&gt;pass&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Base64 encoded (not encrypted by default!), injectable like ConfigMaps&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Volume&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;mnt&lt;&#x2F;code&gt;, NFS mount, LVM&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Lifecycle tied to pod (ephemeral) or independent (PersistentVolume)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Namespace&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Linux users&#x2F;groups, separate directories&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Logical cluster partitioning, resource quotas, access control boundaries&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;kubectl&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;ssh&lt;&#x2F;code&gt; + &lt;code&gt;systemctl&lt;&#x2F;code&gt; + &lt;code&gt;journalctl&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Single CLI to manage everything in the cluster&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Helm&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;apt&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;dnf&lt;&#x2F;code&gt; package manager&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Templated K8S manifests, versioned releases, rollback support&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;kubeconfig&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;~&#x2F;.ssh&#x2F;config&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Defines which clusters you can talk to and with which credentials&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;The trade-off&lt;&#x2F;strong&gt;: You give up simplicity (one server, one config file, one &lt;code&gt;systemctl restart&lt;&#x2F;code&gt;) in exchange for automatic scaling, self-healing, and declarative infrastructure. Whether that&#x27;s worth it depends on whether you&#x27;re running 2 containers or 200. And if you understood everything in the table above, you can stop here, I&#x27;m serious :\&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;want-to-know-more-okay&quot;&gt;Want to know more ? Okay&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;why-containers&quot;&gt;Why containers?&lt;&#x2F;h3&gt;
&lt;p&gt;Before Kubernetes, there were containers. Before containers, there was the classic problem: &lt;em&gt;&quot;it works on my machine.&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You write a Python script that processes epidemiological data. It runs perfectly on your laptop with Python 3.11, pandas 2.1, and that one obscure C library you installed six months ago and forgot about. You hand it to a colleague. It breaks. Different Python version, missing library, wrong OS. You spend half a day debugging environment issues instead of doing actual work.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Containers &lt;em&gt;promise&lt;&#x2F;em&gt; to solve this.&lt;&#x2F;strong&gt; A container packages your application &lt;em&gt;and&lt;&#x2F;em&gt; its entire runtime environment (OS libraries, Python version, dependencies) into a single, portable image. If it runs in the container on your laptop, it runs the same way on a server in Bamako, in Luanda, or on your colleague&#x27;s machine. No surprises*.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Without containers:              With containers:
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+          +-----------------------+
&lt;&#x2F;span&gt;&lt;span&gt;| App A (Python 3.9)  |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| App B (Python 3.11) |          | | Container A       | |
&lt;&#x2F;span&gt;&lt;span&gt;| App C (Java 17)     |          | | Python 3.9 + App  | |
&lt;&#x2F;span&gt;&lt;span&gt;| Conflicting deps!   |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| Shared OS libraries |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| &amp;quot;Who installed      |          | | Container B       | |
&lt;&#x2F;span&gt;&lt;span&gt;|  what?&amp;quot;             |          | | Python 3.11 + App | |
&lt;&#x2F;span&gt;&lt;span&gt;|                     |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| One bare-metal      |          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;| server              |          | | Container C       | |
&lt;&#x2F;span&gt;&lt;span&gt;|                     |          | | Java 17 + App     | |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+          | +-------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;                                 | Isolated, no          |
&lt;&#x2F;span&gt;&lt;span&gt;                                 | conflicts             |
&lt;&#x2F;span&gt;&lt;span&gt;                                 +-----------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;So why do you need Kubernetes?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Containers solve the packaging problem. But in production, new questions appear:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You have 15 containers across 6 servers, how do you know which server has capacity for a new one?&lt;&#x2F;li&gt;
&lt;li&gt;A server crashes at 2am, who restarts the containers that were running on it?&lt;&#x2F;li&gt;
&lt;li&gt;Traffic spikes on Monday morning, how do you spin up more copies of your web app?&lt;&#x2F;li&gt;
&lt;li&gt;You push a bad update, how do you roll back quickly?&lt;&#x2F;li&gt;
&lt;li&gt;Your containers need to talk to each other, who manages the networking and service discovery?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You &lt;em&gt;could&lt;&#x2F;em&gt; solve all of this with bash scripts, cron jobs, and Ansible playbooks. People did, for years. It worked, until it didn&#x27;t — usually at the worst possible moment.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes (K8S)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is an open-source platform created at Google by &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;jbeda&quot;&gt;Joe Beda&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;brendan-burns-487aa590&quot;&gt;Brendan Burns&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;craigmcluckie&quot;&gt;Craig McLuckie&lt;&#x2F;a&gt;. Announced in &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;blog&#x2F;products&#x2F;containers-kubernetes&#x2F;from-google-to-the-world-the-kubernetes-origin-story&quot;&gt;June 2014&lt;&#x2F;a&gt;, it grew out of Google&#x27;s internal cluster manager &lt;a href=&quot;https:&#x2F;&#x2F;research.google&#x2F;pubs&#x2F;large-scale-cluster-management-at-google-with-borg&#x2F;&quot;&gt;Borg&lt;&#x2F;a&gt;, which had been orchestrating containers at massive scale for over a decade. Inspired by Docker&#x27;s rise, the three founders saw the need for something that could orchestrate &lt;em&gt;many&lt;&#x2F;em&gt; containers across &lt;em&gt;many&lt;&#x2F;em&gt; machines. Google &lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;reports&#x2F;kubernetes-project-journey-report&#x2F;&quot;&gt;donated Kubernetes to the CNCF&lt;&#x2F;a&gt; in 2015, and it quickly became the industry standard.&lt;&#x2F;p&gt;
&lt;p&gt;You tell K8S &lt;em&gt;what&lt;&#x2F;em&gt; you want (3 replicas of my app, exposed on port 443, with 2GB of RAM each), and it figures out &lt;em&gt;how&lt;&#x2F;em&gt; to make it happen. If something breaks, K8S fixes it automatically. &lt;em&gt;That&#x27;s the pitch&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;kubernetes-fundamentals&quot;&gt;Kubernetes fundamentals&lt;&#x2F;h3&gt;
&lt;p&gt;Kubernetes operates on one core principle: &lt;strong&gt;declarative configuration&lt;&#x2F;strong&gt;. Instead of telling the system &lt;em&gt;how&lt;&#x2F;em&gt; to do things step by step (imperative), you describe &lt;em&gt;what&lt;&#x2F;em&gt; you want the end state to look like, and K8s figures out how to get there.&lt;&#x2F;p&gt;
&lt;p&gt;On a traditional Linux server, you might do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Imperative: you tell the system every step
&lt;&#x2F;span&gt;&lt;span&gt;podman run -d --name webapp -p 8080:80 my-app:v2
&lt;&#x2F;span&gt;&lt;span&gt;podman stop webapp-old
&lt;&#x2F;span&gt;&lt;span&gt;podman rm webapp-old
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With Kubernetes, you write a manifest:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Declarative: you describe the desired state
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app:v2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You apply it (&lt;code&gt;kubectl apply -f webapp.yaml&lt;&#x2F;code&gt;), and K8s handles the rest: scheduling pods on nodes with available resources, rolling out the new version, terminating old pods, restarting anything that crashes. You described &lt;em&gt;what&lt;&#x2F;em&gt; you want — 3 replicas of &lt;code&gt;my-app:v2&lt;&#x2F;code&gt; on port 80 — and K8S continuously works to make reality match your description. This is called the &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;architecture&#x2F;controller&#x2F;&quot;&gt;reconciliation loop&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: K8s constantly compares the desired state (your manifest) with the actual state (what&#x27;s running), and corrects any drift.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Nota Bene:&lt;&#x2F;strong&gt; Every K8s object — Pods, Services, Deployments — is just a piece of desired state that a controller is responsible for reconciling.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-architecture&quot;&gt;K8s architecture&lt;&#x2F;h3&gt;
&lt;p&gt;A Kubernetes cluster is split into two layers: the &lt;strong&gt;control plane&lt;&#x2F;strong&gt; that makes decisions, and the &lt;strong&gt;worker nodes&lt;&#x2F;strong&gt; that run your actual workloads.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;                            +--------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                            |                            K8S CLUSTER                       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                                                              |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      +-----------------------------+                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |       CONTROL PLANE         |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |                             |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |Scheduler |  |API      |  |&amp;lt;-- kubectl talks here   |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |          |  |Server   |  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |Controller|  | etcd    |  |&amp;lt;-- cluster state lives  |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  |Manager   |  |  (kv)   |  |        here             |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      |  +----------+  +---------+  |                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |      +-----------------------------+                         |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                      | ^                                     |
&lt;&#x2F;span&gt;&lt;span&gt;                            |           instructs  | | reports back                        |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                      v |                                     |
&lt;&#x2F;span&gt;&lt;span&gt;                            |                                                              |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  +-------------+    +-------------+    +-------------+       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | WORKER 1    |    | WORKER 2    |    | WORKER 3    |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  |             |    |             |    |             |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |kubelet  | |    | |kubelet  | |    | |kubelet  | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |kube     | |    | |kube     | |    | |kube     | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |proxy    | |    | |proxy    | |    | |proxy    | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |container| |    | |container| |    | |container| |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |runtime  | |    | |runtime  | |    | |runtime  | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |Pod A    | |    | |Pod C    | |    | |Pod E    | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | |Pod B    | |    | |Pod D    | |    | |         | |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  | +---------+ |    | +---------+ |    | +---------+ |       |
&lt;&#x2F;span&gt;&lt;span&gt;                            |  +-------------+    +-------------+    +-------------+       |
&lt;&#x2F;span&gt;&lt;span&gt;                            +--------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#control-plane-components&quot;&gt;Control Plane&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (also called master nodes) — the brain of the cluster. It doesn&#x27;t run your applications; it manages everything else:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Component&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Role&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-apiserver&quot;&gt;API Server&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Front door for all cluster operations. Every &lt;code&gt;kubectl&lt;&#x2F;code&gt; command, every internal component, talks through it&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;The SSH daemon + a REST API on your server&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#etcd&quot;&gt;etcd&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Distributed key-value store holding the entire cluster state&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Your &lt;code&gt;&#x2F;etc&lt;&#x2F;code&gt; directory + a database, replicated&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-scheduler&quot;&gt;Scheduler&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Decides which worker node should run a new pod based on resource availability and constraints&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You, manually picking which server to deploy to&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-controller-manager&quot;&gt;Controller Manager&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Runs the reconciliation loops — watches desired state vs actual state and corrects drift&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Your Ansible playbooks running on a schedule&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;The control plane requires fewer resources than worker nodes but is &lt;em&gt;far more critical&lt;&#x2F;em&gt;. In production, you run at least 2 control plane nodes (one primary, one for recovery) so the cluster survives a node failure.&lt;&#x2F;p&gt;
 &lt;br&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#node-components&quot;&gt;Worker Nodes&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are where the heavy lifting happens: we are talking about bigger machines, more CPU, more RAM, hosting all your application pods. They&#x27;re also more expendable than control plane nodes, if a worker dies, the scheduler simply reschedules its pods onto surviving nodes. Each worker node has three main components:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Component&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Description&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kubelet&quot;&gt;Kubelet&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;An agent running on each node. It receives pod specifications from the API Server, ensures the containers described in those specs are running and healthy, and reports status back. Think of it as a local &lt;code&gt;systemd&lt;&#x2F;code&gt; that takes orders from the control plane.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;overview&#x2F;components&#x2F;#kube-proxy&quot;&gt;Kube-proxy&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;A network component on each node that maintains network rules, enabling communication to and from your pods. It&#x27;s what makes Services work — routing traffic to the right pod regardless of which node it&#x27;s on.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;setup&#x2F;production-environment&#x2F;container-runtimes&#x2F;&quot;&gt;Container runtime&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;The software that actually runs containers. K8s supports &lt;a href=&quot;https:&#x2F;&#x2F;containerd.io&#x2F;&quot;&gt;containerd&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;cri-o.io&#x2F;&quot;&gt;CRI-O&lt;&#x2F;a&gt;, and any runtime implementing the &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;architecture&#x2F;cri&#x2F;&quot;&gt;Container Runtime Interface (CRI)&lt;&#x2F;a&gt;. Docker was the original default but was &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;blog&#x2F;2022&#x2F;02&#x2F;17&#x2F;dockershim-faq&#x2F;&quot;&gt;deprecated as a runtime in K8s 1.24&lt;&#x2F;a&gt;.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;h3 id=&quot;k8s-core-objects&quot;&gt;K8s core objects&lt;&#x2F;h3&gt;
&lt;p&gt;Now that you understand the architecture, let&#x27;s walk through the objects you&#x27;ll actually work with \o&#x2F;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;pods&quot;&gt;Pods&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;pods&#x2F;&quot;&gt;Pod&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the smallest deployable unit in Kubernetes. It&#x27;s an abstraction over one or more containers, usually running a single application. Each pod gets its own IP address and can hold sidecar containers (supporting processes like log shippers or proxies).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.redhat.com&#x2F;en&#x2F;documentation&#x2F;red_hat_enterprise_linux&#x2F;8&#x2F;html&#x2F;building_running_and_managing_containers&#x2F;assembly_working-with-pods_building-running-and-managing-containers&quot;&gt;Pods&lt;&#x2F;a&gt; are &lt;strong&gt;ephemeral&lt;&#x2F;strong&gt; — they&#x27;re designed to be disposable. If a pod dies, it&#x27;s gone. K8s creates a new one to replace it, with a different IP. This is why you never talk to pods directly in production.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;nginx:1.25&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional server, a pod is roughly equivalent to a running process or a &lt;code&gt;systemd&lt;&#x2F;code&gt; unit. The difference? K8s manages the pod&#x27;s lifecycle automatically.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;services&quot;&gt;Services&lt;&#x2F;h4&gt;
&lt;p&gt;Since pods are ephemeral, you need a stable endpoint to reach them. That&#x27;s what a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;&quot;&gt;Service&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; provides — a permanent IP address and DNS name that load-balances across a set of pods. If a pod dies and gets replaced, the Service keeps working.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Types of Services:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Type&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Scope&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Use Case&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#type-clusterip&quot;&gt;ClusterIP&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (default)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Internal cluster IP&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Backend services that don&#x27;t need external access&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#type-nodeport&quot;&gt;NodePort&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Exposes on each node&#x27;s IP at a static port&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Quick external access for testing (not recommended for production)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#loadbalancer&quot;&gt;LoadBalancer&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cloud provider&#x27;s load balancer&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Production external access (on AWS, creates an ELB&#x2F;ALB)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;#externalname&quot;&gt;ExternalName&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;DNS CNAME mapping&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pointing to external services (&lt;code&gt;database.example.com&lt;&#x2F;code&gt;)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Matches pods with this label
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;targetPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LoadBalancer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Think of a Service as your &lt;code&gt;iptables&lt;&#x2F;code&gt; rules + HAProxy + DNS entry, all managed declaratively.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ingress&quot;&gt;Ingress&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;service&#x2F;&quot;&gt;Service&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; can expose your app, but what if you have 10 services and want them all behind a single domain with path-based routing? That&#x27;s what &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;ingress&#x2F;&quot;&gt;Ingress&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; does — HTTP&#x2F;HTTPS routing with TLS termination and name-based virtual hosting.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;example.com&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;app&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pathType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Prefix&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;api&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pathType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Prefix&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;api-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;ingress-controllers&#x2F;&quot;&gt;Ingress Controller&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (like &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.github.io&#x2F;ingress-nginx&#x2F;&quot;&gt;Nginx Ingress Controller&lt;&#x2F;a&gt; or AWS&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes-sigs.github.io&#x2F;aws-load-balancer-controller&#x2F;&quot;&gt;ALB Ingress Controller&lt;&#x2F;a&gt;) is required to implement the rules. On a single Linux server, this is just Nginx or HAProxy configured as a reverse proxy.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;configmaps&quot;&gt;ConfigMaps&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;configmap&#x2F;&quot;&gt;ConfigMap&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; stores configuration data separately from your container image. You can inject it as environment variables or mount it as files in a pod. This decouples config from code — no rebuilding images just to change a database URL.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ConfigMap&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;app-config&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;DATABASE_URL&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;postgres:&#x2F;&#x2F;db.example.com:5432&#x2F;mydb&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;LOG_LEVEL&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;info&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Reference it in a pod:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app:v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;envFrom&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;configMapRef&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;app-config&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional server, this is just files in &lt;code&gt;&#x2F;etc&#x2F;myapp&#x2F;&lt;&#x2F;code&gt;. K8s makes them version-controlled and injectable.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;secrets&quot;&gt;Secrets&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;secret&#x2F;&quot;&gt;Secrets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; work exactly like ConfigMaps, but they&#x27;re intended for sensitive data (passwords, API keys). They&#x27;re stored base64-encoded, &lt;strong&gt;not encrypted by default&lt;&#x2F;strong&gt; in etcd. For real encryption at rest, enable &lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;administer-cluster&#x2F;encrypt-data&#x2F;&quot;&gt;etcd encryption&lt;&#x2F;a&gt; or use external secret managers like &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;secretsmanager&#x2F;latest&#x2F;userguide&#x2F;intro.html&quot;&gt;AWS Secrets Manager&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;external-secrets.io&#x2F;&quot;&gt;External Secrets Operator&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Secret&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-credentials&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Opaque&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;username&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;YWRtaW4=&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64(&amp;quot;admin&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;cGFzc3dvcmQ=&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# base64(&amp;quot;password&amp;quot;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a Linux server, this is like files encrypted with &lt;code&gt;gpg&lt;&#x2F;code&gt; or managed by &lt;code&gt;pass&lt;&#x2F;code&gt;. The K8s equivalent just integrates better with the pod lifecycle.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;volumes&quot;&gt;Volumes&lt;&#x2F;h4&gt;
&lt;p&gt;Containers are stateless by default — data disappears when they restart. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;volumes&#x2F;&quot;&gt;Volumes&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; attach storage to pods so data persists. K8s supports many volume types: local disks, NFS, cloud provider block storage (AWS EBS, Azure Disk), and more.&lt;&#x2F;p&gt;
&lt;p&gt;For truly persistent storage that outlives a pod, use a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;persistent-volumes&#x2F;&quot;&gt;PersistentVolume (PV)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; and &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;storage&#x2F;persistent-volumes&#x2F;#persistentvolumeclaims&quot;&gt;PersistentVolumeClaim (PVC)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;PersistentVolumeClaim&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-pvc&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ReadWriteOnce&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;10Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;---
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;db-pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres:16&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;var&#x2F;lib&#x2F;postgresql&#x2F;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-volume&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumes&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-volume&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;persistentVolumeClaim&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;claimName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data-pvc&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a single Linux machine, this is just mounting &lt;code&gt;&#x2F;mnt&#x2F;data&lt;&#x2F;code&gt; or an NFS share. K8s abstracts it so you can move workloads across nodes without reconfiguring mount points.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;deployments&quot;&gt;Deployments&lt;&#x2F;h4&gt;
&lt;p&gt;You rarely create pods directly. Instead, you use a &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;controllers&#x2F;deployment&#x2F;&quot;&gt;Deployment&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — a blueprint for stateless applications. It manages scaling, replica counts, rolling updates, and rollbacks.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app:v2&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8080
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Common operations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f deployment.yaml           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create or update
&lt;&#x2F;span&gt;&lt;span&gt;kubectl scale deployment webapp --replicas=5   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Scale to 5 pods
&lt;&#x2F;span&gt;&lt;span&gt;kubectl set image deployment&#x2F;webapp webapp=my-app:v3  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Rolling update
&lt;&#x2F;span&gt;&lt;span&gt;kubectl rollout undo deployment&#x2F;webapp     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Rollback to previous version
&lt;&#x2F;span&gt;&lt;span&gt;kubectl rollout status deployment&#x2F;webapp   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Watch rollout progress
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional server, this is &lt;code&gt;systemd&lt;&#x2F;code&gt; units + a rolling restart script managed by &lt;a href=&quot;https:&#x2F;&#x2F;docs.ansible.com&#x2F;&quot;&gt;Ansible&lt;&#x2F;a&gt;. K8s does it declaratively, with automatic health checks and rollback on failure.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;statefulsets&quot;&gt;StatefulSets&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;controllers&#x2F;statefulset&#x2F;&quot;&gt;StatefulSets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are for stateful applications like databases. Unlike Deployments, they provide:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Stable network identities&lt;&#x2F;strong&gt; (pod names like &lt;code&gt;db-0&lt;&#x2F;code&gt;, &lt;code&gt;db-1&lt;&#x2F;code&gt;, &lt;code&gt;db-2&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Ordered startup and shutdown&lt;&#x2F;strong&gt; (db-0 starts before db-1)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Persistent storage per pod&lt;&#x2F;strong&gt; (each pod gets its own PVC)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;StatefulSet&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;serviceName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;postgres:16&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeMounts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;mountPath&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;var&#x2F;lib&#x2F;postgresql&#x2F;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeClaimTemplates&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;accessModes&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ReadWriteOnce&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;storage&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;20Gi&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From my online research, many teams prefer to run databases &lt;em&gt;outside&lt;&#x2F;em&gt; K8s (RDS, managed PostgreSQL) and only use K8s for stateless workloads. I guess nobody wants to resolve an issue requiring expertise in Postgresql AND Kubernetes layers. &lt;em&gt;If you run your database inside k8s using a StatefulSet, please, let me know what are the good, the bad &amp;amp; the ugly.&lt;&#x2F;em&gt;..... { °_°} &lt;em&gt;Someone&#x27;s whispering in my ear that I should take a look at &lt;a href=&quot;https:&#x2F;&#x2F;cloudnative-pg.io&#x2F;&quot;&gt;CloudnativePG&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;daemonsets&quot;&gt;DaemonSets&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;workloads&#x2F;controllers&#x2F;daemonset&#x2F;&quot;&gt;DaemonSet&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; ensures a copy of a pod runs on every node (or selected nodes). Useful for cluster-wide services like: log collectors (Fluentd, Filebeat), monitoring agents (Prometheus Node Exporter, Datadog agent), network plugins (Calico, Cilium).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;DaemonSet&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;node-exporter&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prom&#x2F;node-exporter:latest&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;On a traditional infrastructure, this is like running &lt;code&gt;systemctl enable monitoring-agent&lt;&#x2F;code&gt; on every server. K8s does it automatically, including on new nodes as they join the cluster.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;k8s-configuration-tooling&quot;&gt;K8s configuration &amp;amp; tooling&lt;&#x2F;h3&gt;
&lt;p&gt;Now that we know the objects, how do we actually work with them?&lt;&#x2F;p&gt;
&lt;h4 id=&quot;kubectl-the-k8s-cli&quot;&gt;kubectl — the K8s CLI&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;kubectl&#x2F;&quot;&gt;kubectl&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the official command-line interface (CLI) to interact with and manage Kubernetes clusters. It&#x27;s the equivalent of &lt;code&gt;ssh&lt;&#x2F;code&gt; + &lt;code&gt;systemctl&lt;&#x2F;code&gt; + &lt;code&gt;podman&lt;&#x2F;code&gt; all rolled into one.&lt;&#x2F;p&gt;
&lt;p&gt;Common commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# View resources
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# List all pods in current namespace
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods -n kube-system           &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# List pods in kube-system namespace
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods -A                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# List pods across all namespaces
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get deployments,services,ingress  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Multiple resource types
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Describe details
&lt;&#x2F;span&gt;&lt;span&gt;kubectl describe pod my-pod               &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Full details, events, status
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs my-pod                       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# View logs
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs my-pod -f                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Follow logs (like tail -f)
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs my-pod --previous            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Logs from crashed container
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Apply manifests
&lt;&#x2F;span&gt;&lt;span&gt;kubectl apply -f deployment.yaml          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create&#x2F;update from file
&lt;&#x2F;span&gt;&lt;span&gt;kubectl apply -f .&#x2F;manifests&#x2F;             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Apply all YAML in directory
&lt;&#x2F;span&gt;&lt;span&gt;kubectl delete -f deployment.yaml         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Delete resources
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Direct manipulation (less common, prefer apply)
&lt;&#x2F;span&gt;&lt;span&gt;kubectl scale deployment webapp --replicas=5
&lt;&#x2F;span&gt;&lt;span&gt;kubectl set image deployment&#x2F;webapp webapp=my-app:v3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Debugging
&lt;&#x2F;span&gt;&lt;span&gt;kubectl exec -it my-pod&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;bin&#x2F;bash      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Shell into running pod
&lt;&#x2F;span&gt;&lt;span&gt;kubectl port-forward pod&#x2F;my-pod 8080:80   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Forward local port to pod
&lt;&#x2F;span&gt;&lt;span&gt;kubectl top nodes                         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Resource usage per node
&lt;&#x2F;span&gt;&lt;span&gt;kubectl top pods                          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Resource usage per pod
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h4 id=&quot;kubeconfig-cluster-credentials&quot;&gt;kubeconfig — cluster credentials&lt;&#x2F;h4&gt;
&lt;p&gt;Your cluster credentials live in the &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;configuration&#x2F;organize-cluster-access-kubeconfig&#x2F;&quot;&gt;kubeconfig file&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, usually at &lt;code&gt;~&#x2F;.kube&#x2F;config&lt;&#x2F;code&gt;. It defines:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clusters&lt;&#x2F;strong&gt;: API server endpoints and certificates&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Users&lt;&#x2F;strong&gt;: Authentication credentials (certs, tokens, OIDC)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Contexts&lt;&#x2F;strong&gt;: A pairing of cluster + user + namespace&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Config&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;clusters&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cluster&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;https:&#x2F;&#x2F;eks-cluster.eu-west-3.eks.amazonaws.com&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;contexts&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;context&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cluster&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prod-context&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;current-context&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;prod-context&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;users&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;admin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;user&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;token&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eyJhbGciOiJSUzI1NiIsImtpZCI6...&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the equivalent of &lt;code&gt;~&#x2F;.ssh&#x2F;config&lt;&#x2F;code&gt; for SSH connections — defining which clusters you can access and how to authenticate.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;manifest-files-infrastructure-as-code&quot;&gt;Manifest files — infrastructure as code&lt;&#x2F;h4&gt;
&lt;p&gt;All K8s resources are defined in &lt;strong&gt;manifest files&lt;&#x2F;strong&gt; — YAML or JSON documents. You store them in version control alongside your application code, making infrastructure changes auditable and reviewable.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;my-app&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;├── deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;├── service.yaml
&lt;&#x2F;span&gt;&lt;span&gt;├── ingress.yaml
&lt;&#x2F;span&gt;&lt;span&gt;├── configmap.yaml
&lt;&#x2F;span&gt;&lt;span&gt;└── secrets.yaml    # (encrypted in git using tools like git-crypt or sealed-secrets)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply them all at once:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f .&#x2F;k8s&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Managed K8s services (&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;what-is-eks.html&quot;&gt;EKS&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.cloud.google.com&#x2F;kubernetes-engine&#x2F;docs&quot;&gt;GKE&lt;&#x2F;a&gt;) also let you manage some resources through their web consoles or CLIs. If you ask me, I&#x27;ll tell you the best practice is &lt;strong&gt;GitOps&lt;&#x2F;strong&gt;: all configuration in &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&quot;&gt;Git&lt;&#x2F;a&gt;, applied via CI&#x2F;CD or tools like &lt;a href=&quot;https:&#x2F;&#x2F;argoproj.github.io&#x2F;cd&#x2F;&quot;&gt;ArgoCD&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;fluxcd.io&#x2F;&quot;&gt;Flux&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;helm-the-k8s-package-manager&quot;&gt;Helm — the K8s package manager&lt;&#x2F;h4&gt;
&lt;p&gt;Writing YAML manifests for every environment (dev, staging, prod) gets repetitive. You need to change image tags, replica counts, resource limits — but the structure stays the same. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;&quot;&gt;Helm&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; solves this by templating manifests. I need to master this part.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;strong&gt;Helm chart&lt;&#x2F;strong&gt; is a collection of templated YAML files plus a &lt;code&gt;values.yaml&lt;&#x2F;code&gt; file for customization:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# values.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicaCount&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;repository&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-app&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tag&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v2.0&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# templates&#x2F;deployment.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Chart.Name&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Values.replicaCount&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: {{ &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.Chart.Name&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;{{ .Values.image.repository }}:{{ .Values.image.tag }}&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Install a chart:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;helm install my-app .&#x2F;my-chart
&lt;&#x2F;span&gt;&lt;span&gt;helm install my-app .&#x2F;my-chart --set replicaCount=5   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Override values
&lt;&#x2F;span&gt;&lt;span&gt;helm upgrade my-app .&#x2F;my-chart                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Update
&lt;&#x2F;span&gt;&lt;span&gt;helm rollback my-app                                  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Rollback
&lt;&#x2F;span&gt;&lt;span&gt;helm uninstall my-app                                 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Remove everything
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Helm also has a massive &lt;a href=&quot;https:&#x2F;&#x2F;artifacthub.io&#x2F;&quot;&gt;public chart repository&lt;&#x2F;a&gt; — want to deploy PostgreSQL, Redis, Nginx Ingress Controller? There&#x27;s a chart for that.&lt;&#x2F;p&gt;
&lt;p&gt;Think of Helm as the &lt;code&gt;apt&lt;&#x2F;code&gt; or &lt;code&gt;dnf&lt;&#x2F;code&gt; of Kubernetes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;enter-eks&quot;&gt;Enter EKS&lt;&#x2F;h3&gt;
&lt;p&gt;Everything up to now has been generic Kubernetes — you could run it on bare metal, in your basement, or in any cloud. Now let&#x27;s talk about &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;eks&#x2F;&quot;&gt;Amazon EKS (Elastic Kubernetes Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;, AWS&#x27;s managed Kubernetes offering.&lt;&#x2F;p&gt;
&lt;p&gt;The main alternatives to EKS for managing K8s include options coming from the &lt;em&gt;&lt;a href=&quot;#&quot;&gt;Hyperscalers&lt;&#x2F;a&gt; (yeah, Hyperscalers, I like the name)&lt;&#x2F;em&gt;  such as Google Kubernetes Engine (GKE) (often considered to be more powerful), Azure Kubernetes Service (AKS) (ideal for the Micros10p ecosystem). For hybrid or on-premises management, Rancher and Red Hat OpenShift are robust alternatives. As &lt;em&gt;a proud&lt;&#x2F;em&gt; DigitalOcean user, I should mention &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;products&#x2F;kubernetes&quot;&gt;DigitalOcean Kubernetes (DOKS)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What EKS manages for you:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With self-managed Kubernetes, &lt;em&gt;you&lt;&#x2F;em&gt; install, patch, upgrade, and monitor the API server, etcd, scheduler, and controller manager. If etcd crashes at 3am, someone will be paged. With EKS, AWS runs the control plane for you:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;You Manage (Self-hosted K8s)&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS Manages (EKS)&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Control plane nodes (HA setup, patching, upgrades)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; Fully managed, multi-AZ by default&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;etcd backups and disaster recovery&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; Automated backups&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Control plane scaling&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; Auto-scales based on cluster size&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;API server availability&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; 99.95% SLA&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Security patches for control plane&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✓&lt;&#x2F;strong&gt; AWS handles it&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Worker nodes (EC2 instances)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✗&lt;&#x2F;strong&gt; You still manage these&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Application deployments&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✗&lt;&#x2F;strong&gt; Still your responsibility&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cluster monitoring and logging&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;✗&lt;&#x2F;strong&gt; You configure CloudWatch or Prometheus&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;EKS is a &lt;strong&gt;managed control plane&lt;&#x2F;strong&gt;, not a fully managed Kubernetes. You still provision and manage worker nodes (EC2 instances), configure networking &lt;a href=&quot;&#x2F;posts&#x2F;aws-1&#x2F;#network&quot;&gt;VPCs&lt;&#x2F;a&gt;, and set up &lt;a href=&quot;&#x2F;posts&#x2F;aws-2-3&#x2F;#iam-policies-how-aws-actually-decides&quot;&gt;IAM roles&lt;&#x2F;a&gt;, etc...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Creating an EKS cluster with eksctl:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eksctl.io&#x2F;&quot;&gt;eksctl&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is the official CLI for EKS. It abstracts away the complexity of creating, managing, and operating Amazon Elastic Kubernetes Service (Amazon EKS) clusters. Written in Go, eksctl provides a declarative syntax through YAML configurations and CLI commands to handle complex EKS cluster operations that would otherwise require multiple manual steps across different AWS services.&lt;&#x2F;p&gt;
&lt;p&gt;Simple cluster creation using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;getting-started-eksctl.html&quot;&gt;cli&lt;&#x2F;a&gt; (assuming you have the right sets or roles to do so):&lt;&#x2F;p&gt;
&lt;p&gt;In plain english:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Create a new Kubernetes cluster named my-cluster in the Paris region (eu-west-3). Add a group of worker nodes called standard-workers, each being a t3.medium machine. Start with 3 nodes running, but allow the cluster to scale down to a minimum of 1 node and up to a maximum of 4 nodes if needed. Make this node group managed by AWS (meaning AWS handles patching and updates for me).&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl create cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --name my-cluster \
&lt;&#x2F;span&gt;&lt;span&gt;  --region eu-west-3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodegroup-name standard-workers \
&lt;&#x2F;span&gt;&lt;span&gt;  --node-type t3.medium \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes 3 \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes-min 1 \
&lt;&#x2F;span&gt;&lt;span&gt;  --nodes-max 4 \
&lt;&#x2F;span&gt;&lt;span&gt;  --managed
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This command:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Creates a new VPC with 8 &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;eksctl&#x2F;vpc-configuration.html&quot;&gt;subnets&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Deploys the EKS control plane&lt;&#x2F;li&gt;
&lt;li&gt;Launches a managed node group (3 t3.medium EC2 instances)&lt;&#x2F;li&gt;
&lt;li&gt;Configures Auto Scaling (1-4 nodes)&lt;&#x2F;li&gt;
&lt;li&gt;Sets up kubectl access automatically&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;After 10-15 minutes, your cluster is ready:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl get nodes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME                                           STATUS   ROLES    AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ip-192-168-1-10.eu-west-3.compute.internal    Ready    &amp;lt;none&amp;gt;   2m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ip-192-168-2-20.eu-west-3.compute.internal    Ready    &amp;lt;none&amp;gt;   2m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ip-192-168-3-30.eu-west-3.compute.internal    Ready    &amp;lt;none&amp;gt;   2m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Advanced configuration&lt;&#x2F;strong&gt; (using a config file):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# cluster.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eksctl.io&#x2F;v1alpha5&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ClusterConfig&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production-cluster&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;region&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eu-west-3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;vpc&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;vpc-0123456789abcdef&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Use existing VPC from aws1
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;subnets&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;private&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;eu-west-3a&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;subnet-private-a&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;eu-west-3b&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;subnet-private-b&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;eu-west-3c&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;subnet-private-c&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;managedNodeGroups&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;general-purpose&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;instanceType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;t3.large&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;minSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;maxSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;desiredCapacity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;volumeSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;allow&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;publicKeyName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;my-keypair&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;workload&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;general&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;tags&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;team&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;platform&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;production&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;compute-optimized&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;instanceType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;c5.2xlarge&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;minSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;maxSize&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;desiredCapacity&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;workload&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;compute-intensive&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;taints&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;compute-intensive&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;effect&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;NoSchedule&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl create cluster -f cluster.yaml
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;EKS vs. self-managed Kubernetes:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Factor&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;EKS&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Self-Managed on EC2&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Setup time&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;15 minutes (eksctl)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Hours to days (kubeadm, Terraform, Ansible)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Control plane HA&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Built-in, multi-AZ&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You configure and maintain&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Upgrades&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;eksctl upgrade cluster&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manual, risky, time-consuming&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Cost&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;$73&#x2F;month + nodes&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Just node costs, but more ops time&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS integration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Native (IAM, VPC, ELB, EBS)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manual integration required&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Flexibility&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Limited control plane customization&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full control&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;When to use&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Most production workloads&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Cost-sensitive, control plane customization needed&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;For most teams, EKS is worth the €€€&#x2F;month. You&#x27;re paying AWS to handle the hard parts (HA, backups, upgrades, security patches) so you can focus on running applications, not babysitting control planes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;eks-networking-iam-integration&quot;&gt;EKS networking &amp;amp; IAM integration&lt;&#x2F;h3&gt;
&lt;p&gt;EKS isn&#x27;t just Kubernetes on AWS — it&#x27;s deeply integrated with AWS services. Three key integrations make EKS feel native to the AWS ecosystem.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-vpc-cni-pods-get-real-vpc-ips&quot;&gt;1. VPC CNI — Pods get real VPC IPs&lt;&#x2F;h4&gt;
&lt;p&gt;In standard Kubernetes, pods get IP addresses from an internal overlay network (like Calico or Flannel). Pods can talk to each other, but they&#x27;re isolated from the rest of your infrastructure. If you want a pod to access an RDS database in your VPC, you need to configure routing.&lt;&#x2F;p&gt;
&lt;p&gt;EKS uses the &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;pod-networking.html&quot;&gt;AWS VPC CNI plugin&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; instead. Every pod gets an IP address &lt;em&gt;directly from your VPC subnets&lt;&#x2F;em&gt; — the same subnets your EC2 instances and RDS databases live in. This means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pods are first-class VPC citizens&lt;&#x2F;strong&gt;: They appear in VPC Flow Logs, Security Groups apply to them, NACLs filter their traffic&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;No NAT for pod-to-pod traffic&lt;&#x2F;strong&gt;: Pods communicate directly via VPC routing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Simplified networking&lt;&#x2F;strong&gt;: Your pod at &lt;code&gt;10.0.1.50&lt;&#x2F;code&gt; can directly connect to your RDS instance at &lt;code&gt;10.0.2.100&lt;&#x2F;code&gt; — no special configuration needed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;The trade-off&lt;&#x2F;strong&gt;: Each worker node has a limited number of &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AWSEC2&#x2F;latest&#x2F;UserGuide&#x2F;using-eni.html&quot;&gt;Elastic Network Interfaces (ENIs)&lt;&#x2F;a&gt;, and each ENI has a limited number of secondary IP addresses. This caps how many pods you can run per node. A t3.medium can run ~17 pods, a c5.large can run ~29 pods. Plan your node sizing accordingly.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;                                   Traditional K8s:                   EKS with VPC CNI:
&lt;&#x2F;span&gt;&lt;span&gt;                                   +---------------------+            +---------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  VPC 10.0.0.0&#x2F;16    |            |  VPC 10.0.0.0&#x2F;16    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |                     |            |                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  EC2: 10.0.1.10     |            |  EC2: 10.0.1.10     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  RDS: 10.0.2.100    |            |  RDS: 10.0.2.100    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |                     |            |  Pod: 10.0.1.50     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  +---------------+  |            |  Pod: 10.0.1.51     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | Overlay net   |  |            |  Pod: 10.0.2.20     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | 192.168.0.0&#x2F;16|  |            |  (all in VPC range) |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  |               |  |            |                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | Pod: 192.168  |  |            |  Direct routing,    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  | Pod: 192.168  |  |            |  no overlay needed  |
&lt;&#x2F;span&gt;&lt;span&gt;                                   |  +---------------+  |            |                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                   +---------------------+            +---------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;2-irsa-pods-get-aws-permissions-without-secrets&quot;&gt;2. IRSA — Pods get AWS permissions without secrets&lt;&#x2F;h4&gt;
&lt;p&gt;Your pods need to access AWS services: read from S3, write to DynamoDB, publish to SQS. The wrong way to do this is hardcoding AWS credentials in a Secret (seriously, don&#x27;t). The right way is &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;iam-roles-for-service-accounts.html&quot;&gt;IAM Roles for Service Accounts (IRSA)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;IRSA uses &lt;a href=&quot;&#x2F;posts&#x2F;aws-2-3&#x2F;#openid-connect-oidc&quot;&gt;OpenID Connect&lt;&#x2F;a&gt; to let Kubernetes Service Accounts assume IAM roles. Here&#x27;s how it works:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;EKS cluster has an OIDC provider endpoint&lt;&#x2F;li&gt;
&lt;li&gt;You create an IAM role that trusts this OIDC provider&lt;&#x2F;li&gt;
&lt;li&gt;You annotate a Kubernetes Service Account with the IAM role ARN&lt;&#x2F;li&gt;
&lt;li&gt;Pods using that Service Account automatically get temporary AWS credentials&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Setup:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Step 1 — Enable OIDC provider for your cluster (one-time):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl utils associate-iam-oidc-provider \
&lt;&#x2F;span&gt;&lt;span&gt;  --cluster genomics-platform \
&lt;&#x2F;span&gt;&lt;span&gt;  --approve
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 2 — Create an IAM policy (what AWS permissions the pod needs):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Statement&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:PutObject&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      ],
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::genomics-sequencing-data&#x2F;*&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 3 — Create IAM role and Service Account together:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;eksctl create iamserviceaccount \
&lt;&#x2F;span&gt;&lt;span&gt;  --name genomics-pipeline \
&lt;&#x2F;span&gt;&lt;span&gt;  --namespace genomics \
&lt;&#x2F;span&gt;&lt;span&gt;  --cluster genomics-platform \
&lt;&#x2F;span&gt;&lt;span&gt;  --attach-policy-arn arn:aws:iam::123456789012:policy&#x2F;GenomicsS3ReadWritePolicy \
&lt;&#x2F;span&gt;&lt;span&gt;  --approve
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 4 — Use the Service Account in your pod:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Pod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;variant-analysis-job&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;serviceAccountName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-pipeline&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# This pod can read&#x2F;write genomics-sequencing-data
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;analyzer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-pipeline:v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;env&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;AWS_REGION&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;value&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eu-west-3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your application code just uses the standard AWS SDK — no credentials to configure:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;boto3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;s3 = boto3.client(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;s3&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Credentials auto-discovered from IRSA
&lt;&#x2F;span&gt;&lt;span&gt;s3.put_object(Bucket=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;genomics-sequencing-data&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, Key=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;results&#x2F;patient-42.vcf&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, Body=data)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Why this is brilliant&lt;&#x2F;strong&gt;: No secrets stored anywhere, credentials rotate automatically (just like EC2 instance roles from &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;Day 1&lt;&#x2F;a&gt;), and you get per-pod IAM policies — the genomics pipeline pod can access sequencing data while a separate clinical trials pod accesses a completely different bucket, all within the same cluster.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;irsa_eks_flow.svg&quot; alt=&quot;&quot; title=&quot;I am obliged to admit I&#x27;m impressed by this level of orchestration&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h4 id=&quot;3-aws-load-balancer-controller-ingress-creates-real-albs&quot;&gt;3. AWS Load Balancer Controller — Ingress creates real ALBs&lt;&#x2F;h4&gt;
&lt;p&gt;When you create a Kubernetes Ingress object in EKS, you want it to provision an actual &lt;a href=&quot;&#x2F;posts&#x2F;aws-1&#x2F;#load-balancing&quot;&gt;Application Load Balancer (ALB)&lt;&#x2F;a&gt;, not some pod running Nginx.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes-sigs.github.io&#x2F;aws-load-balancer-controller&#x2F;&quot;&gt;AWS Load Balancer Controller&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; does exactly this. Install it once in your cluster, and every time you create an Ingress, it provisions a real AWS ALB with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;TLS termination using ACM certificates&lt;&#x2F;li&gt;
&lt;li&gt;Path-based and host-based routing&lt;&#x2F;li&gt;
&lt;li&gt;WAF integration for DDoS protection&lt;&#x2F;li&gt;
&lt;li&gt;Full CloudWatch metrics and logging&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Installation&lt;&#x2F;strong&gt; (using Helm):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Add the EKS chart repo
&lt;&#x2F;span&gt;&lt;span&gt;helm repo add eks https:&#x2F;&#x2F;aws.github.io&#x2F;eks-charts
&lt;&#x2F;span&gt;&lt;span&gt;helm repo update
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Install the controller
&lt;&#x2F;span&gt;&lt;span&gt;helm install aws-load-balancer-controller eks&#x2F;aws-load-balancer-controller \
&lt;&#x2F;span&gt;&lt;span&gt;  -n kube-system \
&lt;&#x2F;span&gt;&lt;span&gt;  --set clusterName=genomics-platform \
&lt;&#x2F;span&gt;&lt;span&gt;  --set serviceAccount.create=false \
&lt;&#x2F;span&gt;&lt;span&gt;  --set serviceAccount.name=aws-load-balancer-controller
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Usage&lt;&#x2F;strong&gt; — create an Ingress with ALB annotations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;networking.k8s.io&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api-ingress&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;namespace&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;annotations&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alb.ingress.kubernetes.io&#x2F;scheme&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;internet-facing&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alb.ingress.kubernetes.io&#x2F;target-type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Routes to pod IPs directly via VPC CNI
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;alb.ingress.kubernetes.io&#x2F;certificate-arn&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;arn:aws:acm:eu-west-3:123456789012:certificate&#x2F;abc123&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ingressClassName&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;alb&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;rules&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;host&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;api.genomics-platform.example.com&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;http&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;pathType&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Prefix&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;backend&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;service&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;genomics-api-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;number&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8000
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it, and within 2-3 minutes, the controller creates an AWS ALB, configures target groups pointing directly to your pod IPs (thanks to VPC CNI), and updates Route 53 (if you&#x27;re using &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes-sigs&#x2F;external-dns&quot;&gt;ExternalDNS&lt;&#x2F;a&gt;). Your API is now publicly accessible at &lt;code&gt;https:&#x2F;&#x2F;api.genomics-platform.example.com&lt;&#x2F;code&gt;, with TLS handled by ACM and traffic distributed across pods.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;This is the real and only good reason to use EKS&lt;&#x2F;strong&gt;: Kubernetes-native workflows (&lt;code&gt;kubectl apply -f ingress.yaml&lt;&#x2F;code&gt;) that provision real AWS infrastructure (ALBs, target groups, security groups) automatically. You get the declarative model of Kubernetes with the managed services of AWS.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;eks_alb_ingress_flow.svg&quot; alt=&quot;&quot; title=&quot;I am obliged to admit I&#x27;m impressed by this level of orchestration&quot;&#x2F;&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;practical-example&quot;&gt;Practical example&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s deploy a simple web application to EKS end-to-end. We use nginx here for clarity — in &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-6&#x2F;&quot;&gt;Day 6&lt;&#x2F;a&gt; we&#x27;ll replace it with the actual genomics Django API, packaged as a Helm chart.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;EKS cluster running (created with &lt;code&gt;eksctl&lt;&#x2F;code&gt; as shown above)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;kubectl&lt;&#x2F;code&gt; configured to talk to your cluster&lt;&#x2F;li&gt;
&lt;li&gt;AWS Load Balancer Controller installed (optional, for the Ingress part)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Step 1 — Create the application Deployment:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-deployment.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;apps&#x2F;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Deployment&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;matchLabels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;template&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;nginx&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;image&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;nginx:1.25&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;resources&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;requests&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;64Mi&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;250m&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;limits&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;memory&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;128Mi&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;cpu&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;500m&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f webapp-deployment.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment.apps&#x2F;webapp created
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME                      READY   STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-2xqwp   1&#x2F;1     Running   0          30s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-8h4kt   1&#x2F;1     Running   0          30s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-n9p5r   1&#x2F;1     Running   0          30s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Step 2 — Expose the Deployment with a Service:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-service.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;v1&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;Service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp-service&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;LoadBalancer&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;selector&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;app&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;webapp&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;protocol&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;TCP&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;targetPort&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Apply it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl apply -f webapp-service.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# service&#x2F;webapp-service created
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get service webapp-service
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME             TYPE           CLUSTER-IP      EXTERNAL-IP                             PORT(S)        AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-service   LoadBalancer   10.100.200.50   a3f2...eu-west-3.elb.amazonaws.com      80:32415&#x2F;TCP   2m
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;EKS automatically provisions an AWS Elastic Load Balancer. After 2-3 minutes, the &lt;code&gt;EXTERNAL-IP&lt;&#x2F;code&gt; appears — that&#x27;s your app&#x27;s public endpoint.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 3 — Scale the application:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl scale deployment webapp --replicas=5
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment.apps&#x2F;webapp scaled
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl get pods
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# NAME                      READY   STATUS    RESTARTS   AGE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-2xqwp   1&#x2F;1     Running   0          5m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-8h4kt   1&#x2F;1     Running   0          5m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-n9p5r   1&#x2F;1     Running   0          5m
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-q8w3j   1&#x2F;1     Running   0          10s
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# webapp-7d8b9c5f6d-x7k2m   1&#x2F;1     Running   0          10s
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The load balancer automatically distributes traffic across all 5 pods.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 4 — Update the application (rolling update):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl set image deployment&#x2F;webapp nginx=nginx:1.26
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment.apps&#x2F;webapp image updated
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl rollout status deployment&#x2F;webapp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Waiting for deployment &amp;quot;webapp&amp;quot; rollout to finish: 2 out of 5 new replicas have been updated...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# deployment &amp;quot;webapp&amp;quot; successfully rolled out
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;K8s replaces pods one at a time, ensuring zero downtime.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Step 5 — Check logs:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl logs -l app=webapp --tail=20
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Shows logs from all webapp pods
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;kubectl logs webapp-7d8b9c5f6d-2xqwp
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Shows logs from a specific pod
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Step 6 — Clean up:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;kubectl delete -f webapp-deployment.yaml
&lt;&#x2F;span&gt;&lt;span&gt;kubectl delete -f webapp-service.yaml
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Or delete everything at once:
&lt;&#x2F;span&gt;&lt;span&gt;kubectl delete deployment,service -l app=webapp
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;What just happened:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You described your desired state in YAML (3 replicas of nginx)&lt;&#x2F;li&gt;
&lt;li&gt;K8s scheduled pods across worker nodes&lt;&#x2F;li&gt;
&lt;li&gt;EKS provisioned an AWS ELB and configured it to route traffic to your pods&lt;&#x2F;li&gt;
&lt;li&gt;You scaled, updated, and monitored the app with simple &lt;code&gt;kubectl&lt;&#x2F;code&gt; commands&lt;&#x2F;li&gt;
&lt;li&gt;All of this ran on infrastructure defined in &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;Day 1&lt;&#x2F;a&gt; (VPC, subnets, security groups, IAM roles)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the declarative model in action: you say &lt;em&gt;what&lt;&#x2F;em&gt; you want, K8s figures out &lt;em&gt;how&lt;&#x2F;em&gt; to make it happen.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;eks-vs-alternatives&quot;&gt;EKS vs. alternatives&lt;&#x2F;h3&gt;
&lt;p&gt;You have containerized applications and want to run them on AWS. What should you choose? Here&#x27;s the honest comparison.&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Factor&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;EKS&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;ECS + Fargate&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Self-Managed K8s on EC2&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Complexity&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Medium&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Low&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;High&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Setup time&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;15 minutes (eksctl)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;5 minutes (CloudFormation)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Hours to days (kubeadm, Terraform)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Learning curve&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Steep (K8s expertise required)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Gentle (AWS-native, simpler concepts)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Very steep (K8s + infrastructure management)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Orchestration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full Kubernetes (industry standard)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS-specific, simpler model&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full Kubernetes, full control&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Portability&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;High (standard K8s, runs anywhere)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Low (AWS-only, vendor lock-in)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;High (K8s is portable)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Infrastructure management&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You manage worker nodes (or use Fargate)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Serverless (no nodes to manage)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You manage everything&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Ecosystem&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Massive (Helm charts, operators, CNCF projects)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS services only&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Massive (K8s ecosystem)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Pricing&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;$73&#x2F;month control plane + nodes&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Pay per task (no idle costs)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Just EC2 costs + your time&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Scaling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Horizontal Pod Autoscaler + Cluster Autoscaler&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Auto-scales per task&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You configure everything&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Networking&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;VPC CNI, complex but powerful&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS native, simple&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You choose (Calico, Flannel, etc.)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;IAM integration&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;IRSA (excellent)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Native task roles (excellent)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manual (complex)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Monitoring&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch + Prometheus + third-party&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;CloudWatch native&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;You set up everything&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Best for&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Complex microservices, multi-cloud strategy, K8s expertise on team&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Simple containerized apps, AWS-first teams, want low ops overhead&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full control needed, K8s expertise, cost-sensitive&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Avoid if&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Simple 2-3 container setup, no K8s experience&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Need K8s portability, complex networking requirements&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Small team, want to focus on apps not infrastructure&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;hr &#x2F;&gt;
&lt;h2 id=&quot;my-honest-recommendation-for-a-biomedical-research-center&quot;&gt;My honest recommendation for a biomedical research center&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t like giving recommendations. There are so many factors to consider, so many criteria to take into account. I&#x27;ve always believed you should start simple and, if necessary, move on to more complex options.&lt;&#x2F;p&gt;
&lt;p&gt;So, for most teams, &lt;strong&gt;start with ECS + Fargate&lt;&#x2F;strong&gt;. It&#x27;s simpler, cheaper for small workloads, and gets you running quickly. As complexity grows (more services, more teams, multi-cloud needs), &lt;em&gt;then&lt;&#x2F;em&gt; evaluate EKS. If you already know Kubernetes or need portability: &lt;strong&gt;use EKS&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For example. If you&#x27;re running batch analysis jobs (genomic processing, statistical models): &lt;strong&gt;ECS + Fargate&lt;&#x2F;strong&gt; is perfect. Define the job, let AWS run it, pay only for execution time. If you&#x27;re building a complex platform, handling lots of requests, with web apps, APIs, databases, data pipelines, and ML inference: &lt;strong&gt;EKS&lt;&#x2F;strong&gt; gives you the flexibility and ecosystem to compose these pieces together.&lt;&#x2F;p&gt;
&lt;p&gt;Self-managed K8s only makes sense if you have specific requirements that EKS can&#x27;t meet, or if you have a dedicated platform team that lives and breathes Kubernetes.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;Kubernetes emerged from Google&#x27;s need to manage &lt;strong&gt;&lt;em&gt;thousands of containers across massive infrastructure&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. It solved real problems at that &lt;strong&gt;&lt;em&gt;scale&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. Today, it&#x27;s becoming the &lt;strong&gt;&lt;em&gt;industry standard&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; because the problems it solves, orchestration, self-healing, automatic scaling, service discovery, are increasingly common. But that doesn&#x27;t mean every team needs it right now. Come on man, you&#x27;re not Google.&lt;&#x2F;p&gt;
&lt;p&gt;The real value is: if you understand Kubernetes, you understand container orchestration itself. That knowledge transfers everywhere: AWS EKS, Google GKE, Azure AKS, your own data center. The mental model is identical across platforms. That&#x27;s why Kubernetes literacy is worth investing in, even if you don&#x27;t deploy it immediately. Learning it now means you&#x27;ll be prepared when that moment arrives.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;solved_problem.jpg&quot; alt=&quot;You&#x27;re welcome&quot; title=&quot;You&#x27;re welcome&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;This article is awfully long &lt;em&gt;wtf&lt;&#x2F;em&gt;! I really hope you did learn something. The topic is amazingly huge and cannot be covered in one tiny small simple article. Here are resources to continue your Kubernetes and EKS journey:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Blog posts:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.boot.dev&#x2F;blog&#x2F;education&#x2F;maybe-you-do-need-kubernetes&#x2F;&quot;&gt;Maybe you do need Kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;samof76.space&#x2F;kubernetes-in-anger.html&quot;&gt;Kubernetes in Anger&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Official documentation:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;&quot;&gt;Kubernetes documentation - concepts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;&quot;&gt;Amazon EKS user guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.eksworkshop.com&#x2F;&quot;&gt;Amazon EKS workshop&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.github.io&#x2F;aws-eks-best-practices&#x2F;&quot;&gt;EKS best practices guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Video tutorials:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=H5sPGruv2yc&quot;&gt;You don&#x27;t need Kubernetes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=s_o8dwzRlu4&quot;&gt;Kubernetes crash course for absolute beginners&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=X48VuDVv0do&quot;&gt;Kubernetes tutorial for beginners&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=QThadS3Soig&quot;&gt;Getting started with Amazon EKS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=l_iZfujb9rc&quot;&gt;Joe Beda on co-creating Kubernetes at Google&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Interactive learning:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;training.play-with-kubernetes.com&#x2F;kubernetes-workshop&#x2F;&quot;&gt;Free browser-based K8s playground&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;killercoda.com&#x2F;kubernetes&quot;&gt;KillerCoda interactive K8s tutorials&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Tools to practice with:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;minikube.sigs.k8s.io&#x2F;&quot;&gt;Minikube&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kind.sigs.k8s.io&#x2F;&quot;&gt;Kind (Kubernetes in Docker)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;canonical.com&#x2F;microk8s&quot;&gt;MicroK8s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;k9scli.io&#x2F;&quot;&gt;k9s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;k3s.io&#x2F;&quot;&gt;k3s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.k0sproject.io&#x2F;stable&#x2F;&quot;&gt;k0s&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Numeronyms:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;d14n, a11y, l10n, o11y, g11n, m17n, p13n, v12n, c14n, ...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 2-3)</title>
        <published>2026-02-04T00:00:00+00:00</published>
        <updated>2026-02-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-2-3/"/>
        <id>https://nskm.xyz/posts/aws-2-3/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-2-3/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;devoops.png&quot; alt=&quot;Dev oops&quot; title=&quot;Dev oops&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I don&#x27;t agree with this, but my employer says I don&#x27;t have the right to share the source code I&#x27;ve written in the course of my work. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;shorts&#x2F;FEYlE8pHICk&quot;&gt;I don&#x27;t ever want a problem&lt;&#x2F;a&gt;. So, I&#x27;ll try to say as much as I can without divulging any specific information.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, but if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;Welcome to the second episode of this series. Already three days in the training. The pace is fast, there are many concepts to master, fatigue and exhaustion are setting in. Today, we&#x27;ll talk about the security and audit systems that determine
whether your cloud infrastructure can be trusted with sensitive data. The previous episode can be found &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#security-and-audit&quot;&gt;Security and Audit&lt;&#x2F;a&gt; - How AWS enforces permissions and tracks access
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#iam-policies-how-aws-actually-decides&quot;&gt;IAM Policies&lt;&#x2F;a&gt; - Policy evaluation logic and types&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#openid-connect-oidc&quot;&gt;OpenID Connect (OIDC)&lt;&#x2F;a&gt; - Federated identity and cross-organizational access&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#kms-and-acm-encryption-and-certificates&quot;&gt;KMS and ACM&lt;&#x2F;a&gt; - Encryption and certificate management&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-2-3&#x2F;#cloudtrail-who-did-what-and-when&quot;&gt;CloudTrail&lt;&#x2F;a&gt; - Audit logging and compliance&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;security-and-audit&quot;&gt;Security and Audit&lt;&#x2F;h2&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#identity-and-access-management&quot;&gt;previous article&lt;&#x2F;a&gt;, we introduced IAM: users, groups, roles, policies, and the principle of least privilege. That was the &quot;who can do what&quot; overview. Today we go deeper into the &lt;em&gt;how&lt;&#x2F;em&gt; — how policies are actually evaluated, how to avoid hardcoding credentials entirely (even across organizations), how to encrypt things, and how to know &lt;em&gt;exactly&lt;&#x2F;em&gt; what happened in your account at 3am last Tuesday.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;iam-policies-how-aws-actually-decides&quot;&gt;IAM Policies: how AWS actually decides&lt;&#x2F;h3&gt;
&lt;p&gt;You write a policy, attach it to a user or role, and hope for the best. But what happens when &lt;em&gt;multiple&lt;&#x2F;em&gt; policies apply? When one says Allow and another says Deny? AWS follows a &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_evaluation-logic.html&quot;&gt;specific evaluation logic&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Default deny&lt;&#x2F;strong&gt; — everything is denied unless explicitly allowed&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Explicit deny wins&lt;&#x2F;strong&gt; — if &lt;em&gt;any&lt;&#x2F;em&gt; policy says Deny, it&#x27;s denied, period&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Allow must be present&lt;&#x2F;strong&gt; — the action must be explicitly allowed by at least one policy&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Boundaries are checked&lt;&#x2F;strong&gt; — SCPs, permission boundaries, and session policies can further restrict&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Think of it like this: you need a &quot;yes&quot; from every gatekeeper, and a single &quot;no&quot; from anyone overrides everything.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Types of policies:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Policy Type&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Attached To&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Purpose&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html#policies_id-based&quot;&gt;Identity-based&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Users, Groups, Roles&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Grant permissions to an identity&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html#policies_resource-based&quot;&gt;Resource-based&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;S3 buckets, SQS queues, etc.&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Control who can access &lt;em&gt;this&lt;&#x2F;em&gt; resource&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies_boundaries.html&quot;&gt;Permission boundaries&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Users, Roles&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Set the &lt;em&gt;maximum&lt;&#x2F;em&gt; permissions an identity can have&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;organizations&#x2F;latest&#x2F;userguide&#x2F;orgs_manage_policies_scps.html&quot;&gt;Service Control Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Organization accounts&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Guardrails across entire accounts&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html#policies_session&quot;&gt;Session policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Temporary sessions&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Limit permissions for a specific session&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Permission boundaries&lt;&#x2F;strong&gt; deserve special attention. They don&#x27;t &lt;em&gt;grant&lt;&#x2F;em&gt; permissions — they set a ceiling on what an identity can do. Think of it as a safety net: an identity policy can allow an action, but if the permission boundary doesn&#x27;t include it, the action is blocked.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Permission boundary allows: &lt;code&gt;s3:*&lt;&#x2F;code&gt; and &lt;code&gt;ec2:DescribeInstances&lt;&#x2F;code&gt; (read-only)&lt;&#x2F;li&gt;
&lt;li&gt;Identity policy allows: &lt;code&gt;s3:*&lt;&#x2F;code&gt;, &lt;code&gt;ec2:*&lt;&#x2F;code&gt; (full EC2 access)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Effective result&lt;&#x2F;strong&gt;: The user can do all S3 actions and only read EC2, not modify it&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A permission boundary is a maximum limit. The effective permissions are the intersection (overlap) of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What the permission boundary allows&lt;&#x2F;li&gt;
&lt;li&gt;What the identity policy allows&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is useful when you want to let developers create their own IAM roles. You set a permission boundary that says &quot;you can have S3 and read-only EC2,&quot; and even if a developer accidentally adds a policy that grants &lt;code&gt;ec2:TerminateInstances&lt;&#x2F;code&gt;, that action is blocked by the boundary. The boundary prevents privilege escalation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A more realistic policy example:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The day 1 article showed a simple S3 read policy. Here&#x27;s what a real-world policy looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Statement&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ReadSharedDatasets&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:ListBucket&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&#x2F;shared&#x2F;*&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      ],
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Condition&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;StringEquals&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;aws:RequestedRegion&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;eu-west-3&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;UploadOwnResults&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:PutObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&#x2F;results&#x2F;${aws:username}&#x2F;*&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;DenyUnencryptedUploads&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Deny&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:PutObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-datasets&#x2F;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Condition&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;StringNotEquals&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:x-amz-server-side-encryption&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;aws:kms&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;      }
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You read it like this (&lt;em&gt;Sid -&amp;gt; Effet -&amp;gt; Action -&amp;gt; Resource -&amp;gt; Condition&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;ReadSharedDatasets: Allow s3:GetObject, s3:ListBucket on research-datasets when in eu-west-3&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;UploadOwnResults: Allow s3:PutObject on own results datasets owned by current user with username&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;DenyUnencryptedUploads: Deny s3:PutObject on research-datasets when there is no KMS encryption&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You understand it like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;ReadSharedDatasets: Allow reading from the shared research-datasets bucket, but only from eu-west-3&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;UploadOwnResults: Allow uploading to your personal results folder&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;DenyUnencryptedUploads: Deny uploading unencrypted files to the research-datasets bucket&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
Now tet&#x27;s imagine the following interaction:
&lt;p&gt;A researcher tries to upload an unencrypted file to their results folder:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Policy 2 says: &quot;You can upload files&quot; ✅&lt;&#x2F;li&gt;
&lt;li&gt;Policy 3 says: &quot;But NOT unencrypted files&quot; ❌&lt;&#x2F;li&gt;
&lt;li&gt;Result: Upload is DENIED — because Explicit deny wins (rule #2 from the evaluation logic: Explicit deny wins — if any policy says Deny, it&#x27;s denied, period)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
Notice three things:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_elements_condition.html&quot;&gt;Conditions&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; restrict &lt;em&gt;where&lt;&#x2F;em&gt; actions can happen (only &lt;code&gt;eu-west-3&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;reference_policies_variables.html&quot;&gt;Policy variables&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; like &lt;code&gt;${aws:username}&lt;&#x2F;code&gt; scope access per current user dynamically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Explicit Deny blocks everything&lt;&#x2F;strong&gt;  A researcher can&#x27;t bypass this, even if they accidentally add a permissive policy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Why do we mention this?&lt;&#x2F;p&gt;
&lt;p&gt;To reinforce the critical IAM evaluation rule: &lt;strong&gt;&quot;A single Deny overrides all Allows&quot;&lt;&#x2F;strong&gt;. This is one of the most important security
principles in AWS.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;strong&gt;Creating an IAM Role (practical example):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s say you have an EC2 instance running a Python script that needs to read from S3 and write to DynamoDB. Here&#x27;s how you&#x27;d do it properly with the &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;cli&#x2F;latest&#x2F;userguide&#x2F;cli-chap-welcome.html&quot;&gt;AWS CLI&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;Step 1 — Create the trust policy (who can assume this role):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Statement&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Principal&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Service&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ec2.amazonaws.com&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;},
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sts:AssumeRole&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Reading this in plain English:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Allow the EC2 service to assume this role (ResearchAnalysisRole)&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Breaking it down:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Principal&lt;&#x2F;strong&gt; (&lt;code&gt;ec2.amazonaws.com&lt;&#x2F;code&gt;) = WHO can do this → the EC2 service&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Action&lt;&#x2F;strong&gt; (&lt;code&gt;sts:AssumeRole&lt;&#x2F;code&gt;) = WHAT they can do → take on this role&#x27;s permissions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Effect&lt;&#x2F;strong&gt; (&lt;code&gt;Allow&lt;&#x2F;code&gt;) = permission granted&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Step 2 — Create the role and attach the trust policy:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws iam create-role \
&lt;&#x2F;span&gt;&lt;span&gt;  --role-name ResearchAnalysisRole \
&lt;&#x2F;span&gt;&lt;span&gt;  --assume-role-policy-document file:&#x2F;&#x2F;trust-policy.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Key distinction:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Trust policy&lt;&#x2F;strong&gt; (Step 1): &quot;Who can assume this role?&quot; → Answer: The EC2 service&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Permissions policy&lt;&#x2F;strong&gt; (Step 3): &quot;What can this role do?&quot; → Answer: Read S3, write to DynamoDB&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Step 3 — Create and attach the permissions policy:&lt;&#x2F;p&gt;
&lt;p&gt;First, create the &lt;code&gt;permissions-policy.json&lt;&#x2F;code&gt; file with the permissions the role needs:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Statement&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ReadFromS3&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:ListBucket&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-data&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::research-data&#x2F;*&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      ]
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Sid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;WriteToDynamoDB&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dynamodb:PutItem&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dynamodb:UpdateItem&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:dynamodb:eu-west-3:123456789012:table&#x2F;analysis-results&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now attach this permissions policy to the role:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws iam put-role-policy \
&lt;&#x2F;span&gt;&lt;span&gt;  --role-name ResearchAnalysisRole \
&lt;&#x2F;span&gt;&lt;span&gt;  --policy-name ResearchAnalysisPermissions \
&lt;&#x2F;span&gt;&lt;span&gt;  --policy-document file:&#x2F;&#x2F;permissions-policy.json
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Step 4 — Create an instance profile and attach the role:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;aws iam create-instance-profile \
&lt;&#x2F;span&gt;&lt;span&gt;  --instance-profile-name ResearchAnalysisProfile
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;aws iam add-role-to-instance-profile \
&lt;&#x2F;span&gt;&lt;span&gt;  --instance-profile-name ResearchAnalysisProfile \
&lt;&#x2F;span&gt;&lt;span&gt;  --role-name ResearchAnalysisRole
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now any EC2 instance launched with this profile gets temporary credentials based on the ResearchAnalysisRole&#x27;s permissions. automatically. No access keys to manage, no secrets to rotate, no &lt;code&gt;.env&lt;&#x2F;code&gt; file to accidentally commit inside the Git repository. Your Python script just calls &lt;code&gt;boto3.client(&#x27;s3&#x27;)&lt;&#x2F;code&gt; and it works, the SDK picks up the credentials from the instance metadata.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The complete picture:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | IAM Role: ResearchAnalysisRole                             |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | Trust Policy:                                              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |   &amp;quot;Allow EC2 service to assume this role&amp;quot;                  |
&lt;&#x2F;span&gt;&lt;span&gt;                          |                                                            |
&lt;&#x2F;span&gt;&lt;span&gt;                          | Permission Policy:                                         |
&lt;&#x2F;span&gt;&lt;span&gt;                          |   - Allow S3: GetObject, ListBucket                        |
&lt;&#x2F;span&gt;&lt;span&gt;                          |   - Allow DynamoDB: PutItem, UpdateItem                    |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                                 | (attached to)
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | Instance Profile: ResearchAnalysisProfile                  |
&lt;&#x2F;span&gt;&lt;span&gt;                          | (container that holds the role)                            |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                                 | (attached to)
&lt;&#x2F;span&gt;&lt;span&gt;                                                 |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          | EC2 Instance                                               |
&lt;&#x2F;span&gt;&lt;span&gt;                          +------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                          |                                                            |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  +--------------------------------------------------+      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | Python Script (running on instance)              |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  |                                                  |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | import boto3                                     |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | s3 = boto3.client(&amp;#39;s3&amp;#39;)                          |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | db = boto3.client(&amp;#39;dynamodb&amp;#39;)                    |      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  +--------------------------------------+-----------+      |
&lt;&#x2F;span&gt;&lt;span&gt;                          |                                         |                  |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  +--------------------------------------+---+              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | Instance Metadata Service            |   |              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  | (provides temporary creds) ----------+   |              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  |                                      |   |              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |  +--------------------------------------+---+              |
&lt;&#x2F;span&gt;&lt;span&gt;                          |                                         |                  |
&lt;&#x2F;span&gt;&lt;span&gt;                          +-----------------------------------------+------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                                    |
&lt;&#x2F;span&gt;&lt;span&gt;                                                                    |
&lt;&#x2F;span&gt;&lt;span&gt;                                   +------------+-------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                   |            |
&lt;&#x2F;span&gt;&lt;span&gt;                               +---+---+   +----+--------+
&lt;&#x2F;span&gt;&lt;span&gt;                               |  S3   |   |  DynamoDB   |
&lt;&#x2F;span&gt;&lt;span&gt;                               |(read) |   |  (write)    |
&lt;&#x2F;span&gt;&lt;span&gt;                               +-------+   +-------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;assume-role.webp&quot; alt=&quot;Assume role&quot; title=&quot;Assume role&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;openid-connect-oidc&quot;&gt;OpenID Connect (OIDC)&lt;&#x2F;h3&gt;
&lt;p&gt;So far, IAM handles identities &lt;em&gt;inside&lt;&#x2F;em&gt; AWS. But what about the outside world? What if your GitHub Actions pipeline needs to deploy to AWS? What if your researchers log in through your organization&#x27;s Active Directory?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;openid.net&#x2F;developers&#x2F;how-connect-works&#x2F;&quot;&gt;OpenID Connect (OIDC)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is an identity layer built on top of &lt;a href=&quot;https:&#x2F;&#x2F;oauth.net&#x2F;2&#x2F;&quot;&gt;OAuth 2.0&lt;&#x2F;a&gt;. It allows external identity providers to authenticate users and services, which can then assume AWS roles. No long-lived credentials stored anywhere.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;How it works in practice:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;                                            Step 1: Authenticate with Identity Provider
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | GitHub &#x2F; Google &#x2F; Azure AD|
&lt;&#x2F;span&gt;&lt;span&gt;                                            | (Identity Provider)       |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       ^
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | &amp;quot;Login with GitHub&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                    +--+--+
&lt;&#x2F;span&gt;&lt;span&gt;                                                    |User |
&lt;&#x2F;span&gt;&lt;span&gt;                                                    +--+--+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | Step 2: Receive JWT Token
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | (cryptographic proof of identity)
&lt;&#x2F;span&gt;&lt;span&gt;                                                       v
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | JWT Token                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | Contains:                 |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Repository name         |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Branch                  |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Commit SHA              |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Timestamp               |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | Step 3: Send token to AWS STS
&lt;&#x2F;span&gt;&lt;span&gt;                                                       v
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | AWS STS                   |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | (Security Token Service)  |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | Step 4: STS checks trust policy
&lt;&#x2F;span&gt;&lt;span&gt;                                                       | &amp;quot;Is this token from the repo
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |  I trust? YES -&amp;gt; OK&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;                                                       v
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;                                            | Temporary AWS Credentials |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Access Key ID           |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Secret Access Key       |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Session Token           |
&lt;&#x2F;span&gt;&lt;span&gt;                                            | - Expires in 1 hour       |
&lt;&#x2F;span&gt;&lt;span&gt;                                            +---------------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;The flow:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;User&#x2F;Service authenticates&lt;&#x2F;strong&gt; with an external identity provider (GitHub, Google, Azure AD, corporate LDAP)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Provider issues a JSON Web Token&lt;&#x2F;strong&gt;, a cryptographic &lt;a href=&quot;https:&#x2F;&#x2F;jwt.io&#x2F;introduction&quot;&gt;proof&lt;&#x2F;a&gt; containing metadata (repository, branch, user identity, etc.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Token is sent to AWS STS (Security Token Service)&lt;&#x2F;strong&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;STS&#x2F;latest&#x2F;APIReference&#x2F;welcome.html&quot;&gt;STS&lt;&#x2F;a&gt; examines it&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;STS checks the trust policy&lt;&#x2F;strong&gt; — &quot;Is this token from a trusted source?&quot; If yes, temporary credentials are issued&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Credentials expire automatically&lt;&#x2F;strong&gt; — typically 1 hour, so no manual cleanup needed&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Real-world example — GitHub Actions deploying to AWS:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Instead of storing AWS access keys as GitHub secrets, you configure an &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_roles_providers_create_oidc.html&quot;&gt;OIDC identity provider in AWS&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;yaml&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-yaml &quot;&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# .github&#x2F;workflows&#x2F;deploy.yml
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;jobs&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;deploy&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;permissions&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;id-token&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Required for OIDC
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;contents&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;steps&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;uses&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aws-actions&#x2F;configure-aws-credentials@v4&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;role-to-assume&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;arn:aws:iam::123456789012:role&#x2F;GitHubDeployRole&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;          &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;aws-region&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;eu-west-3&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;      - &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;aws s3 sync .&#x2F;build s3:&#x2F;&#x2F;my-app-bucket&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Security: What if someone forks your repo?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If someone forks your repo, they can&#x27;t assume your role. Here&#x27;s why:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Github OIDC token includes metadata&lt;&#x2F;strong&gt;: repository name, branch, commit SHA, etc.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Your trust policy is specific&lt;&#x2F;strong&gt;: it explicitly checks: &quot;Only allow tokens from &lt;code&gt;organization&#x2F;original-repo-name&lt;&#x2F;code&gt;&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The fork has different metadata&lt;&#x2F;strong&gt;: when the fork&#x27;s workflow runs, the token says &lt;code&gt;fork-owner&#x2F;forked-repo&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;The policy rejects it&lt;&#x2F;strong&gt;: AWS compares: &lt;code&gt;fork-owner&#x2F;forked-repo&lt;&#x2F;code&gt; ≠ &lt;code&gt;organization&#x2F;original-repo-name&lt;&#x2F;code&gt; → Denied&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Result: No credentials, no access&lt;&#x2F;strong&gt; — Even if the attacker has your exact workflow file, the OIDC token won&#x27;t match the trust policy&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Why this matters for a biomedical research center:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Researchers often come from partner institutions, universities, or international organizations. Instead of creating and managing IAM users for each collaborator, you can federate identity through their home institution&#x27;s identity provider. They log in with their university credentials, get temporary AWS access scoped to exactly what they need, and when their collaboration ends, you revoke nothing — their access simply stops when the trust relationship is removed.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 210px&quot; src=&quot;&#x2F;images&#x2F;security-check.webp&quot; alt=&quot;Security check&quot; title=&quot;Security check&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;kms-and-acm-encryption-and-certificates&quot;&gt;KMS and ACM: encryption and certificates&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;overview.html&quot;&gt;AWS KMS (Key Management Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Manages encryption keys for your data. If you&#x27;re storing patient data, genomic sequences, or any sensitive research data, encryption isn&#x27;t optional — it&#x27;s a compliance requirement (HIPAA, GDPR, etc.).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Key concepts:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Concept&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;What it does&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;concepts.html#kms_keys&quot;&gt;Customer Master Key (CMK)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;The top-level key. Never leaves AWS. You control who can use it. IAM policies define access.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;concepts.html#data-keys&quot;&gt;Data key&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Generated by KMS, used to actually encrypt your data. You use it locally, then discard it.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;key-policies.html&quot;&gt;Key policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;IAM-like policies controlling who can use or manage the key. Auditable via CloudTrail.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;rotate-keys.html&quot;&gt;Automatic rotation&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AWS rotates key material annually. Old data remains decryptable. Compliance requirement.&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;How envelope encryption works:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;Step 1: Request data key from KMS
&lt;&#x2F;span&gt;&lt;span&gt;Application --&amp;gt; KMS: &amp;quot;Give me a data key&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 2: KMS returns both plaintext and encrypted key
&lt;&#x2F;span&gt;&lt;span&gt;KMS --&amp;gt; Application:
&lt;&#x2F;span&gt;&lt;span&gt;  - Plaintext key (256-bit AES key)
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypted key (encrypted with CMK)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 3: Encrypt data locally with plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;Application:
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypts patient data with plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;  - Discards plaintext key from memory
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 4: Store encrypted data + encrypted key
&lt;&#x2F;span&gt;&lt;span&gt;Database stores:
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypted patient data (gigabytes)
&lt;&#x2F;span&gt;&lt;span&gt;  - Encrypted data key (tiny, ~200 bytes)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Step 5: To decrypt later
&lt;&#x2F;span&gt;&lt;span&gt;Application: &amp;quot;KMS, decrypt this key for me&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;KMS: Decrypts it, returns plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;Application: Uses plaintext key to decrypt patient data
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Why this design?&lt;&#x2F;strong&gt; Sending gigabytes of sensitive data to KMS would be slow, expensive, and create a bottleneck. Instead, KMS only handles small cryptographic keys, and the heavy encryption happens locally in your application. Best of both worlds: security + performance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Practical example — patient records:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;1. Patient uploads medical scan (500 MB)
&lt;&#x2F;span&gt;&lt;span&gt;2. You request a data key from KMS (costs ~$0.03)
&lt;&#x2F;span&gt;&lt;span&gt;3. Application encrypts scan with plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;4. Plaintext key is immediately discarded
&lt;&#x2F;span&gt;&lt;span&gt;5. Database stores:
&lt;&#x2F;span&gt;&lt;span&gt;   - Encrypted scan (500 MB, unreadable)
&lt;&#x2F;span&gt;&lt;span&gt;   - Encrypted data key (200 bytes, small)
&lt;&#x2F;span&gt;&lt;span&gt;6. The CMK stays locked in KMS (never exported, never leaves AWS)
&lt;&#x2F;span&gt;&lt;span&gt;7. To decrypt: send encrypted key to KMS, get plaintext key
&lt;&#x2F;span&gt;&lt;span&gt;8. Audit trail in CloudTrail: &amp;quot;Who decrypted what and when&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;AWS-managed vs. Customer-managed keys:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Type&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Cost&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Control&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Use when&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;AWS-managed&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Free&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Limited (AWS rotates annually)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Most AWS services (S3, RDS, DynamoDB by default)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Customer-managed&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;~$1&#x2F;month + API calls&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Full (you choose rotation, who can access, audit trail)&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Compliance-heavy (HIPAA, GDPR, biomedical data)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;For biomedical research with patient data, &lt;strong&gt;customer-managed keys are typically required&lt;&#x2F;strong&gt; because auditors need to see exactly who accessed the encryption keys and when (CloudTrail).&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;acm&#x2F;latest&#x2F;userguide&#x2F;acm-overview.html&quot;&gt;AWS ACM (Certificate Manager)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Handles TLS&#x2F;SSL certificates for your domains. If you&#x27;ve wrestled with &lt;a href=&quot;https:&#x2F;&#x2F;letsencrypt.org&#x2F;&quot;&gt;Let&#x27;s Encrypt&lt;&#x2F;a&gt; renewals, ACM is the managed equivalent.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Public certificates (Free):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Domain validation: ACM verifies you own the domain&lt;&#x2F;li&gt;
&lt;li&gt;Use with: ALB, CloudFront, API Gateway&lt;&#x2F;li&gt;
&lt;li&gt;Automatic renewal: No more &quot;certificate expired at 3am&quot; alerts&lt;&#x2F;li&gt;
&lt;li&gt;Wildcard support: &lt;code&gt;*.example.com&lt;&#x2F;code&gt; covers all subdomains&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Private CA (Paid):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For internal services that need TLS but aren&#x27;t exposed to the internet&lt;&#x2F;li&gt;
&lt;li&gt;Example: Your research database server communicates with Python scripts using mutual TLS&lt;&#x2F;li&gt;
&lt;li&gt;Cost: ~$400&#x2F;month for the CA, plus per-certificate fees&lt;&#x2F;li&gt;
&lt;li&gt;Use when: Internal services need encrypted communication, but you control both client and server&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;The tradeoff:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ACM public certificates:&lt;&#x2F;strong&gt; Free, automatic, but only work with AWS services&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Let&#x27;s Encrypt:&lt;&#x2F;strong&gt; Free, but you manage renewal automation yourself&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;ACM private CA:&lt;&#x2F;strong&gt; Paid, but manages all internal TLS automatically&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For biomedical research centers: use &lt;strong&gt;free public certificates for your website&lt;&#x2F;strong&gt; (ACM + ALB), and use &lt;strong&gt;HTTP&#x2F;2 between internal services&lt;&#x2F;strong&gt; (encryption handled by VPC itself, no need for certificates).&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;crypto.png&quot; alt=&quot;Speak louder for those at the back of the room&quot; title=&quot;Speak louder for those at the back of the room&quot;&#x2F;&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;h3 id=&quot;cloudtrail-who-did-what-and-when&quot;&gt;CloudTrail: who did what, and when&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;awscloudtrail&#x2F;latest&#x2F;userguide&#x2F;cloudtrail-user-guide.html&quot;&gt;AWS CloudTrail&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; records every API call made in your AWS account. Every. Single. One. Someone launched an EC2 instance? Logged. Someone changed a security group? Logged. Someone tried to access an S3 bucket and was denied? Logged.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;What CloudTrail captures:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Field&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Example&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Who&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;arn:aws:iam::123456789012:user&#x2F;jdoe&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;What&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;RunInstances&lt;&#x2F;code&gt;, &lt;code&gt;PutBucketPolicy&lt;&#x2F;code&gt;, &lt;code&gt;DeleteObject&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;When&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;2026-02-04T14:32:17Z&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Where&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;eu-west-3&lt;&#x2F;code&gt;, source IP &lt;code&gt;203.0.113.42&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;How&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Console, CLI, SDK, or assumed role&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Result&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Success or failure (with error code)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Event types:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Management events&lt;&#x2F;strong&gt;: Control plane operations (creating resources, changing configurations). Logged by default.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Data events&lt;&#x2F;strong&gt;: Data plane operations (reading S3 objects, invoking Lambda functions). &lt;em&gt;Not&lt;&#x2F;em&gt; logged by default — you must explicitly enable them. They&#x27;re high-volume and cost money.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Insights events&lt;&#x2F;strong&gt;: CloudTrail analyzes your patterns and flags unusual activity (sudden spike in API calls, unusual error rates).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Practical example — investigating a security incident:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A researcher reports they can&#x27;t access their S3 bucket anymore. You suspect someone changed the bucket policy. With CloudTrail and &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;logs&#x2F;AnalyzingLogData.html&quot;&gt;CloudWatch Logs Insights&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sql&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-sql &quot;&gt;&lt;code class=&quot;language-sql&quot; data-lang=&quot;sql&quot;&gt;&lt;span&gt;fields @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;userIdentity&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;arn&lt;&#x2F;span&gt;&lt;span&gt;, eventName, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;requestParameters&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;bucketName
&lt;&#x2F;span&gt;&lt;span&gt;| filter eventSource = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3.amazonaws.com&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;| filter eventName &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;like &#x2F;&lt;&#x2F;span&gt;&lt;span&gt;PutBucket&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;| filter &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;requestParameters&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;bucketName &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;research-datasets&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;| sort @&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;timestamp desc
&lt;&#x2F;span&gt;&lt;span&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;limit &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This query shows you exactly who modified the bucket policy, when, and from where. No more guessing, no more &quot;it wasn&#x27;t me.&quot; The audit trail is immutable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Best practices:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enable CloudTrail in all regions&lt;&#x2F;strong&gt; — attacks often target regions you&#x27;re not watching&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Send logs to a centralized S3 bucket&lt;&#x2F;strong&gt; in a dedicated security account — so attackers can&#x27;t delete their tracks even if they compromise a workload account&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Enable log file integrity validation&lt;&#x2F;strong&gt; — CloudTrail can detect if someone tampered with log files&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Set up &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;awscloudtrail&#x2F;latest&#x2F;userguide&#x2F;cloudwatch-alarms-for-cloudtrail.html&quot;&gt;CloudWatch alarms&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; for critical events: root account login, IAM policy changes, security group modifications, console sign-in failures&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;The traditional infrastructure equivalent:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;CloudTrail Feature&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Traditional Equivalent&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Management events&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt; on Linux, syslog for config changes&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Data events&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Application-level access logs (Apache, Nginx logs)&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Insights&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Custom anomaly detection scripts, SIEM correlation rules&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Log integrity&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;AIDE&lt;&#x2F;code&gt;, &lt;code&gt;Tripwire&lt;&#x2F;code&gt;, signed log shipping&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Multi-region logging&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Centralized syslog server, rsyslog forwarding&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;In the biomedical research context:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;CloudTrail is &lt;em&gt;required&lt;&#x2F;em&gt; for compliance. HIPAA mandates audit trails for access to protected health information. GDPR requires you to demonstrate who accessed personal data and why. CloudTrail, combined with &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;config&#x2F;latest&#x2F;developerguide&#x2F;WhatIsConfig.html&quot;&gt;AWS Config&lt;&#x2F;a&gt; (which tracks &lt;em&gt;resource&lt;&#x2F;em&gt; configuration changes over time), gives you a complete audit story.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;equivalence-in-the-linux-world&quot;&gt;Equivalence in the Linux world&lt;&#x2F;h2&gt;
&lt;p&gt;The concepts we&#x27;ve covered aren&#x27;t AWS innovations. They&#x27;re &lt;strong&gt;fundamental security patterns&lt;&#x2F;strong&gt; that exist in every operating system. Here&#x27;s how AWS services map to traditional Linux&#x2F;Unix equivalents:&lt;&#x2F;p&gt;
&lt;table style=&quot;border-collapse: collapse; border: 1px solid #333; width: 100%;&quot;&gt;
  &lt;thead&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;AWS Service&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Linux&#x2F;Unix Equivalent&lt;&#x2F;th&gt;
      &lt;th style=&quot;border: 1px solid #333; padding: 10px; text-align: left;&quot;&gt;Purpose&lt;&#x2F;th&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;thead&gt;
  &lt;tbody&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;IAM Policies&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt;, file permissions (rwx), RBAC&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Define who can do what&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Permission Boundaries&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;AppArmor, SELinux policies&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Set maximum permissions ceiling&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;OIDC (Federated Identity)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;LDAP, Kerberos, PAM modules&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;External identity provider authentication&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;Trust Policy&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;sudoers&lt;&#x2F;code&gt;, PAM rules&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Define who can assume a role&#x2F;user&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;KMS (Encryption Keys)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;GPG, OpenSSL, PKCS#11, HSM&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manage encryption keys centrally&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;ACM (Certificates)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Let&#x27;s Encrypt + certbot, OpenSSL&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Manage TLS&#x2F;SSL certificates&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr style=&quot;border: 1px solid #333;&quot;&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;strong&gt;CloudTrail (Audit)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt;, &lt;code&gt;syslog&lt;&#x2F;code&gt;, &lt;code&gt;journalctl&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;
      &lt;td style=&quot;border: 1px solid #333; padding: 10px;&quot;&gt;Immutable audit logs of system activity&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Why AWS then?&lt;&#x2F;strong&gt; These equivalents work great on Linux, but AWS eliminates the plumbing work, automates, standardizes, and integrates these patterns across hundreds of services. AWS provides enterprise-grade reliability.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;If Day 1 was about &quot;where and what,&quot; Day 2-3 has been about &quot;how and who.&quot; Security and audit should not be something you think about &lt;em&gt;after&lt;&#x2F;em&gt;. They&#x27;re the foundation of any production infrastructure, especially even more for people handling sensitive data like what we do with &lt;a href=&quot;&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;4S&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The patterns here generalize beyond AWS: whether you&#x27;re running on-premises or on another cloud, the principles remain the same:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Default deny, explicit allow&lt;&#x2F;strong&gt;: the principle of least privilege applied everywhere&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Separate the identity layer&lt;&#x2F;strong&gt;: authentication (who you are) from authorization (what you can do)&lt;&#x2F;li&gt;
&lt;li&gt;**Keep an immutable audit trail: you can&#x27;t defend what you can&#x27;t prove&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Encrypt by default&lt;&#x2F;strong&gt;: both in transit and at rest&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Use temporary credentials&lt;&#x2F;strong&gt;: no long-lived secrets scattered across your infrastructure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I don&#x27;t think I have fully understood and mastered everything. I don&#x27;t think I can explore everything in a single article. If you want to dive deeper into AWS security and audit, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;best-practices.html&quot;&gt;AWS Identity and Access Management Best Practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;architecture&#x2F;security-identity-compliance&#x2F;&quot;&gt;AWS Security Best Practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;compliance&#x2F;hipaa-compliance&#x2F;&quot;&gt;HIPAA Compliance on AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;compliance&#x2F;gdpr-center&#x2F;&quot;&gt;GDPR Compliance on AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;awscloudtrail&#x2F;latest&#x2F;userguide&#x2F;cloudtrail-user-guide.html&quot;&gt;CloudTrail User Guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;kms&#x2F;latest&#x2F;developerguide&#x2F;best-practices.html&quot;&gt;KMS Best Practices&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;prescriptive-guidance&#x2F;latest&#x2F;security-reference-architecture&#x2F;&quot;&gt;AWS Security Reference Architecture (SRA)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_roles_providers_oidc.html&quot;&gt;OpenID Connect on AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;owasp.org&#x2F;www-project-top-ten&#x2F;&quot;&gt;The OWASP Top 10 and how cloud addresses it&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;security&#x2F;zero-trust&#x2F;&quot;&gt;Zero Trust Architecture&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>AWS (Day 1)</title>
        <published>2026-02-02T00:00:00+00:00</published>
        <updated>2026-02-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/aws-1/"/>
        <id>https://nskm.xyz/posts/aws-1/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/aws-1/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-infra.jpg&quot; alt=&quot;infrastructure&quot; title=&quot;infrastructure&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I don&#x27;t agree with this, but my employer says I don&#x27;t have the right to share the source code I&#x27;ve written in the course of my work. &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;shorts&#x2F;FEYlE8pHICk&quot;&gt;I don&#x27;t ever want a problem&lt;&#x2F;a&gt;. So, I&#x27;ll try to say as much as I can without divulging any specific information.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If you are a colleague and recognize the situation described below, remember: I&#x27;m critiquing the system, not the people.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, but if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Render unto Caesar what is Caesar&#x27;s, Claude helped me find up-to-date documentation links and he also helped beautify all the diagrams used (and not used) in this article.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;&#x2F;h2&gt;
&lt;p&gt;One of the joys of corporate life: you&#x27;re politely asked what training would help you be more productive, and a few months later, you&#x27;re enrolled in something completely unrelated to your request.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve been asked to take a course called &quot;AWS Automation and Observability.&quot; Of course, I only have one choice: accept. Even though I wasn&#x27;t sure it would be immediately relevant to my current work.&lt;&#x2F;p&gt;
&lt;p&gt;Training you didn&#x27;t choose &lt;em&gt;(especially when you already have some technical background)&lt;&#x2F;em&gt; can feel misaligned with your current interests. When the content covers tools like &lt;a href=&quot;https:&#x2F;&#x2F;i.giphy.com&#x2F;pPhyAv5t9V8djyRFJH.webp&quot;&gt;Jenkins&lt;&#x2F;a&gt; without discussing more modern CI&#x2F;CD approaches, the relevance can feel limited.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a certain irony in being told:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;« Il est strictement interdit d&#x27;enregistrer, de filmer ou de fixer par quelque moyen que ce soit les sessions de formation. Les supports doivent rester confidentiels. »&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;...when the material itself is widely available in public documentation, and when &lt;em&gt;(at least for day 0)&lt;&#x2F;em&gt;, there was no instructor-specific examples or custom material. I respect the instructor&#x27;s knowledge of the subject, &lt;em&gt;he clearly knows his stuff&lt;&#x2F;em&gt;, but I felt the format, delivery, and relevance could have been better tailored to the audience.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps the problem isn&#x27;t the instructor but the constraints he was working under: limited time, the fact that there were too many people with different levels in the same class, or budget restrictions. In an ideal world, training would be more engaging, current, and tailored to diverse experience levels. There were opportunities to improve on these dimensions.&lt;&#x2F;p&gt;
&lt;p&gt;Since there&#x27;s no escaping it, might as well make the most of it and stay in a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=m7XZyj6Ru9w&quot;&gt;good mood&lt;&#x2F;a&gt;. Let&#x27;s talk about what I wish the first day had covered and &lt;em&gt;how&lt;&#x2F;em&gt; it should have been covered.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aws&quot;&gt;AWS&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;&quot;&gt;Amazon Web Services (AWS)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is Amazon&#x27;s cloud computing platform, launched in 2006 with two initial services: &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;&quot;&gt;S3 (Simple Storage Service)&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ec2&#x2F;&quot;&gt;EC2 (Elastic Compute Cloud)&lt;&#x2F;a&gt;. The idea emerged from Amazon&#x27;s internal infrastructure challenges—they had built robust, scalable systems to handle their e-commerce peaks, and realized they could rent that infrastructure to others.&lt;&#x2F;p&gt;
&lt;p&gt;Today, AWS offers &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;products&#x2F;&quot;&gt;200+ services&lt;&#x2F;a&gt; spanning compute, storage, databases, machine learning, networking, and more. It holds roughly 31% of the global cloud market share (as of 2024), making it the largest cloud provider. &lt;em&gt;Phew&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In Africa, the &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;local&#x2F;africa&#x2F;cape-town&#x2F;&quot;&gt;Cape Town region (af-south-1)&lt;&#x2F;a&gt; was launched in 2020. It is AWS&#x27;s first and currently only African region. There&#x27;s no dedicated region yet for West Africa specifically. Users typically connect to eu-west-3 (Paris) or af-south-1 (Cape Town) depending on latency requirements.&lt;&#x2F;p&gt;
&lt;p&gt;AWS does also have :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;about-aws&#x2F;whats-new&#x2F;2023&#x2F;06&#x2F;aws-edge-location-nigeria&#x2F;&quot;&gt;Edge locations (CloudFront POPs) in Lagos and Nairobi&lt;&#x2F;a&gt; for content delivery.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;about-aws&#x2F;whats-new&#x2F;2025&#x2F;04&#x2F;aws-wavelength-zone-dakar&#x2F;&quot;&gt;Wavelength zone in Dakar Senegal&lt;&#x2F;a&gt;, a new type of infrastructure designed to run workloads that require low latency or edge resiliency.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;alternatives-the-hyperscalers&quot;&gt;Alternatives: the hyperscalers&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Hyperscalers&lt;&#x2F;strong&gt; are cloud providers operating at &lt;em&gt;massive&lt;&#x2F;em&gt; scale; we are talking about data centers across multiple continents, serving &lt;em&gt;millionZ&lt;&#x2F;em&gt; of customers simultaneously. The &lt;em&gt;&quot;Big 3&quot;&lt;&#x2F;em&gt; dominate the market:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Provider &lt;&#x2F;th&gt;&lt;th&gt;Share&lt;&#x2F;th&gt;&lt;th&gt;Strengths&lt;&#x2F;th&gt;&lt;th&gt;Best For&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;&quot;&gt;AWS&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~31%&lt;&#x2F;td&gt;&lt;td&gt;Widest service catalog, mature ecosystem&lt;&#x2F;td&gt;&lt;td&gt;General purpose, enterprise, startups&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;azure.microsoft.com&#x2F;&quot;&gt;Azure&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~24%&lt;&#x2F;td&gt;&lt;td&gt;Windows integration, hybrid cloud&lt;&#x2F;td&gt;&lt;td&gt;Microsoft shops, hybrid deployments&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;&quot;&gt;GCP&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~11%&lt;&#x2F;td&gt;&lt;td&gt;Data analytics, ML&#x2F;AI (TensorFlow), Kubernetes &lt;&#x2F;td&gt;&lt;td&gt;Data-heavy workloads, ML projects&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Notable alternatives:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;&quot;&gt;DigitalOcean&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;&quot;&gt;Linode&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;www.vultr.com&#x2F;&quot;&gt;Vultr&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Simpler, developer-friendly, cheaper for small workloads&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ovhcloud.com&#x2F;&quot;&gt;OVHcloud&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — European provider, good for GDPR compliance, competitive pricing&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.scaleway.com&#x2F;&quot;&gt;Scaleway&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — French provider, strong EU presence, interesting ARM offerings&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.hetzner.com&#x2F;&quot;&gt;Hetzner&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — German provider, excellent price-to-performance ratio, popular for self-hosted projects&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The hyperscaler choice often comes down to existing tooling, team expertise, and specific service needs rather than raw capability. They all solve similar problems.&lt;&#x2F;p&gt;
&lt;p&gt;As an advocate for the &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;philosophy&#x2F;free-software-intro.en.html&quot;&gt;free software movement&lt;&#x2F;a&gt;, what is my advice ?&lt;&#x2F;p&gt;
&lt;p&gt;GCP: While proprietary, Google has historically &lt;a href=&quot;https:&#x2F;&#x2F;opensource.google&#x2F;projects&quot;&gt;opened up key technologies&lt;&#x2F;a&gt; such as Kubernetes and &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&quot;&gt;many others&lt;&#x2F;a&gt; to promote interoperability and reduce vendor lock-in.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;technologies&#x2F;cloud-computing&#x2F;openshift&quot;&gt;Red Hat OpenShift (on any cloud)&lt;&#x2F;a&gt;: Not a &lt;a href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;topics&#x2F;cloud-computing&#x2F;what-is-a-hyperscaler&quot;&gt;hyperscaler&lt;&#x2F;a&gt; per se, but using this platform on a cloud infrastructure allows you to maintain a free and portable software layer between different providers.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;why-would-a-biomedical-research-center-use-aws&quot;&gt;Why would a biomedical research center use AWS ?&lt;&#x2F;h3&gt;
&lt;p&gt;For an organization handling sensitive health data and research workloads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compliance&lt;&#x2F;strong&gt;: HIPAA, GDPR-ready configurations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Burst capacity&lt;&#x2F;strong&gt;: spin up hundreds of CPUs for genomic analysis, pay only for what you use&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Global collaboration&lt;&#x2F;strong&gt;: share datasets across continents with proper access controls&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Focus on research&lt;&#x2F;strong&gt;: less time managing servers, more time on science&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#fundamentals&quot;&gt;Fundamentals&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#identity-and-access-management&quot;&gt;Identity and Access Management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#network&quot;&gt;Network&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;VPC basics (CIDR, Subnets)&lt;&#x2F;li&gt;
&lt;li&gt;Gateways (IGW, NAT)&lt;&#x2F;li&gt;
&lt;li&gt;Hybrid connectivity&lt;&#x2F;li&gt;
&lt;li&gt;Network Security&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#load-balancing&quot;&gt;Load Balancing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#compute-services&quot;&gt;Compute Services&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#storage&quot;&gt;Storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;aws-1&#x2F;#observability&quot;&gt;Observability&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;aws-concepts-traditional-infrastructure&quot;&gt;AWS concepts → Traditional infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;If you&#x27;ve been managing Linux servers, you already know most of these concepts. AWS just wraps them in managed services with different names:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;AWS Service&#x2F;Concept&lt;&#x2F;th&gt;&lt;th&gt;Traditional Equivalent&lt;&#x2F;th&gt;&lt;th&gt;What&#x27;s Different?&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EC2&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Physical server, VM (KVM&#x2F;VMware)&lt;&#x2F;td&gt;&lt;td&gt;Rent by the hour, no hardware to buy&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;VPC&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Network subnet, VLAN&lt;&#x2F;td&gt;&lt;td&gt;Software-defined, fully isolated per customer&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Security Groups&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt; rules (instance-level)&lt;&#x2F;td&gt;&lt;td&gt;Stateful, attached to network interfaces&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Network ACLs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;iptables&lt;&#x2F;code&gt; at router&#x2F;subnet level&lt;&#x2F;td&gt;&lt;td&gt;Stateless, numbered rules, processed in order&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;File server (NFS, Samba), MinIO&lt;&#x2F;td&gt;&lt;td&gt;Object storage (not filesystem), infinite scale, HTTP API&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EBS&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Hard drive, LVM volume&lt;&#x2F;td&gt;&lt;td&gt;Network-attached block storage, point-in-time snapshots&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EFS&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;NFS share&lt;&#x2F;td&gt;&lt;td&gt;Managed NFS, auto-scaling, multi-AZ&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;RDS&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;PostgreSQL server you installed&lt;&#x2F;td&gt;&lt;td&gt;AWS manages backups, patches, replication, HA&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Load Balancer (ALB&#x2F;NLB)&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Nginx, HAProxy, Apache &lt;code&gt;mod_proxy&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Fully managed, auto-scales, integrated health checks&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Auto Scaling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Custom bash scripts watching &lt;code&gt;top&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Automatic instance scaling based on CloudWatch metrics&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IAM&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;&#x2F;etc&#x2F;passwd&lt;&#x2F;code&gt;, &lt;code&gt;sudo&lt;&#x2F;code&gt;, LDAP&#x2F;Active Directory&lt;&#x2F;td&gt;&lt;td&gt;Controls AWS API access, not just OS users&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;IAM Roles&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Service accounts, &lt;code&gt;systemd&lt;&#x2F;code&gt; user credentials&lt;&#x2F;td&gt;&lt;td&gt;Temporary credentials that auto-rotate&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudWatch Metrics&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Prometheus, Nagios, Zabbix, Grafana&lt;&#x2F;td&gt;&lt;td&gt;Pre-integrated with all AWS services&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudWatch Logs&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;syslog&lt;&#x2F;code&gt;, &lt;code&gt;journald&lt;&#x2F;code&gt;, ELK stack&lt;&#x2F;td&gt;&lt;td&gt;Centralized log aggregation, SQL-like queries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudWatch Alarms&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Nagios alerts, &lt;code&gt;monit&lt;&#x2F;code&gt;, custom scripts&lt;&#x2F;td&gt;&lt;td&gt;Trigger actions (scaling, notifications, Lambda)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;CloudTrail&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;&lt;code&gt;auditd&lt;&#x2F;code&gt;, &lt;code&gt;&#x2F;var&#x2F;log&#x2F;audit&#x2F;audit.log&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td&gt;Every AWS API call logged (who did what, when)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Lambda&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Cron jobs + shell scripts&lt;&#x2F;td&gt;&lt;td&gt;Event-driven functions, no server to manage&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Route 53&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;BIND, &lt;code&gt;dnsmasq&lt;&#x2F;code&gt;, PowerDNS&lt;&#x2F;td&gt;&lt;td&gt;Managed DNS with health checks and routing policies&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Regions&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Multiple data center locations&lt;&#x2F;td&gt;&lt;td&gt;Completely isolated, compliance&#x2F;data residency boundaries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Availability Zones&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Separate racks&#x2F;power&#x2F;networking in same DC&lt;&#x2F;td&gt;&lt;td&gt;Physical separation within region, low-latency links&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;The trade-off&lt;&#x2F;strong&gt;: You give up control (can&#x27;t SSH into the Load Balancer) in exchange for less maintenance (AWS patches it for you). Whether that&#x27;s worth it depends on your team size, expertise, and what you&#x27;re trying to build. And if you understood everything inside the table above, you can stop here, I&#x27;m serious :\&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;want-to-know-more-okay&quot;&gt;Want to know more ? Okay&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;fundamentals&quot;&gt;Fundamentals&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;global-infrastructure&#x2F;latest&#x2F;regions&#x2F;aws-regions.html&quot;&gt;Regions&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are geographically isolated clusters of data centers. Each region (e.g., &lt;code&gt;eu-west-3&lt;&#x2F;code&gt; for Paris, &lt;code&gt;us-east-1&lt;&#x2F;code&gt; for N. Virginia) operates independently. You choose a region based on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Latency&lt;&#x2F;strong&gt; — closer to your users = faster response&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Compliance&lt;&#x2F;strong&gt; — data residency laws may require specific locations&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Service availability&lt;&#x2F;strong&gt; — not all services exist in all regions&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Pricing&lt;&#x2F;strong&gt; — costs vary by region&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;global-infrastructure&#x2F;latest&#x2F;regions&#x2F;aws-availability-zones.html&quot;&gt;Availability Zones (AZs)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are physically separate data centers within a region, connected by low-latency links. Deploying across multiple Zones provides fault tolerance: if one data center fails, your application survives.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;organizations&#x2F;latest&#x2F;userguide&#x2F;orgs_introduction.html&quot;&gt;Organizations&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is a service designed for central governance and management of multiple AWS accounts. They are useful for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Isolating environments (dev&#x2F;staging&#x2F;prod)&lt;&#x2F;li&gt;
&lt;li&gt;Separating billing by department or project&lt;&#x2F;li&gt;
&lt;li&gt;Applying security policies across accounts&lt;&#x2F;li&gt;
&lt;li&gt;Consolidated billing with volume discounts&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;identity-and-access-management&quot;&gt;Identity and Access Management&lt;&#x2F;h3&gt;
&lt;p&gt;Before you start spinning up resources, you need to understand &lt;strong&gt;who can do what&lt;&#x2F;strong&gt; in your AWS account. This is where &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;introduction.html&quot;&gt;IAM (Identity and Access Management)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; comes in.&lt;&#x2F;p&gt;
&lt;p&gt;IAM is AWS&#x27;s authentication and authorization service. It controls who can access your AWS resources and what actions they can perform. Get this wrong, and you&#x27;ll either lock yourself out or leave your infrastructure wide open to attackers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Core IAM concepts:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Component&lt;&#x2F;th&gt;&lt;th&gt;Purpose&lt;&#x2F;th&gt;&lt;th&gt;When to Use&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_users.html&quot;&gt;Users&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Individual identities with permanent credentials&lt;&#x2F;td&gt;&lt;td&gt;Human access via Console&#x2F;CLI&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_groups.html&quot;&gt;Groups&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Collections of users with shared permissions&lt;&#x2F;td&gt;&lt;td&gt;Organizing users by function (developers, ops, analysts)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;id_roles.html&quot;&gt;Roles&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Temporary credentials that can be assumed&lt;&#x2F;td&gt;&lt;td&gt;Services, applications, cross-account access&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html&quot;&gt;Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;JSON documents defining permissions&lt;&#x2F;td&gt;&lt;td&gt;Attach to users, groups, or roles&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;IAM&#x2F;latest&#x2F;UserGuide&#x2F;access_policies.html&quot;&gt;IAM Policies&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are JSON documents that specify allowed or denied actions. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Version&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;2012-10-17&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Statement&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Effect&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Allow&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Action&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:GetObject&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;s3:ListBucket&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Resource&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;arn:aws:s3:::my-research-data&#x2F;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;  }]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This policy allows reading objects from a specific S3 bucket, nothing more. That&#x27;s the &lt;strong&gt;principle of least privilege&lt;&#x2F;strong&gt;: grant only the minimum permissions needed to do the job.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Why roles matter more than you think:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The biggest mistake beginners make is hardcoding AWS credentials in their applications. I should be honest with you here, yes I&#x27;ve done it when I was younger. But today, please, I&#x27;m telling you, don&#x27;t do this.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Example scenario&lt;&#x2F;strong&gt;: Your EC2 instance needs to read files from S3.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Wrong approach&lt;&#x2F;strong&gt;: Store AWS access keys in a config file on the instance.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Keys can be stolen if the instance is compromised&lt;&#x2F;li&gt;
&lt;li&gt;Keys don&#x27;t rotate automatically&lt;&#x2F;li&gt;
&lt;li&gt;Difficult to audit who used which credentials&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Right approach&lt;&#x2F;strong&gt;: Attach an IAM role with S3 read permissions to the EC2 instance.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No credentials stored anywhere&lt;&#x2F;li&gt;
&lt;li&gt;Temporary credentials rotate automatically&lt;&#x2F;li&gt;
&lt;li&gt;CloudTrail logs show exactly which instance accessed which resources&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Root account protection:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;When you create an AWS account, you get a root user with unlimited access. This is dangerous. Best practices:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Enable MFA&lt;&#x2F;strong&gt; (Multi-Factor Authentication) on the root account&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Create IAM users&lt;&#x2F;strong&gt; for daily work, even for administrators&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Lock away root credentials&lt;&#x2F;strong&gt; - only use them for tasks that &lt;em&gt;require&lt;&#x2F;em&gt; root (billing, account closure)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;organizations&#x2F;latest&#x2F;userguide&#x2F;orgs_manage_policies_scps.html&quot;&gt;AWS Organizations and Service Control Policies (SCPs)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; add another layer: they set permission boundaries across multiple accounts. Even if an IAM policy allows an action, an SCP can block it at the organization level. Useful for enforcing compliance (e.g., &quot;no one can launch instances outside eu-west-3&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;In the biomedical research context:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You&#x27;d use IAM to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Give researchers read-only access to specific S3 buckets containing datasets&lt;&#x2F;li&gt;
&lt;li&gt;Allow the data engineering team to manage ETL pipelines (write access to certain resources)&lt;&#x2F;li&gt;
&lt;li&gt;Grant your analysis scripts (running on EC2&#x2F;Lambda) temporary credentials to access databases&lt;&#x2F;li&gt;
&lt;li&gt;Prevent anyone from accidentally exposing patient data by restricting public S3 bucket creation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Security Groups (covered below) control &lt;em&gt;network&lt;&#x2F;em&gt; access. IAM controls &lt;em&gt;identity and authorization&lt;&#x2F;em&gt;. You need both.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network&quot;&gt;Network&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Maybe I did need this class after all. I&#x27;m having flashbacks... crimping tool... crossover cable... straight cable... cat5.... class C... IPV6... Layer 3... Layer 4....&lt;&#x2F;em&gt; Heeelp! \o&#x2F;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;what-is-amazon-vpc.html&quot;&gt;VPC (Virtual Private Cloud)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is your isolated network within AWS. With a VPC you define:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;what-is&#x2F;cidr&#x2F;&quot;&gt;CIDR block&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: your IP range (e.g., &lt;code&gt;10.0.0.0&#x2F;16&lt;&#x2F;code&gt; gives you 65,536 IPs)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;configure-subnets.html&quot;&gt;Subnets&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: subdivisions of your VPC, placed in specific Zones
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Public subnets&lt;&#x2F;em&gt;: resources can have public IPs, direct internet access&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Private subnets&lt;&#x2F;em&gt;: no direct internet access, only internal communication&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Gateways:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;VPC_Internet_Gateway.html&quot;&gt;Internet Gateway (IGW)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: enables internet access for public subnets. Attach one to your VPC, add routes, done.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-nat-gateway.html&quot;&gt;NAT Gateway&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: lets private subnet resources reach the internet (for updates, API calls) without being directly reachable..&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Hybrid connectivity:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpn&#x2F;latest&#x2F;s2svpn&#x2F;VPC_VPN.html&quot;&gt;Site-to-Site VPN&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: encrypted tunnel between your on-premises network and AWS VPC. Quick to set up, uses public internet, variable latency.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;directconnect&#x2F;latest&#x2F;UserGuide&#x2F;Welcome.html&quot;&gt;AWS Direct Connect&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: dedicated physical connection to AWS. Consistent latency, higher bandwidth, but requires physical setup and contracts. Useful for heavy data transfer or strict latency requirements.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Network Security:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;AWS provides two complementary layers of network security: &lt;strong&gt;Security Groups&lt;&#x2F;strong&gt; and &lt;strong&gt;Network ACLs&lt;&#x2F;strong&gt;. Understanding when to use each is critical.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-security-groups.html&quot;&gt;Security Groups&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are stateful firewalls attached to resources (EC2 instances, RDS databases, etc.). They act like bouncers at the door of individual servers. Define allowed inbound&#x2F;outbound traffic by port, protocol, and source. If you allow inbound traffic on port 80, the return traffic is automatically allowed—that&#x27;s what &quot;stateful&quot; means.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;vpc-network-acls.html&quot;&gt;Network ACLs (NACLs)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; are stateless firewalls at the subnet level. They filter traffic entering or leaving entire subnets. Rules are evaluated in numerical order (100, 200, 300...), and the first match wins. Unlike Security Groups, NACLs require explicit rules for both inbound and outbound traffic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Security Groups vs. Network ACLs:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;Security Groups&lt;&#x2F;th&gt;&lt;th&gt;Network ACLs&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scope&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Instance level (attached to ENI)&lt;&#x2F;td&gt;&lt;td&gt;Subnet level&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;State&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Stateful (return traffic auto-allowed)&lt;&#x2F;td&gt;&lt;td&gt;Stateless (must allow both directions)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Rules&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Only Allow rules&lt;&#x2F;td&gt;&lt;td&gt;Allow + Deny rules&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Evaluation&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;All rules evaluated&lt;&#x2F;td&gt;&lt;td&gt;Processed in order, first match wins&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Default behavior&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Deny all inbound, allow all outbound&lt;&#x2F;td&gt;&lt;td&gt;Allow everything&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Typical use&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Your primary security control&lt;&#x2F;td&gt;&lt;td&gt;Edge cases, compliance, IP blocking&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;When to use what:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Security Groups&lt;&#x2F;strong&gt; should be your default choice for 95% of scenarios:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Allow SSH (port 22) only from your office IP&lt;&#x2F;li&gt;
&lt;li&gt;Let web servers accept HTTP&#x2F;HTTPS from anywhere&lt;&#x2F;li&gt;
&lt;li&gt;Allow database connections only from application servers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Network ACLs&lt;&#x2F;strong&gt; are for specific edge cases:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Block a known malicious IP range at the subnet boundary&lt;&#x2F;li&gt;
&lt;li&gt;Compliance requirements mandating subnet-level controls&lt;&#x2F;li&gt;
&lt;li&gt;Defense-in-depth: add a second layer of protection&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Example scenario - Blocking an attacking IP:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Your web servers (in a public subnet) are under attack from &lt;code&gt;203.0.113.0&#x2F;24&lt;&#x2F;code&gt;. Security Groups can only &lt;em&gt;allow&lt;&#x2F;em&gt; traffic, not deny it. Solution: add a NACL rule.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;NACL Inbound Rules (evaluated in order):
&lt;&#x2F;span&gt;&lt;span&gt;Rule 100: DENY   TCP   80   from 203.0.113.0&#x2F;24   (block attackers)
&lt;&#x2F;span&gt;&lt;span&gt;Rule 200: ALLOW  TCP   80   from 0.0.0.0&#x2F;0        (allow everyone else)
&lt;&#x2F;span&gt;&lt;span&gt;Rule *:   DENY   ALL   ALL  from 0.0.0.0&#x2F;0        (default deny)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because NACLs are stateless, you also need outbound rules for responses:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;NACL Outbound Rules:
&lt;&#x2F;span&gt;&lt;span&gt;Rule 100: ALLOW  TCP  1024-65535  to 0.0.0.0&#x2F;0   (ephemeral ports)
&lt;&#x2F;span&gt;&lt;span&gt;Rule *:   DENY   ALL  ALL         to 0.0.0.0&#x2F;0    (default deny)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;1024-65535&lt;&#x2F;code&gt; range covers ephemeral ports used by client connections. Yes, this is annoying. This is why most people stick to Security Groups.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;&#x2F;strong&gt; The default NACL in your VPC allows all traffic. Most AWS users never modify it. Only touch NACLs when you have &lt;em&gt;3&lt;&#x2F;em&gt; specific reasons.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;vpc&#x2F;latest&#x2F;userguide&#x2F;flow-logs.html&quot;&gt;Flow Logs&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Capture network traffic metadata (source&#x2F;destination IP, port, protocol, action) for debugging and audit. Essential for troubleshooting connectivity issues and security investigations. Send logs to CloudWatch or S3 for analysis.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;load-balancing&quot;&gt;Load Balancing&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;High Availability&lt;&#x2F;strong&gt; means your application stays up even when parts of the infrastructure fail. In AWS, this typically involves deploying across multiple Availability Zones and using load balancers to distribute traffic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;elasticloadbalancing&#x2F;&quot;&gt;Elastic Load Balancing (ELB)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; automatically distributes incoming traffic across multiple targets. AWS offers several types:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Type&lt;&#x2F;th&gt;&lt;th&gt;Layer&lt;&#x2F;th&gt;&lt;th&gt;Best For&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;elasticloadbalancing&#x2F;latest&#x2F;application&#x2F;introduction.html&quot;&gt;Application Load Balancer (ALB)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Layer 7 (HTTP&#x2F;HTTPS)&lt;&#x2F;td&gt;&lt;td&gt;Web apps, microservices, content-based routing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;elasticloadbalancing&#x2F;latest&#x2F;network&#x2F;introduction.html&quot;&gt;Network Load Balancer (NLB)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Layer 4 (TCP&#x2F;UDP)&lt;&#x2F;td&gt;&lt;td&gt;Ultra-low latency, millions of requests&#x2F;sec&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;elasticloadbalancing&#x2F;latest&#x2F;gateway&#x2F;introduction.html&quot;&gt;Gateway Load Balancer&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Layer 3&lt;&#x2F;td&gt;&lt;td&gt;Third-party virtual appliances (firewalls, IDS)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;autoscaling&#x2F;ec2&#x2F;userguide&#x2F;what-is-amazon-ec2-auto-scaling.html&quot;&gt;Auto Scaling&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; automatically adjusts the number of EC2 instances based on demand:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Scheduled scaling&lt;&#x2F;strong&gt;: scale at predictable times (e.g., business hours)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic scaling&lt;&#x2F;strong&gt;: react to CloudWatch metrics (CPU, memory, custom metrics)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Predictive scaling&lt;&#x2F;strong&gt;: ML-based forecasting of future demand&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Multi-AZ resilience&lt;&#x2F;strong&gt;: Deploy instances across multiple AZs, place a load balancer in front, and Auto Scaling replaces failed instances automatically. This is the foundation of most production architectures on AWS.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;compute-services&quot;&gt;Compute Services&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;Compute&lt;&#x2F;strong&gt; refers to the processing power needed to run applications. AWS offers several options depending on your level of control vs. convenience:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ec2&#x2F;&quot;&gt;EC2 (Elastic Compute Cloud)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Virtual machines you fully control. Choose your OS, instance type (CPU&#x2F;RAM), and storage. Pricing models:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Model&lt;&#x2F;th&gt;&lt;th&gt;Description&lt;&#x2F;th&gt;&lt;th&gt;Savings&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;On-Demand&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pay by the hour&#x2F;second, no commitment&lt;&#x2F;td&gt;&lt;td&gt;Baseline pricing&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Reserved&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;1 or 3-year commitment for steady workloads&lt;&#x2F;td&gt;&lt;td&gt;Up to 72% off&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Spot&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Bid on unused capacity, can be interrupted&lt;&#x2F;td&gt;&lt;td&gt;Up to 90% off&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Savings Plans&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Flexible commitment across instance families&lt;&#x2F;td&gt;&lt;td&gt;Up to 72% off&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Container services&lt;&#x2F;strong&gt; — For containerized workloads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonECS&#x2F;latest&#x2F;developerguide&#x2F;Welcome.html&quot;&gt;ECS (Elastic Container Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: AWS-native container orchestration. Simpler than Kubernetes, tightly integrated with AWS.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;eks&#x2F;latest&#x2F;userguide&#x2F;what-is-eks.html&quot;&gt;EKS (Elastic Kubernetes Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Managed Kubernetes. Use this if you need Kubernetes compatibility or already use K8s.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;fargate&#x2F;&quot;&gt;Fargate&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Serverless compute for containers. No EC2 instances to manage—just define CPU&#x2F;memory and run your containers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;When to use what:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;EC2: Full control needed, legacy apps, specific OS requirements&lt;&#x2F;li&gt;
&lt;li&gt;ECS + Fargate: Simple containerized apps, AWS-native approach&lt;&#x2F;li&gt;
&lt;li&gt;EKS: Kubernetes expertise on the team, multi-cloud portability needed&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-computing.jpg&quot; alt=&quot;Cloud computing&quot; title=&quot;Cloud computing&quot;&#x2F;&gt;
&lt;h3 id=&quot;storage&quot;&gt;Storage&lt;&#x2F;h3&gt;
&lt;p&gt;AWS offers different storage types for different use cases:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;&quot;&gt;Amazon S3&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Object storage for any type of data. Highly durable (11 nines), infinitely scalable. &lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;storage-classes&#x2F;&quot;&gt;Storage classes&lt;&#x2F;a&gt; optimize cost based on access patterns:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Class&lt;&#x2F;th&gt;&lt;th&gt;Access Pattern&lt;&#x2F;th&gt;&lt;th&gt;Retrieval&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Standard&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Frequent access&lt;&#x2F;td&gt;&lt;td&gt;Instant&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Intelligent-Tiering&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Unknown&#x2F;changing patterns&lt;&#x2F;td&gt;&lt;td&gt;Instant (auto-moves data)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Standard-IA&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Infrequent access&lt;&#x2F;td&gt;&lt;td&gt;Instant&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;s3&#x2F;storage-classes&#x2F;glacier&#x2F;&quot;&gt;S3 Glacier Instant&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Archive, rare access&lt;&#x2F;td&gt;&lt;td&gt;Milliseconds&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Glacier Flexible&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Archive&lt;&#x2F;td&gt;&lt;td&gt;Minutes to hours&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;S3 Glacier Deep Archive&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Long-term archive&lt;&#x2F;td&gt;&lt;td&gt;12-48 hours&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Lifecycle policies&lt;&#x2F;strong&gt; automatically transition objects between classes or delete them after a period.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Block vs. File storage:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ebs&#x2F;&quot;&gt;EBS (Elastic Block Store)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Block storage attached to a single EC2 instance. Think: hard drive for your VM. Great for databases.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;efs&#x2F;&quot;&gt;EFS (Elastic File System)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Shared file system mountable by multiple EC2 instances. Think: NFS. Great for shared application data.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Databases:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonRDS&#x2F;latest&#x2F;UserGuide&#x2F;Welcome.html&quot;&gt;Amazon RDS (Relational Database Service)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — Managed relational databases for PostgreSQL, &lt;em&gt;(and other database providers I won&#x27;t talk about because I am a free software advocate)&lt;&#x2F;em&gt;. AWS handles the operational heavy lifting: backups, patching, OS updates, and replication. You focus on schema design and queries.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;High Availability and scaling options:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Understanding the difference between &lt;strong&gt;Multi-AZ&lt;&#x2F;strong&gt; and &lt;strong&gt;Read Replicas&lt;&#x2F;strong&gt; is critical:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;Multi-AZ&lt;&#x2F;th&gt;&lt;th&gt;Read Replicas&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Purpose&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;High availability (failover)&lt;&#x2F;td&gt;&lt;td&gt;Read scaling, analytics&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Replication&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Synchronous (to standby in another AZ)&lt;&#x2F;td&gt;&lt;td&gt;Asynchronous (can lag slightly)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Failover&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Automatic (1-2 minutes)&lt;&#x2F;td&gt;&lt;td&gt;Manual promotion required&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Readable&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Standby is not accessible&lt;&#x2F;td&gt;&lt;td&gt;Yes, handle read traffic&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Use case&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Production databases requiring uptime&lt;&#x2F;td&gt;&lt;td&gt;Distribute read load, reporting queries&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Cost&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;~2x (paying for standby)&lt;&#x2F;td&gt;&lt;td&gt;Additional instance cost per replica&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;Multi-AZ deployment&lt;&#x2F;strong&gt;: Your primary database synchronously replicates to a standby instance in a different Availability Zone. If the primary fails (hardware issue, AZ outage), RDS automatically fails over to the standby. Your application reconnects to the same endpoint—no code changes needed. This is for &lt;strong&gt;disaster recovery&lt;&#x2F;strong&gt;, not performance.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Read Replicas&lt;&#x2F;strong&gt;: Create up to 15 read-only copies of your database. Use them to offload read traffic (analytics, reporting) from the primary. Replication is asynchronous, so there may be a slight lag (usually milliseconds to seconds). You can promote a replica to primary if needed, but it&#x27;s a manual operation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;rds&#x2F;aurora&#x2F;&quot;&gt;Amazon Aurora&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; — AWS&#x27;s proprietary database engine, PostgreSQL compatible:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;&#x2F;strong&gt;: Up to 3x faster than PostgreSQL (according to AWS benchmarks)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Storage auto-scaling&lt;&#x2F;strong&gt;: Starts at 10GB, grows automatically up to 128TB in 10GB increments&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;High availability built-in&lt;&#x2F;strong&gt;: Data replicated 6 ways across 3 AZs automatically&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Read scaling&lt;&#x2F;strong&gt;: Up to 15 Aurora Replicas with sub-10ms replica lag&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Cost&lt;&#x2F;strong&gt;: More expensive than standard RDS, but better price-to-performance for demanding workloads&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.cloudzero.com&#x2F;blog&#x2F;aurora-vs-rds&#x2F;&quot;&gt;Aurora&lt;&#x2F;a&gt; is AWS&#x27;s recommended choice for new applications that need high performance and availability.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Backup Strategies:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;RDS provides two backup mechanisms:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonRDS&#x2F;latest&#x2F;UserGuide&#x2F;USER_WorkingWithAutomatedBackups.html&quot;&gt;Automated backups&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Enabled by default&lt;&#x2F;li&gt;
&lt;li&gt;Point-in-time recovery: restore your database to any second within the retention period (1-35 days)&lt;&#x2F;li&gt;
&lt;li&gt;Full daily backups + transaction logs&lt;&#x2F;li&gt;
&lt;li&gt;Deleted when you delete the RDS instance (unless you configure a final snapshot)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonRDS&#x2F;latest&#x2F;UserGuide&#x2F;USER_CreateSnapshot.html&quot;&gt;Manual snapshots&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;User-initiated, persist until you explicitly delete them&lt;&#x2F;li&gt;
&lt;li&gt;Useful before major changes (schema migrations, upgrades)&lt;&#x2F;li&gt;
&lt;li&gt;Can be copied across regions for disaster recovery&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;&#x2F;strong&gt;: Before any risky operation (major version upgrade, schema change), create a manual snapshot. Automated backups might not cover you if the retention period expires.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;RDS vs. NoSQL:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Not all data fits the relational model. &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;amazondynamodb&#x2F;latest&#x2F;developerguide&#x2F;Introduction.html&quot;&gt;Amazon DynamoDB&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; is AWS&#x27;s managed NoSQL database (key-value and document store):&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Feature&lt;&#x2F;th&gt;&lt;th&gt;RDS (SQL)&lt;&#x2F;th&gt;&lt;th&gt;DynamoDB (NoSQL)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Data model&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Tables with fixed schema, relations&lt;&#x2F;td&gt;&lt;td&gt;Key-value &#x2F; JSON documents, flexible schema&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Queries&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Complex SQL (JOINs, aggregations)&lt;&#x2F;td&gt;&lt;td&gt;Simple key lookups, limited querying&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scaling&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Vertical (bigger instance), Read Replicas&lt;&#x2F;td&gt;&lt;td&gt;Horizontal (automatic), virtually unlimited&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Transactions&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Full ACID support&lt;&#x2F;td&gt;&lt;td&gt;Limited transactions (single-item ACID, multi-item with conditions)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Best for&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Complex queries, reporting, traditional apps&lt;&#x2F;td&gt;&lt;td&gt;High-throughput simple queries, IoT, gaming, mobile backends&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pricing&lt;&#x2F;strong&gt;&lt;&#x2F;td&gt;&lt;td&gt;Pay for instance size (even if idle)&lt;&#x2F;td&gt;&lt;td&gt;Pay for storage + read&#x2F;write capacity used&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;&lt;strong&gt;When to use what:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RDS&lt;&#x2F;strong&gt;: You need SQL, complex queries, transactions, existing relational schema, or you&#x27;re migrating from on-premises MySQL&#x2F;PostgreSQL&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;DynamoDB&lt;&#x2F;strong&gt;: Key-value access patterns, need massive scale, unpredictable traffic spikes, single-digit millisecond latency requirements&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Most traditional applications (e-commerce, ERP, content management) use RDS. DynamoDB shines for high-scale, low-latency use cases where you don&#x27;t need complex querying.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-storage.jpg&quot; alt=&quot;cloud storage&quot; title=&quot;cloud storage&quot;&#x2F;&gt;
&lt;h3 id=&quot;observability&quot;&gt;Observability&lt;&#x2F;h3&gt;
&lt;p&gt;Observability = understanding what&#x27;s happening inside your systems. AWS provides &lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;monitoring&#x2F;WhatIsCloudWatch.html&quot;&gt;Amazon CloudWatch&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; as the central service for this.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;monitoring&#x2F;working_with_metrics.html&quot;&gt;Metrics&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Numerical data points over time. AWS services automatically send metrics (CPU usage, network traffic, request counts). You can also publish custom metrics from your applications.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;logs&#x2F;WhatIsCloudWatchLogs.html&quot;&gt;Logs&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Centralized log storage and analysis. Stream logs from EC2, Lambda, containers, or any application. Use &lt;strong&gt;Log Insights&lt;&#x2F;strong&gt; to query across log groups with a SQL-like syntax.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.aws.amazon.com&#x2F;AmazonCloudWatch&#x2F;latest&#x2F;monitoring&#x2F;AlarmThatSendsEmail.html&quot;&gt;Alarms&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Watch metrics and trigger actions when thresholds are breached:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Send notifications via SNS (email, SMS, Slack)&lt;&#x2F;li&gt;
&lt;li&gt;Trigger Auto Scaling to add&#x2F;remove instances&lt;&#x2F;li&gt;
&lt;li&gt;Execute Lambda functions for custom remediation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Example alarm&lt;&#x2F;strong&gt;: &quot;If average CPU &amp;gt; 80% for 5 minutes, add 2 instances and notify the ops team.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Beyond CloudWatch:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;xray&#x2F;&quot;&gt;AWS X-Ray&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Distributed tracing for microservices&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;cloudtrail&#x2F;&quot;&gt;CloudTrail&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Audit log of all API calls in your account&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;cloud-observability.jpg&quot; alt=&quot;cloud observability&quot; title=&quot;cloud observability&quot;&#x2F;&gt;
&lt;br&gt;
&lt;h2 id=&quot;one-picture-is-worth-thousand-words&quot;&gt;One picture is worth thousand words&lt;&#x2F;h2&gt;


&lt;div class=&quot;aws-diagram-wrapper&quot;&gt;
    &lt;style&gt;
        .aws-diagram-wrapper {
            --aws-bg: #0d1117;
            --aws-bg-secondary: #161b22;
            --aws-bg-tertiary: #21262d;
            --aws-border: #30363d;
            --aws-text: #e6edf3;
            --aws-text-muted: #8b949e;
            --aws-orange: #a8895c;
            --aws-green: #6f8a6f;
            --aws-blue: #64788f;
            --aws-blue-light: #8296ab;
            --aws-purple: #9b8fab;
            --aws-yellow: #ab9179;

            font-family: &#x27;IBM Plex Sans&#x27;, -apple-system, BlinkMacSystemFont, &#x27;Segoe UI&#x27;, sans-serif;
            background: var(--aws-bg);
            color: var(--aws-text);
            padding: 40px 20px;
            margin: 30px 0;
        }

        .aws-diagram-wrapper * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .aws-diagram-wrapper h1 {
            font-size: 1.6rem;
            font-weight: 600;
            margin-bottom: 8px;
            color: var(--aws-orange);
        }

        .aws-diagram-wrapper .subtitle {
            color: var(--aws-text-muted);
            font-size: 0.9rem;
            margin-bottom: 40px;
        }

        .aws-diagram-wrapper .diagram-container {
            position: relative;
            background: linear-gradient(180deg, var(--aws-bg-secondary) 0%, var(--aws-bg) 100%);
            border: 1px solid var(--aws-border);
            padding: 30px;
            overflow-x: auto;
        }

        .aws-diagram-wrapper .diagram {
            display: flex;
            flex-direction: column;
            gap: 16px;
            min-width: 1100px;
        }

        .aws-diagram-wrapper .zone {
            border: 2px dashed var(--aws-border);
            padding: 20px;
            position: relative;
        }

        .aws-diagram-wrapper .zone-label {
            position: absolute;
            top: -10px;
            left: 20px;
            background: var(--aws-bg);
            padding: 2px 12px;
            font-size: 0.7rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 1px;
            color: var(--aws-text-muted);
        }

        .aws-diagram-wrapper .zone.internet {
            border-color: var(--aws-green);
            background: rgba(111,138,111, 0.05);
        }

        .aws-diagram-wrapper .zone.vpc {
            border-color: var(--aws-blue);
            background: rgba(100,120,143, 0.03);
        }

        .aws-diagram-wrapper .zone.public-subnet {
            border-color: var(--aws-yellow);
            background: rgba(171,145,121, 0.05);
        }

        .aws-diagram-wrapper .zone.private-subnet {
            border-color: var(--aws-purple);
            background: rgba(155,143,171, 0.05);
        }

        .aws-diagram-wrapper .zone.az {
            border-color: var(--aws-blue-light);
            border-style: dotted;
            background: rgba(130,150,171, 0.03);
        }

        .aws-diagram-wrapper .row {
            display: flex;
            gap: 20px;
            align-items: flex-start;
        }

        .aws-diagram-wrapper .component {
            background: var(--aws-bg-tertiary);
            border: 1px solid var(--aws-border);
            padding: 14px 18px;
            min-width: 130px;
            text-align: center;
            position: relative;
            transition: all 0.2s ease;
            cursor: pointer;
        }

        .aws-diagram-wrapper .component:hover {
            border-color: var(--aws-orange);
            transform: translateY(-2px);
            box-shadow: 0 4px 20px rgba(168,137,92, 0.15);
        }

        .aws-diagram-wrapper .component.active {
            border-color: var(--aws-orange);
            background: #2d333b;
        }

        .aws-diagram-wrapper .component-name {
            font-weight: 600;
            font-size: 0.85rem;
            margin-bottom: 6px;
            color: var(--aws-text);
        }

        .aws-diagram-wrapper .component-type {
            font-family: &#x27;JetBrains Mono&#x27;, &#x27;Fira Code&#x27;, monospace;
            font-size: 0.65rem;
            color: var(--aws-orange);
            background: rgba(168,137,92, 0.1);
            padding: 3px 8px;
            display: inline-block;
        }

        .aws-diagram-wrapper .arrow-container {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 8px 0;
        }

        .aws-diagram-wrapper .arrow {
            display: flex;
            align-items: center;
            gap: 8px;
            color: #6e7681;
            font-size: 0.7rem;
            font-family: &#x27;JetBrains Mono&#x27;, monospace;
        }

        .aws-diagram-wrapper .arrow-line {
            width: 50px;
            height: 2px;
            background: linear-gradient(90deg, var(--aws-border) 0%, var(--aws-orange) 50%, var(--aws-border) 100%);
            position: relative;
        }

        .aws-diagram-wrapper .arrow-line::after {
            content: &#x27;&gt;&#x27;;
            position: absolute;
            right: -6px;
            top: -7px;
            color: var(--aws-orange);
            font-size: 0.7rem;
            font-weight: bold;
        }

        .aws-diagram-wrapper .arrow-down {
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .aws-diagram-wrapper .arrow-down .arrow-line {
            width: 2px;
            height: 30px;
            background: linear-gradient(180deg, var(--aws-border) 0%, var(--aws-orange) 50%, var(--aws-border) 100%);
        }

        .aws-diagram-wrapper .arrow-down .arrow-line::after {
            content: &#x27;v&#x27;;
            right: -5px;
            top: auto;
            bottom: -10px;
            font-size: 0.6rem;
        }

        .aws-diagram-wrapper .flex-center {
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .aws-diagram-wrapper .flex-between {
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
        }

        .aws-diagram-wrapper .flex-col {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
        }

        .aws-diagram-wrapper .info-panel {
            margin-top: 30px;
            background: var(--aws-bg-secondary);
            border: 1px solid var(--aws-border);
            padding: 24px;
            min-height: 180px;
        }

        .aws-diagram-wrapper .info-panel h3 {
            font-size: 1rem;
            color: var(--aws-orange);
            margin-bottom: 12px;
        }

        .aws-diagram-wrapper .info-panel .description {
            color: var(--aws-text-muted);
            line-height: 1.7;
            margin-bottom: 16px;
            font-size: 0.9rem;
        }

        .aws-diagram-wrapper .info-panel .analogy {
            background: var(--aws-bg-tertiary);
            border-left: 3px solid var(--aws-green);
            padding: 12px 16px;
            margin-bottom: 16px;
        }

        .aws-diagram-wrapper .info-panel .analogy-label {
            font-size: 0.65rem;
            text-transform: uppercase;
            letter-spacing: 1px;
            color: var(--aws-green);
            margin-bottom: 6px;
        }

        .aws-diagram-wrapper .info-panel .analogy p {
            font-size: 0.85rem;
            color: var(--aws-text-muted);
        }

        .aws-diagram-wrapper .info-panel .code {
            font-family: &#x27;JetBrains Mono&#x27;, &#x27;Fira Code&#x27;, monospace;
            font-size: 0.75rem;
            background: var(--aws-bg);
            padding: 12px 16px;
            color: #91a7bd;
            overflow-x: auto;
            line-height: 1.5;
        }

        .aws-diagram-wrapper .storage-section {
            display: flex;
            gap: 20px;
            margin-top: 16px;
        }

        .aws-diagram-wrapper .storage-group {
            flex: 1;
            background: var(--aws-bg-secondary);
            border: 1px solid var(--aws-border);
            padding: 16px;
        }

        .aws-diagram-wrapper .storage-group h4 {
            font-size: 0.75rem;
            color: var(--aws-text-muted);
            margin-bottom: 12px;
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .aws-diagram-wrapper .storage-items {
            display: flex;
            gap: 12px;
            flex-wrap: wrap;
        }

        .aws-diagram-wrapper .legend {
            display: flex;
            gap: 24px;
            flex-wrap: wrap;
            margin-top: 20px;
            padding: 14px;
            background: var(--aws-bg-secondary);
        }

        .aws-diagram-wrapper .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.75rem;
            color: var(--aws-text-muted);
        }

        .aws-diagram-wrapper .legend-color {
            width: 14px;
            height: 14px;
            border: 2px dashed;
        }

        .aws-diagram-wrapper .legend-color.internet { border-color: var(--aws-green); background: rgba(111,138,111, 0.2); }
        .aws-diagram-wrapper .legend-color.vpc { border-color: var(--aws-blue); background: rgba(100,120,143, 0.2); }
        .aws-diagram-wrapper .legend-color.public { border-color: var(--aws-yellow); background: rgba(171,145,121, 0.2); }
        .aws-diagram-wrapper .legend-color.private { border-color: var(--aws-purple); background: rgba(155,143,171, 0.2); }

        .aws-diagram-wrapper .click-hint {
            text-align: center;
            color: #6e7681;
            font-size: 0.75rem;
            margin-top: 14px;
        }

        .aws-diagram-wrapper .or-divider {
            font-size: 0.65rem;
            color: #6e7681;
            font-style: italic;
        }
    &lt;&#x2F;style&gt;

    &lt;h1&gt;AWS Architecture - Overview&lt;&#x2F;h1&gt;
    &lt;p class=&quot;subtitle&quot;&gt;Click on a component to see details and analogy with your current stack&lt;&#x2F;p&gt;

    &lt;div class=&quot;diagram-container&quot;&gt;
        &lt;div class=&quot;diagram&quot;&gt;

            &lt;!-- Internet Zone --&gt;
            &lt;div class=&quot;zone internet&quot;&gt;
                &lt;span class=&quot;zone-label&quot;&gt;Internet&lt;&#x2F;span&gt;
                &lt;div class=&quot;flex-center&quot;&gt;
                    &lt;div class=&quot;component&quot; data-component=&quot;users&quot;&gt;
                        &lt;div class=&quot;component-name&quot;&gt;Users&lt;&#x2F;div&gt;
                        &lt;div class=&quot;component-type&quot;&gt;Front &amp; mobile Apps&lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;arrow&quot;&gt;
                        &lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;
                        &lt;span&gt;HTTPS&lt;&#x2F;span&gt;
                        &lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;component&quot; data-component=&quot;route53&quot;&gt;
                        &lt;div class=&quot;component-name&quot;&gt;Route 53&lt;&#x2F;div&gt;
                        &lt;div class=&quot;component-type&quot;&gt;DNS&lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;!-- VPC --&gt;
            &lt;div class=&quot;zone vpc&quot;&gt;
                &lt;span class=&quot;zone-label&quot;&gt;VPC (10.0.0.0&#x2F;16)&lt;&#x2F;span&gt;

                &lt;div class=&quot;flex-between&quot; style=&quot;gap: 20px;&quot;&gt;

                    &lt;!-- AZ 1 --&gt;
                    &lt;div class=&quot;zone az&quot; style=&quot;flex: 1;&quot;&gt;
                        &lt;span class=&quot;zone-label&quot;&gt;AZ-1 (eu-west-3a)&lt;&#x2F;span&gt;

                        &lt;!-- Public Subnet AZ1 --&gt;
                        &lt;div class=&quot;zone public-subnet&quot; style=&quot;margin-bottom: 15px;&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Public Subnet (10.0.1.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;igw&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;Internet Gateway&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;IGW&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;arrow-down&quot;&gt;&lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;alb&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;Load Balancer&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;ALB &#x2F; NLB&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;nat&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;NAT Gateway&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;NAT&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;

                        &lt;!-- Private Subnet AZ1 --&gt;
                        &lt;div class=&quot;zone private-subnet&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Private Subnet (10.0.10.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;ec2&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;EC2 Instance&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;t3.medium&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;or-divider&quot;&gt;or&lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;ecs&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;ECS &#x2F; Fargate&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;Container&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;

                    &lt;!-- AZ 2 --&gt;
                    &lt;div class=&quot;zone az&quot; style=&quot;flex: 1;&quot;&gt;
                        &lt;span class=&quot;zone-label&quot;&gt;AZ-2 (eu-west-3b)&lt;&#x2F;span&gt;

                        &lt;!-- Public Subnet AZ2 --&gt;
                        &lt;div class=&quot;zone public-subnet&quot; style=&quot;margin-bottom: 15px;&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Public Subnet (10.0.2.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;alb&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;Load Balancer&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;ALB (replica)&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;

                        &lt;!-- Private Subnet AZ2 --&gt;
                        &lt;div class=&quot;zone private-subnet&quot;&gt;
                            &lt;span class=&quot;zone-label&quot;&gt;Private Subnet (10.0.20.0&#x2F;24)&lt;&#x2F;span&gt;
                            &lt;div class=&quot;flex-col&quot;&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;ec2&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;EC2 Instance&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;t3.medium&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                                &lt;div class=&quot;arrow-down&quot;&gt;&lt;div class=&quot;arrow-line&quot;&gt;&lt;&#x2F;div&gt;&lt;&#x2F;div&gt;
                                &lt;div class=&quot;component&quot; data-component=&quot;rds&quot;&gt;
                                    &lt;div class=&quot;component-name&quot;&gt;RDS PostgreSQL&lt;&#x2F;div&gt;
                                    &lt;div class=&quot;component-type&quot;&gt;Multi-AZ&lt;&#x2F;div&gt;
                                &lt;&#x2F;div&gt;
                            &lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;

            &lt;!-- Storage &amp; Monitoring --&gt;
            &lt;div class=&quot;storage-section&quot;&gt;
                &lt;div class=&quot;storage-group&quot;&gt;
                    &lt;h4&gt;Storage&lt;&#x2F;h4&gt;
                    &lt;div class=&quot;storage-items&quot;&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;s3&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;S3 Bucket&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Object Storage&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;ebs&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;EBS Volume&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Block Storage&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;efs&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;EFS&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;File System&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
                &lt;div class=&quot;storage-group&quot;&gt;
                    &lt;h4&gt;Monitoring and Streaming&lt;&#x2F;h4&gt;
                    &lt;div class=&quot;storage-items&quot;&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;cloudwatch&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;CloudWatch&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Monitoring&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                        &lt;div class=&quot;component&quot; data-component=&quot;msk&quot;&gt;
                            &lt;div class=&quot;component-name&quot;&gt;MSK (Kafka)&lt;&#x2F;div&gt;
                            &lt;div class=&quot;component-type&quot;&gt;Streaming&lt;&#x2F;div&gt;
                        &lt;&#x2F;div&gt;
                    &lt;&#x2F;div&gt;
                &lt;&#x2F;div&gt;
            &lt;&#x2F;div&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;!-- Legend --&gt;
    &lt;div class=&quot;legend&quot;&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color internet&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;Internet (public access)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color vpc&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;VPC (your private network)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color public&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;Public Subnet (exposed)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
        &lt;div class=&quot;legend-item&quot;&gt;
            &lt;div class=&quot;legend-color private&quot;&gt;&lt;&#x2F;div&gt;
            &lt;span&gt;Private Subnet (protected)&lt;&#x2F;span&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;

    &lt;p class=&quot;click-hint&quot;&gt;Click on a component to see details&lt;&#x2F;p&gt;

    &lt;!-- Info Panel --&gt;
    &lt;div class=&quot;info-panel&quot; id=&quot;aws-info-panel&quot;&gt;
        &lt;h3&gt;Select a component&lt;&#x2F;h3&gt;
        &lt;p class=&quot;description&quot;&gt;
            Click on any element of the diagram to see a detailed explanation
            and the equivalent in your current environment (Nginx, Django, PostgreSQL...).
        &lt;&#x2F;p&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
(function() {
    const componentInfo = {
        users: {
            title: &quot;Users &#x2F; Clients&quot;,
            description: &quot;The users who access your applications from the Internet. This could be health workers using our &lt;a href=&#x27;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&#x27;&gt;syndromic surveillance system&lt;&#x2F;a&gt;.&quot;,
            analogy: &quot;It&#x27;s the same as now - your users typing the URL in their browser or systems calling your REST API.&quot;,
            code: &quot;curl https:&#x2F;&#x2F;surveillance.pasteur.sn&#x2F;api&#x2F;v1&#x2F;cases&#x2F;&quot;
        },
        route53: {
            title: &quot;Route 53 - DNS Service&quot;,
            description: &quot;AWS&#x27;s managed DNS service. It translates domain names (surveillance.pasteur.sn) into IP addresses. Can perform health checking and intelligent routing (geolocation, failover).&quot;,
            analogy: &quot;Equivalent to your current DNS (maybe managed by your registrar or Cloudflare). The difference: Route 53 integrates natively with other AWS services.&quot;,
            code: &quot;# Example record&lt;br&gt;surveillance.pasteur.sn  A  -&gt; ALB (alias)&quot;
        },
        igw: {
            title: &quot;Internet Gateway (IGW)&quot;,
            description: &quot;The gateway in and out of your VPC to the Internet. Without IGW, nothing in your VPC can communicate with the outside world. There is ONE per VPC.&quot;,
            analogy: &quot;It&#x27;s like the router&#x2F;firewall of your datacenter that connects your internal network to the Internet. Like your platform&#x27;s main gateway.&quot;,
            code: &quot;# One VPC = One IGW&lt;br&gt;aws ec2 create-internet-gateway&quot;
        },
        alb: {
            title: &quot;Application Load Balancer (ALB &#x2F; NLB)&quot;,
            description: &quot;Distributes traffic between multiple instances. ALB = Layer 7 (HTTP), understands URLs and can route &#x2F;api to one group, &#x2F;admin to another. NLB = Layer 4 (TCP), faster but less intelligent.&quot;,
            analogy: &quot;It&#x27;s your Nginx in reverse proxy mode, but managed and automatically scalable. No need to manage the nginx.conf file anymore!&quot;,
            code: &quot;# Nginx equivalent&lt;br&gt;upstream django {&lt;br&gt;    server 10.0.10.5:8000;&lt;br&gt;    server 10.0.20.5:8000;&lt;br&gt;}&lt;br&gt;location &#x2F; {&lt;br&gt;    proxy_pass http:&#x2F;&#x2F;django;&lt;br&gt;}&quot;
        },
        nat: {
            title: &quot;NAT Gateway&quot;,
            description: &quot;Allows resources in a PRIVATE subnet to access the Internet (for updates, external APIs) WITHOUT being accessible from the Internet. Outgoing traffic goes through NAT, but no incoming traffic is possible.&quot;,
            analogy: &quot;Like when your Django server (behind a firewall) can do &#x27;pip install&#x27; or call the Africa&#x27;s Talking API, but no one can access that server directly from the Internet.&quot;,
            code: &quot;# From your private EC2, this works:&lt;br&gt;curl https:&#x2F;&#x2F;api.africastalking.com&#x2F;send&lt;br&gt;&lt;br&gt;# But from the Internet, impossible to reach the EC2&quot;
        },
        ec2: {
            title: &quot;EC2 - Elastic Compute Cloud&quot;,
            description: &quot;Virtual machines. You choose the type (t3.medium = 2 vCPU, 4 GB RAM), the OS (Ubuntu, Amazon Linux), and you pay per hour. On Demand = flexible, Reserved = -60%, Spot = -90% but interruptible.&quot;,
            analogy: &quot;It&#x27;s exactly like your current VPS or physical servers, but elastic. You can create 10 in 2 minutes, and delete them afterwards.&quot;,
            code: &quot;# Equivalent to your current server&lt;br&gt;Ubuntu 22.04&lt;br&gt;2 vCPU, 4 GB RAM&lt;br&gt;Django + Gunicorn + your code&quot;
        },
        ecs: {
            title: &quot;ECS &#x2F; EKS &#x2F; Fargate - Containers&quot;,
            description: &quot;ECS = AWS container orchestrator. EKS = Managed Kubernetes. Fargate = serverless (no servers to manage). You package your Django in a Docker image, and AWS handles the rest.&quot;,
            analogy: &quot;If you&#x27;re using Docker now with docker-compose, ECS is the same but in production and scalable. No need to SSH into the server to do &#x27;docker pull&#x27;.&quot;,
            code: &quot;# Dockerfile&lt;br&gt;FROM python:3.11&lt;br&gt;COPY . &#x2F;app&lt;br&gt;RUN pip install -r requirements.txt&lt;br&gt;CMD [\&quot;gunicorn\&quot;, \&quot;config.wsgi:application\&quot;]&quot;
        },
        rds: {
            title: &quot;RDS - Relational Database Service&quot;,
            description: &quot;Managed databases (PostgreSQL, MySQL, etc.). AWS handles automatic backups, security patches, Multi-AZ replication. You focus on your queries, not maintenance.&quot;,
            analogy: &quot;It&#x27;s your current PostgreSQL, but you no longer have to worry about pg_dump, version upgrades, or replication. AWS does everything.&quot;,
            code: &quot;# Django settings.py&lt;br&gt;DATABASES = {&lt;br&gt;    &#x27;default&#x27;: {&lt;br&gt;        &#x27;ENGINE&#x27;: &#x27;django.db.backends.postgresql&#x27;,&lt;br&gt;        &#x27;HOST&#x27;: &#x27;mydb.xxxxx.eu-west-3.rds.amazonaws.com&#x27;,&lt;br&gt;        &#x27;NAME&#x27;: &#x27;surveillance_db&#x27;,&lt;br&gt;    }&lt;br&gt;}&quot;
        },
        s3: {
            title: &quot;S3 - Simple Storage Service&quot;,
            description: &quot;Unlimited object storage. Perfect for static files, backups, media uploads. Not a classic file system (no mkdir), but &#x27;buckets&#x27; and &#x27;objects&#x27; with URLs.&quot;,
            analogy: &quot;Replaces your &#x2F;var&#x2F;www&#x2F;media&#x2F; folder for Django uploads. No more disk space issues, and your files are accessible via URL directly.&quot;,
            code: &quot;# Django settings with django-storages&lt;br&gt;DEFAULT_FILE_STORAGE = &#x27;storages.backends.s3boto3.S3Boto3Storage&#x27;&lt;br&gt;AWS_STORAGE_BUCKET_NAME = &#x27;ipd-surveillance-media&#x27;&quot;
        },
        ebs: {
            title: &quot;EBS - Elastic Block Store&quot;,
            description: &quot;Virtual hard drives attached to an EC2 instance. Like your server&#x27;s SSD. Persistent (data remains even if EC2 is stopped). Different types: gp3 (general), io2 (high perf), st1 (cheap HDD).&quot;,
            analogy: &quot;It&#x27;s exactly your current server&#x27;s hard drive. &#x2F;dev&#x2F;sda1 but in the cloud. If your EC2 dies, you can attach the EBS to a new instance.&quot;,
            code: &quot;# On your EC2&lt;br&gt;df -h&lt;br&gt;&#x2F;dev&#x2F;nvme0n1p1  100G   45G   55G  45% &#x2F;&quot;
        },
        efs: {
            title: &quot;EFS - Elastic File System&quot;,
            description: &quot;File system shared between MULTIPLE EC2 instances. Like a NAS. Useful when multiple servers need to access the same files (ex: shared uploads, common source code).&quot;,
            analogy: &quot;Like an NFS share between your servers. If you have 3 Django instances that all need to see the same uploaded files, EFS solves this problem.&quot;,
            code: &quot;# Mounted on multiple EC2&lt;br&gt;mount -t nfs4 fs-xxxxx.efs.eu-west-3.amazonaws.com:&#x2F; &#x2F;mnt&#x2F;shared&quot;
        },
        cloudwatch: {
            title: &quot;CloudWatch - Monitoring&quot;,
            description: &quot;Collects metrics (CPU, RAM, requests), centralizes logs, and triggers alerts. Built-in dashboard. Can trigger automatic actions (ex: scale up if CPU &gt; 80%).&quot;,
            analogy: &quot;Combines htop + tail -f &#x2F;var&#x2F;log + your alert system. But everything is centralized and you can create visual dashboards.&quot;,
            code: &quot;# Alert example&lt;br&gt;If CPUUtilization &gt; 80% for 5 min&lt;br&gt;-&gt; Send email to ops@pasteur.sn&lt;br&gt;-&gt; Add 2 instances to Auto Scaling Group&quot;
        },
        msk: {
            title: &quot;MSK - Managed Streaming for Kafka&quot;,
            description: &quot;Apache Kafka managed by AWS. For real-time data streaming, data pipelines, or event-driven architecture. Useful for processing millions of events per second.&quot;,
            analogy: &quot;Imagine each suspected case report generates an &#x27;event&#x27; that must be processed in real-time to trigger epidemiological alerts. Kafka enables this continuous flow of data.&quot;,
            code: &quot;# Producer (notification system)&lt;br&gt;producer.send(&#x27;alerts-topic&#x27;, {&lt;br&gt;    &#x27;type&#x27;: &#x27;suspected_case&#x27;,&lt;br&gt;    &#x27;disease&#x27;: &#x27;cholera&#x27;,&lt;br&gt;    &#x27;location&#x27;: &#x27;dakar&#x27;,&lt;br&gt;    &#x27;timestamp&#x27;: &#x27;2025-01-31T10:30:00Z&#x27;&lt;br&gt;})&quot;
        }
    };

    const wrapper = document.querySelector(&#x27;.aws-diagram-wrapper&#x27;);
    const panel = wrapper.querySelector(&#x27;#aws-info-panel&#x27;);

    wrapper.querySelectorAll(&#x27;.component&#x27;).forEach(comp =&gt; {
        comp.addEventListener(&#x27;click&#x27;, function() {
            const componentId = this.dataset.component;
            const info = componentInfo[componentId];

            if (info) {
                wrapper.querySelectorAll(&#x27;.component&#x27;).forEach(c =&gt; c.classList.remove(&#x27;active&#x27;));
                wrapper.querySelectorAll(`[data-component=&quot;${componentId}&quot;]`).forEach(c =&gt; c.classList.add(&#x27;active&#x27;));

                panel.innerHTML = `
                    &lt;h3&gt;${info.title}&lt;&#x2F;h3&gt;
                    &lt;p class=&quot;description&quot;&gt;${info.description}&lt;&#x2F;p&gt;
                    &lt;div class=&quot;analogy&quot;&gt;
                        &lt;div class=&quot;analogy-label&quot;&gt;Equivalent dans ton stack actuel&lt;&#x2F;div&gt;
                        &lt;p&gt;${info.analogy}&lt;&#x2F;p&gt;
                    &lt;&#x2F;div&gt;
                    &lt;div class=&quot;code&quot;&gt;${info.code.replace(&#x2F;\n&#x2F;g, &#x27;&lt;br&gt;&#x27;)}&lt;&#x2F;div&gt;
                `;
            }
        });
    });
})();
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;how-to-practice&quot;&gt;How to practice&lt;&#x2F;h2&gt;
&lt;p&gt;You don&#x27;t need a corporate account to learn AWS:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;free&#x2F;&quot;&gt;AWS Free Tier&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: The real AWS, free for 12 months (with limits). Great for hands-on experience with actual services.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;localstack.cloud&#x2F;&quot;&gt;LocalStack&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: AWS emulator running on your laptop. Spin up S3, Lambda, DynamoDB locally. No cloud costs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;minikube.sigs.k8s.io&#x2F;&quot;&gt;Minikube&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;kind.sigs.k8s.io&#x2F;&quot;&gt;Kind&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Local Kubernetes clusters for learning EKS concepts.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;k3s.io&#x2F;&quot;&gt;K3s&lt;&#x2F;a&gt; &#x2F; &lt;a href=&quot;https:&#x2F;&#x2F;k3d.io&#x2F;&quot;&gt;K3d&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Lightweight Kubernetes distributions, perfect for development and edge deployments.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.podman.io&#x2F;en&#x2F;latest&#x2F;markdown&#x2F;podman-compose.1.html&quot;&gt;Podman Compose&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;: Simulate architectures with containers (PostgreSQL, Redis, Nginx). Understand the concepts before going managed.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;The key insight is this: everything you&#x27;ve been doing manually for years, fingers in the nose, eyes closed (configuring Nginx, Gunicorn, PostgreSQL, managing users, monitoring logs), AWS offers it as managed services. You&#x27;re trading full control for less maintenance.&lt;&#x2F;p&gt;
&lt;p&gt;Is that trade-off worth it? It depends. For a small team that needs to move fast and can&#x27;t afford dedicated ops, managed services make sense. For organizations with specific compliance needs or those who want to avoid vendor lock-in, the calculus changes.&lt;&#x2F;p&gt;
&lt;p&gt;Either way, understanding these concepts matters, whether you end up using AWS, another cloud, or staying on-premises.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;there_is_no_cloud.png&quot; alt=&quot;There is no cloud&quot; title=&quot;There is no cloud&quot;&#x2F;&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic&lt;&#x2F;h2&gt;
&lt;p&gt;Congratulations, you made it to the end. I hope you learned something, if you enjoyed this piece, you can read my post about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;&quot;&gt;how I&#x27;m helping save lives in West Africa using free software&lt;&#x2F;a&gt;, or you can &lt;em&gt;like, share and subscribe; it helps fight the algorithm.&lt;&#x2F;em&gt; Here are some links you may find interesing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=uaflChh3n1A&quot;&gt;Introduction to AWS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;908&#x2F;&quot;&gt;The Cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=MQbkN99eBD8&quot;&gt;Why is Kubernetes everywhere?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;basecamp.com&#x2F;cloud-exit&quot;&gt;We left the cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=vBjonut1JMk&quot;&gt;How Kubernetes is built&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=tCehFMwjWqM&quot;&gt;AI won&#x27;t take your job (but this will)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=CjKhQoYeR4Q&quot;&gt;Getting started with AWS, step by step guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Syndromic Surveillance! (Part 1)</title>
        <published>2025-08-24T00:00:00+00:00</published>
        <updated>2025-08-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/syndromic-surveillance/"/>
        <id>https://nskm.xyz/posts/syndromic-surveillance/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/syndromic-surveillance/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;images&#x2F;surveillance_screens.jpg&quot; alt=&quot;&quot; title=&quot;Liberty&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers :&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Opinions expressed in this post &lt;em&gt;(and in any of all my posts)&lt;&#x2F;em&gt; are solely, &lt;em&gt;unless otherwise specified&lt;&#x2F;em&gt;, those of the authors, &lt;em&gt;me&lt;&#x2F;em&gt;. Those opinions absolutely do not reflect the views, policies, positions of any organizations, employers, affiliated groups.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I&#x27;ve strived for accuracy throughout this piece, but if you catch any errors, please reach out—I&#x27;d be grateful for the feedback and happy to make updates!&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#hook&quot;&gt;Hook&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#history&quot;&gt;Definition, context, history&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#what&quot;&gt;4S overview&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#core&quot;&gt;Core principles&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#collect&quot;&gt;Data collection&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#process&quot;&gt;Data processing and storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#share&quot;&gt;Data sharing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#alert&quot;&gt;Alerting and notifications&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#integration&quot;&gt;Integration with existing systems&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#stack&quot;&gt;The technological stack&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#front&quot;&gt;Frontend&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#back&quot;&gt;Backend&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#else&quot;&gt;More&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#engineers&quot;&gt;The engineering team&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#future&quot;&gt;The roadmap&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;syndromic-surveillance&#x2F;#more&quot;&gt;More on this topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;hook&quot;&gt;&lt;u&gt;Hook:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;From &lt;strong&gt;June 30 to July 2, 2025&lt;&#x2F;strong&gt;, a coordination meeting for the entire 4S network was recently held in &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lom%C3%A9&quot;&gt;Lomé, Togo&lt;&#x2F;a&gt;. During this meeting, a new implementation of the &lt;strong&gt;4S platform&lt;&#x2F;strong&gt; was presented to the participants.&lt;&#x2F;p&gt;
&lt;video style=&quot;display: block; margin: 0 auto; width: 600px&quot; class=&quot;video&quot; controls=&quot;controls&quot; &gt;
  &lt;source  src=&quot;&#x2F;images&#x2F;4s-annual-regional-coordination-meeting.mp4&quot; type=&quot;video&#x2F;mp4&quot; &#x2F;&gt;
  Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;Quote:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Le réseau 4S a été conçu pour répondre à un besoin crucial, celui de disposer d&#x27;un système régional de surveillance capable de détecter précocément les maladies de santé publique, de renforcer les capacités de laboratoires et de partager des données pour une réponse adéquate et adaptée aux problèmes sanitaires.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Quote :&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The 4S network was designed to meet a crucial need: to have a regional surveillance system capable of early detection of public health diseases, strengthening laboratory capacities and sharing data for an adequate and appropriate response to health issues.
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The striking disconnect that exists across many sectors, public health included. Officials excel at announcing initiatives and securing funding. Press releases about &lt;em&gt;&quot;implementing advanced early detection systems&quot;&lt;&#x2F;em&gt; generate buzz and demonstrate progress. But when it comes to the unglamorous technical work: database design, API development, system integration... Silence. These crucial implementation details, handled by &lt;em&gt;anonymous engineers and developers&lt;&#x2F;em&gt;, rarely see daylight in public discourse.&lt;&#x2F;p&gt;
&lt;p&gt;While policy makers avoid technical specifics, it&#x27;s precisely these software choices that determine whether systems function during critical moments.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 250px&quot; src=&quot;&#x2F;images&#x2F;mother.jpg&quot; alt=&quot;Mother&quot; title=&quot;Mother&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;history&quot;&gt;&lt;u&gt;Definition, context, history:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A syndromic surveillance system is a &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Y6DPDC_Mf90&quot;&gt;public health&lt;&#x2F;a&gt; &lt;strong&gt;surveillance&lt;&#x2F;strong&gt; system that monitors &lt;strong&gt;symptom clusters&lt;&#x2F;strong&gt; rather than specific confirmed diagnoses. It aims to &lt;strong&gt;detect epidemics or public health events&lt;&#x2F;strong&gt; at an &lt;strong&gt;early&lt;&#x2F;strong&gt; stage, by analyzing data in real time.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2007&quot;&gt;2007:&lt;&#x2F;h3&gt;
&lt;p&gt;Before 2007, &lt;a href=&quot;https:&#x2F;&#x2F;simple.wikipedia.org&#x2F;wiki&#x2F;Madagascar&quot;&gt;Madagascar&lt;&#x2F;a&gt; only had a passive, monthly paper-based reporting system that was &lt;em&gt;&lt;strong&gt;too slow&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; for outbreak response. The &lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pubmed.ncbi.nlm.nih.gov&#x2F;17505252&#x2F;&quot;&gt;chikungunya outbreak&lt;&#x2F;a&gt;&lt;&#x2F;em&gt; in the Indian Ocean exposed &lt;em&gt;&lt;strong&gt;critical gaps&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; in Madagascar&#x27;s disease surveillance.&lt;&#x2F;p&gt;
&lt;p&gt;The solution was to setup a real-time sentinel surveillance system using mobile phones for daily data transmission. This implementation was &lt;em&gt;&lt;strong&gt;the first nationwide real-time-like&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pdfs.semanticscholar.org&#x2F;66b8&#x2F;8be85954b548c3b744ffd7ea8bac7ccae008.pdf&quot;&gt;surveillance system&lt;&#x2F;a&gt; ever established in Madagascar.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2012&quot;&gt;2012:&lt;&#x2F;h3&gt;
&lt;p&gt;The Syndromic Sentinel Surveillance System in Senegal, the 4S network, is &lt;a href=&quot;https:&#x2F;&#x2F;rh.pasteur.sn&#x2F;en&#x2F;research-and-public-health&#x2F;epidemiology-clinical-research-and-data-science&#x2F;fever-surveillance-syndromic-sentinel-surveillance-senegal-4s-network&quot;&gt;Another syndromic sentinel surveillance system&lt;&#x2F;a&gt; based on febrile syndromes. It was implemented in Senegal in 2012 and inpired by the Madagascar model.&lt;&#x2F;p&gt;
&lt;p&gt;The criteria of individual target diseases are based on &lt;a href=&quot;https:&#x2F;&#x2F;www.who.int&#x2F;publications&#x2F;i&#x2F;item&#x2F;who-recommended-surveillance-standards&quot;&gt;World Health Organization recommended surveillance standards&lt;&#x2F;a&gt;. This means: for &lt;em&gt;each disease&lt;&#x2F;em&gt; or &lt;em&gt;syndrome&lt;&#x2F;em&gt; there is a description of the &lt;em&gt;rationale for surveillance, case definition, types of surveillance, minimum data elements, data analyses and principal uses of data for decision-making.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Data are transmitted on a daily basis by the general practitioners of the sentinel sites. They are validated and analyzed daily within the epidemiology unit of the Institution. These data are sent to the Ministry of Health in the form of a weekly newsletter.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2015&quot;&gt;2015:&lt;&#x2F;h3&gt;
&lt;p&gt;The existing implementation faced significant challenges. The database consisted of scattered Excel files distributed across multiple locations, making studies and analyses complicated and time-consuming. There was an urgent need to organize, structure, and centralize these disparate files.&lt;&#x2F;p&gt;
&lt;p&gt;To address these issues, a new platform was developed: Teranga. Built using &lt;a href=&quot;https:&#x2F;&#x2F;httpd.apache.org&#x2F;&quot;&gt;Apache&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.php.net&#x2F;&quot;&gt;PHP&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;JavaScript&quot;&gt;Javascript&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.mysql.com&#x2F;products&#x2F;community&#x2F;&quot;&gt;MySQL&lt;&#x2F;a&gt;, Teranga provides improved data management, enhanced tracking capabilities, modular architecture, and streamlined deployment during outbreak situations.&lt;&#x2F;p&gt;
&lt;p&gt;The new sentinel surveillance system included 17 health centers and &lt;a href=&quot;https:&#x2F;&#x2F;www.omicsonline.org&#x2F;proceedings&#x2F;early-outbreak-detection-through-sentinel-surveillance-system-in-senegal-51640.html&quot;&gt;identified 4 confirmed outbreaks&lt;&#x2F;a&gt;. The system has proved the feasibility of improving disease surveillance capacity through innovative technological solutions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2020&quot;&gt;2020:&lt;&#x2F;h3&gt;
&lt;p&gt;When &lt;a href=&quot;https:&#x2F;&#x2F;www.cdc.gov&#x2F;covid&#x2F;about&#x2F;index.html&quot;&gt;COVID-19&lt;&#x2F;a&gt; struck, Teranga rose to meet an unprecedented challenge, becoming the backbone of Senegal&#x27;s pandemic response. Seamlessly coordinating patient care, traveler monitoring, financial operations, clinical research, and treatment center management across the entire country. The pandemic trully elevated Teranga to a mission-critical status.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2022&quot;&gt;2022:&lt;&#x2F;h3&gt;
&lt;p&gt;What began as a surveillance system for on institution, evolved to become West Africa indispensable healthcare hub: The 4S network. Teranga is now expanding from Senegal into other West African countries: Gambia, Cape-Verde, Mauritania, Niger, Mali, Togo, Guinea, Guinea Bissau, Sierra-Leone and Benin. The goal being to provide broader coverage and improve health systems in a sustainable and effective manner.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2023&quot;&gt;2023:&lt;&#x2F;h3&gt;
&lt;p&gt;I am hired by the Institution. I&#x27;m tasked with reimplementing the current system, rebuilding it from scratch while improving on what came before. I don&#x27;t have much say in the tech stack, just enough &lt;em&gt;freedom&lt;&#x2F;em&gt; to go with what works for &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;toolbelt&#x2F;&quot;&gt;me&lt;&#x2F;a&gt;. The usual lineup of &lt;a href=&quot;https:&#x2F;&#x2F;www.debian.org&#x2F;&quot;&gt;Debian&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;&quot;&gt;Python&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;&quot;&gt;Postgresql&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.nginx.org&#x2F;&quot;&gt;Nginx&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;podman.io&quot;&gt;Podman&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;Git&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;Emacs&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tmuxcheatsheet.com&#x2F;&quot;&gt;Tmux&lt;&#x2F;a&gt;, etc ... More on that in the following episodes.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2025&quot;&gt;2025:&lt;&#x2F;h3&gt;
&lt;p&gt;The surveillance platform my colleagues and I have spent two years developing has now been presented to the public. But public recognition &lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;vLK4Mq3jiKIAAAAC&#x2F;tenor.gif&quot;&gt;is not really the source of my pride&lt;&#x2F;a&gt;. What matters is that our system, our algorithms, our data structures, our functions, our for loops, our SQL queries are actively making a difference in saving lives. Phew!&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 250px&quot; src=&quot;&#x2F;images&#x2F;wip.jpg&quot; alt=&quot;Work in progress&quot; title=&quot;Work in progress...&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;what&quot;&gt;&lt;u&gt;4S overview:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;identify unusual health events earlier and provide a quicker response.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I can&#x27;t say it better.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;core&quot;&gt;Core principles:&lt;&#x2F;h3&gt;
&lt;p&gt;It&#x27;s really fascinating that these early systems already recognized the core principles we are trying to implement today:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;collect&quot;&gt;1. Standardized data collection:&lt;&#x2F;h4&gt;
&lt;p&gt;Healthcare providers at sentinel sites should use standardized digital forms to capture essential demographic, clinical, and temporal information. We want to ensure consistency across all participating facilities and enable accurate epidemiological analysis. We should always try to adhere to WHO surveillance standards with clearly predefined entities &amp;amp; attributes.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;process&quot;&gt;2. Data processing and storage:&lt;&#x2F;h4&gt;
&lt;p&gt;The platform should handles real-time data streaming between microservices, enabling immediate processing of incoming surveillance data. Each microservice should ensures data integrity through automated validation rules. We should always check for completeness, consistency, and quality. Validated data should be stored in a database with proper indexing for efficient retrieval.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;share&quot;&gt;3. Information sharing:&lt;&#x2F;h4&gt;
&lt;p&gt;The epidemiology unit generates documents consolidating validated surveillance data for the Ministry of Health. The platform integrates with third parties to share aggregated data with the Ministry of Health. The platform also provides interactive dashboards for stakeholders.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;alert&quot;&gt;4. Alerting and notifications:&lt;&#x2F;h4&gt;
&lt;p&gt;The platform should ensure immediate notification delivery to relevant actor via email and dashboard notifications. Whenever needed, the platform should automatically generates notifications through multiple channels—email alerts, in-app notifications, and dashboard warnings.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;integration&quot;&gt;5. Integration with existing systems:&lt;&#x2F;h4&gt;
&lt;p&gt;The platform should seamlessly integrate with the regional health data aggregation system and any other existing platform used by Ministry of Health. The system must also integrate easily with any biobank systems that may exist.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A drawing is worth more than thousand words:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;text&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-text &quot;&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&lt;span&gt;                                        [Health facility]   [Hospital]         [Clinic]
&lt;&#x2F;span&gt;&lt;span&gt;                                              |                 |                  |
&lt;&#x2F;span&gt;&lt;span&gt;                                              |                 |                  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         +----+-----------------+------------------+----+
&lt;&#x2F;span&gt;&lt;span&gt;                                         |              4S platform                     |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data collection (Patients, symptoms, ...)  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data validation &amp;amp; storage                  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data treatment (Analyses, studies, ...)    |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data sharing (Reports, alerts, ...)        |
&lt;&#x2F;span&gt;&lt;span&gt;                                         | • Data dashboards (Statistics, plots, ...)   |
&lt;&#x2F;span&gt;&lt;span&gt;                                         +----+-------------------+-------------+-------+
&lt;&#x2F;span&gt;&lt;span&gt;                                              |                   |             |
&lt;&#x2F;span&gt;&lt;span&gt;                                         +----+----+              |        +----+----+
&lt;&#x2F;span&gt;&lt;span&gt;                                         | Reports |              |        | Alerts  |
&lt;&#x2F;span&gt;&lt;span&gt;                                         |Analytics|              |        |Warnings |
&lt;&#x2F;span&gt;&lt;span&gt;                                         +----+----+              |        +----+----+
&lt;&#x2F;span&gt;&lt;span&gt;                                              |                   |             |
&lt;&#x2F;span&gt;&lt;span&gt;                                              |                   |             |
&lt;&#x2F;span&gt;&lt;span&gt;                                        +-----+---------+   +-----+----+    +---+-------+
&lt;&#x2F;span&gt;&lt;span&gt;                                        | Public Health |   | Research |    | Emergency |
&lt;&#x2F;span&gt;&lt;span&gt;                                        |   Department  |   |          |    | Response  |
&lt;&#x2F;span&gt;&lt;span&gt;                                        +---------------+   +----------+    +-----------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the platform we are trying to build :) I can stop the post here, thanks for reading ...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;stack&quot;&gt;The technological stack:&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;front&quot;&gt;Frontend:&lt;&#x2F;h4&gt;
&lt;p&gt;The 4S platform frontend leverages &lt;a href=&quot;https:&#x2F;&#x2F;angularjs.dev&#x2F;&quot;&gt;AngularJS&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;&quot;&gt;TypeScript&lt;&#x2F;a&gt;, providing a dynamic and type-safe user interface that ensures smooth interactions for healthcare providers.&lt;&#x2F;p&gt;
&lt;p&gt;One of the main component of our architecture is &lt;a href=&quot;https:&#x2F;&#x2F;www.keycloak.org&#x2F;&quot;&gt;Keycloak&lt;&#x2F;a&gt;, an identity &amp;amp; access management solution that handles user authentication, authorization accross the entire platform. Customizing the Django Rest Framework&#x27;s authentication classes to handle different tokens sent by different realms was an adventure worthy of an article.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;back&quot;&gt;Backend:&lt;&#x2F;h4&gt;
&lt;p&gt;The backend infrastructure centers around &lt;a href=&quot;https:&#x2F;&#x2F;python.org&quot;&gt;Python&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;djangoproject.com&quot;&gt;Django&lt;&#x2F;a&gt;, and Django Rest Framework. With each passing day, as we make progress on the project, I become more and more convinced that it was the right choice. Django is an amazing piece of software, thanks a lot to all its contributors.&lt;&#x2F;p&gt;
&lt;p&gt;Data management is handled by &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&quot;&gt;PostgreSQL&lt;&#x2F;a&gt;, our primary database system. I can proudly say that I&#x27;m the one who made this choice. Postgresql is known for its reliability, strong adherence to SQL standards, powerful extensibility, support for complex data types, ACID compliance, robust security features, and excellent community support.&lt;&#x2F;p&gt;
&lt;p&gt;To handle real-time communication and event-driven processes such as email notifications, lab result updates, and system alerts, we&#x27;ve integrated &lt;a href=&quot;https:&#x2F;&#x2F;kafka.apache.org&#x2F;&quot;&gt;Apache Kafka&lt;&#x2F;a&gt;. Kafka ensures that critical healthcare information flows efficiently between different system components without data loss.&lt;&#x2F;p&gt;
&lt;p&gt;In order to detect outbreaks, samples (blood, urine, stool, etc.) must be collected. And to effectively manage vast biological sample collections, ensure data integrity, and streamline complex workflows, we need a Biobank and a Biobanking software. A biobank is essentially an organized library of biological samples (like blood and tissue) that are stored alongside health and personal information, all used to support medical research. &lt;a href=&quot;https:&#x2F;&#x2F;www.modul-bio.com&#x2F;en&#x2F;our-solutions&#x2F;mbiolims&#x2F;&quot;&gt;Mbiolims&lt;&#x2F;a&gt; is the biobanking software we use to manage our samples and their associated data.&lt;&#x2F;p&gt;
&lt;p&gt;Here too, I would need to write a really long article telling you how we&#x27;ve managed to do the integration between Django and MBioLIMS :) Hehe!&lt;&#x2F;p&gt;
&lt;h4 id=&quot;ops&quot;&gt;Operations:&lt;&#x2F;h4&gt;
&lt;p&gt;All code versioning and collaboration is managed through &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&quot;&gt;Git&lt;&#x2F;a&gt; &amp;amp; Bitbucket, ensuring secure source code management, proper access controls and audit trails. While Bitbucket provides comprehensive version control and collaboration features, I&#x27;m still convinced it was not the right choice. &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt; ? &lt;a href=&quot;https:&#x2F;&#x2F;about.gitea.com&#x2F;&quot;&gt;Gitea&lt;&#x2F;a&gt; ? Github ? Come on!&lt;&#x2F;p&gt;
&lt;p&gt;The 4S platform is in fact a constallation of multiple running containers. Those containers are built using Docker and &lt;a href=&quot;https:&#x2F;&#x2F;podman.io&quot;&gt;Podman&lt;&#x2F;a&gt; technologies, enabling consistent deployment across different environments while simplifying development and testing workflows. I mean, I&#x27;m the only one using Podman while all my teammates are still using Docker :\&lt;&#x2F;p&gt;
&lt;p&gt;Our continuous integration and deployment pipeline is powered by Jenkins. Jenkins automates testing and deployment processes to maintain code quality and enable rapid, reliable updates. I prefer &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ci&#x2F;&quot;&gt;GitlabCI&lt;&#x2F;a&gt; by 13 parsecs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes&lt;&#x2F;a&gt; is used for container orchestration, deployment and operations. K8s provides automatic scaling, load balancing, and high availability to ensure our platform can handle varying loads and maintain uptime. My opinions on this tool are mixed.&lt;&#x2F;p&gt;
&lt;p&gt;In one side, K8s will allow us to easily scale our applications up or down based on demand. This is a critical requirement for managing sensitive healthcare information. In the other side, I live in a part of the world where most medical facilities (most people, let&#x27;s be honest) do not even have a working domain name, website, and email address. How can we ask them for the DevOps expertise to manage a Kubernetes cluster? I will see to what extent I can write an article about Kubernetes.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;else&quot;&gt;Even more:&lt;&#x2F;h4&gt;
&lt;p&gt;There are other essential components of the system which I am not really familiar with.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dhis2.org&#x2F;&quot;&gt;DHIS2&lt;&#x2F;a&gt; is widely adopted across West Africa for integrated health information systems, disease surveillance, education management, and public health emergency response. We simply cannot ask a country that already uses DHIS2 to use the 4S platform without it being able to transfer data back to a DHIS2 instance.&lt;&#x2F;p&gt;
&lt;p&gt;We have an &lt;a href=&quot;https:&#x2F;&#x2F;superset.apache.org&#x2F;&quot;&gt;Apache Superset&lt;&#x2F;a&gt; instance for data visualization and exploration. With Apache Superset, we can easily let a third party consult some information, without modifying our system.&lt;&#x2F;p&gt;
&lt;p&gt;Our platform generate lots of files, analysis reports &amp;amp; statistics. We needed something to store vast amounts of unstructured data, like images, videos, pdf documents, etc... We choosed &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;minio&#x2F;minio&quot;&gt;MinIO&lt;&#x2F;a&gt; for this use case.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;The diagram we&#x27;ve seen above can also be seen using this different perspective:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;    +-----------------------------------------------------------------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    |                                                      KUBERNETES CLUSTER                                               |
&lt;&#x2F;span&gt;&lt;span&gt;    +-----------------------------------------------------------------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    |                                                                                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;    |  +--------------------------------------------------+   &amp;lt;-- (Auth&#x2F;Roles) --&amp;gt;  +------------------+                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |             FRONTEND CLIENTS                     |------------------------&amp;gt;|     KEYCLOAK     |                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |          (AngularJS + TypeScript)                |&amp;lt;------------------------|   (Auth Server   |                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |  +------------------^-------------------------------+                         +-----^------------+                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |                     |                                                               |                                 |
&lt;&#x2F;span&gt;&lt;span&gt;    |              (API Requests)                                                         | (Auth&#x2F;Roles)                    |
&lt;&#x2F;span&gt;&lt;span&gt;    |                     |                                                          +----+                                 |
&lt;&#x2F;span&gt;&lt;span&gt;    |                     |                                                          |                                      |
&lt;&#x2F;span&gt;&lt;span&gt;    +---------------------v----------------------------------------------------------v--------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    |  +--------------------------------------------------------------------------------+      +--------------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |                BACKEND MICROSERVICES (Django Rest Framework)                   |      |    Biobank (Mbiolims)    | |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |      Microservices exchanges data via a message broker (Kafka in our case)     |&amp;lt;----&amp;gt;|   Stores Samples infos   | |
&lt;&#x2F;span&gt;&lt;span&gt;    |  |   [Microservice A]  &amp;lt;--Data--&amp;gt;  [Microservice B] &amp;lt;--Data--&amp;gt; [Microservice N-1] |      |                          | |
&lt;&#x2F;span&gt;&lt;span&gt;    |  +-------------------------^-----------------------^-------------------------^----+      +--------------------------+ |
&lt;&#x2F;span&gt;&lt;span&gt;    |                            |                       |                         |                                        |
&lt;&#x2F;span&gt;&lt;span&gt;    |              (Store&#x2F;Retrieve)       (Write&#x2F;Open Files)      (Sends data aggregations)                                 |
&lt;&#x2F;span&gt;&lt;span&gt;    |                            |                       |                         |                                        |
&lt;&#x2F;span&gt;&lt;span&gt;    +----------------------------v-----------------------v-------------------------v----------------------------------------+
&lt;&#x2F;span&gt;&lt;span&gt;    | +--------------------------------+ +--------------------------------+ +--------------------------------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;    | |        POSTGRESQL DB           | |             MINIO              | |                   DHIS2                    |  |
&lt;&#x2F;span&gt;&lt;span&gt;    | |     (Primary Data Store)       | |      (Object&#x2F;File Storage)     | |           (External Data Recipient)        |  |
&lt;&#x2F;span&gt;&lt;span&gt;    | +--------------------------------+ +--------------------------------+ +--------------------------------------------+  |
&lt;&#x2F;span&gt;&lt;span&gt;    |               | (Reads Data)                                                                                          |
&lt;&#x2F;span&gt;&lt;span&gt;    |               |                                                                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;    | +-------------v--------------------+                                                                                  |
&lt;&#x2F;span&gt;&lt;span&gt;    | |    APACHE SUPERSET (Dataviz)     |                                                                                  |
&lt;&#x2F;span&gt;&lt;span&gt;    | +----------------------------------+                                                                                  |
&lt;&#x2F;span&gt;&lt;span&gt;    |                                                                                                                       |
&lt;&#x2F;span&gt;&lt;span&gt;    +-----------------------------------------------------------------------------------------------------------------------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h3 id=&quot;engineers&quot;&gt;The engineering team:&lt;&#x2F;h3&gt;
&lt;p&gt;This article is also for my fellow developers who built the 4S network under impossible constraints—limited budgets, legacy infrastructure, unrealistic timelines. My colleagues engineers writing scripts to detect disease patterns, configuring servers that never get enough resources. My teammates who&#x27;s written documentation that nobody reads but everyone depends on. I&#x27;m talking about the people who made the story:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;cisse&quot;&gt;Cisse:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mamadou-cisse-723b29114&#x2F;&quot;&gt;Cisse&lt;&#x2F;a&gt; a.k.a &quot;Celui qui fait bouger le monde&quot;, plays a crucial role in coordinating activities across the Institution Digital Factory team. His expertise extends to managing and preserving the integrity of biomedical data within the Institution. He works closely with stakeholders to validate specifications of new health applications. To uncover more about him, follow this &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mamadou-cisse-723b29114&#x2F;&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;mame-astou&quot;&gt;Mame Astou:&lt;&#x2F;h4&gt;
&lt;p&gt;As an integral member of the development team, &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&quot;&gt;Mame Astou&lt;&#x2F;a&gt; a.k.a &quot;Madame La Directrice&quot;, craft robust and dynamic web applications while maintaining a keen eye for intuitive user interface design. She knows how to create user experiences that prioritize both aesthetic appeal and seamless usability. What would we be without her? Absolutely nothing. To uncover more about her, please visit this &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mameastougassama&quot;&gt;page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;diom&quot;&gt;Diom:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.doyoubuzz.com&#x2F;diom-sow&quot;&gt;Diom&lt;&#x2F;a&gt;, a.k.a &quot;Le Grand Marabout de l&#x27;Architecture&quot;, is a DevOps engineer who bridges the gap between development and operations. With expertise in containerization technologies, cloud platforms, and monitoring solutions, he design and maintain scalable deployment environments while ensuring system reliability and security.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;abdoul-karim&quot;&gt;Abdoul Karim:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;Abdoul Karim&lt;&#x2F;a&gt; is probably the pillar of the team, always ready to make concessions and take responsibility. His technical experience spans multiple domains. It would take me hours to explain why he is an excellent engineer. Just go and find out by yourself how great &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;mohamed-abdoul-karim-diop-76250b127&#x2F;&quot;&gt;he is&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;mariama&quot;&gt;Mariama:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;#&quot;&gt;Mariama&lt;&#x2F;a&gt; a.k.a &quot;La Sauveuse De Tous Les Hommes&quot;, has a deep knowledge of Scrum and agile principles. She guide the team through iterative development cycles while fostering continuous improvement and team collaboration. We are still waiting for that one day she will finally write a few lines of TypeScript. Access Mariama&#x27;s comprehensive profile by following this &lt;a href=&quot;#&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;birante&quot;&gt;Birante:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fr.linkedin.com&#x2F;in&#x2F;birantesy&quot;&gt;Birante&lt;&#x2F;a&gt; has an exceptional expertise that encompasses everything from custom UI animations and state management to integrating native device features and third-party services. He is able to deliver native-quality experiences across both iOS, Android and Web platforms. He secretly dreams about rewriting all the 4s platform using &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=gcwzWzC7gUA&quot;&gt;RoR&lt;&#x2F;a&gt; applications. Here is a &lt;a href=&quot;#&quot;&gt;link&lt;&#x2F;a&gt; to get the complete picture about Birante.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;tidiane&quot;&gt;Tidiane:&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;adtidiane&quot;&gt;Tidiane&lt;&#x2F;a&gt;, a.k.a &quot;Le Sage&quot;, a.k.a &quot;The Biobank expert&quot;, is probably the wisest and most reserved member of the team. Tidiane is a seasoned backend developer who brings deep expertise in Django framework development. He excel at designing robust APIs and implementing complex business logic that powers modern web applications. If you know anyone who works at &lt;a href=&quot;https:&#x2F;&#x2F;www.modul-bio.com&quot;&gt;Mbiolims&lt;&#x2F;a&gt;, please tell them they should hire Tidiane. His background can be found &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;amadou-tidiane-diallo-61065a41&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;adrien&quot;&gt;Adrien:&lt;&#x2F;h4&gt;
&lt;p&gt;Aux âmes bien nées, la valeur n&#x27;attend point le nombre d&#x27;années. &lt;a href=&quot;#&quot;&gt;Adrien&lt;&#x2F;a&gt;, the youngest in the team, is a software engineer with an extensive experience in developing RESTful APIs, managing database migrations, and implementing automated testing frameworks within Django projects. For additional information about Adrien, visit this &lt;a href=&quot;#&quot;&gt;link&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Guys, your dedication, your resilience, your ingenuity deserve recognition far beyond what they receive.
Thank you.&lt;&#x2F;strong&gt;
&lt;br&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;future&quot;&gt;The roadmap:&lt;&#x2F;h3&gt;
&lt;p&gt;Right now we&#x27;re developing comprehensive features related to &lt;strong&gt;&quot;case management&quot;&lt;&#x2F;strong&gt;. Those features will enable healthcare providers to track patient journeys from initial consultation through treatment completion, ensuring continuity of care and improved outcomes.&lt;&#x2F;p&gt;
&lt;p&gt;We plan to extend our platform to handle a &lt;strong&gt;wider spectrum of medical conditions and syndromes&lt;&#x2F;strong&gt;, transforming it from a specialized tool into a comprehensive healthcare management solution.&lt;&#x2F;p&gt;
&lt;p&gt;Our platform will also align with the &lt;strong&gt;One Health approach&lt;&#x2F;strong&gt;, recognizing the interconnection between human, animal, and environmental health.&lt;&#x2F;p&gt;
&lt;p&gt;Data exchange with other healthcare systems, electronic health records, and medical devices, is something we need to work towards. We really need to meet evolving healthcare standards and prepare for international expansion. While I agree we didn&#x27;t put enough efforts on this, compliance and interoperability remain central to our development strategy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more&quot;&gt;&lt;u&gt;More on the topic:&lt;&#x2F;u&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Writing about 4S implementation could fill volumes. For those ready to dig deeper into the technical and policy dimensions of public health surveillance, &lt;em&gt;and before I write the second part of this series&lt;&#x2F;em&gt;, here are resources that expand on the key concepts discussed:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;healthsites-io&#x2F;cartographie-des-donn%C3%A9es-sanitaires-durgence-au-s%C3%A9n%C3%A9gal-474c3c3bec29&quot;&gt;Mapping emergency health data in Senegal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Z8pa6BQN54w&quot;&gt;How CARE transforms outbreaks into opportunities for Africa&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cZfzP3J2VxY&quot;&gt;A new way to fight infectious diseases and predict outbreaks&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stories.theglobalfund.org&#x2F;early-detection-for-rapid-response-strengthening-disease-surveillance-across-west-africa&quot;&gt;Early detection for rapid response: strengthening disease surveillance across West Africa&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;institutpasteurdakar.sn&#x2F;strengthening-epidemic-resilience-through-one-health-and-integrated-community-based-surveillance&#x2F;&quot;&gt;Strengthening epidemic resilience through one health and integrated community-based surveillance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kaikai.dev&#x2F;blog&#x2F;blog-1&#x2F;ihe-for-senegal-a-look-back-at-the-ihe-training-week-6&quot;&gt;Launch and training on medical data exchange in Senegal according to IHE standards&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=pmiQza2kQmE&quot;&gt;Dengue sylvatique : l’angle mort du diagnostic — Dr Idrissa Dieng&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some people we might want to collaborate with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;data.humdata.org&#x2F;&quot;&gt;the Humanitarian Data Exchange&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;healthsites.io&#x2F;&quot;&gt;HealthSites.IO, I&#x27;ve contributed Python code for them&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eyone.net&#x2F;en&#x2F;about-us&quot;&gt;Eyone, improving the quality of medical care through technology.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;njureel.com&#x2F;#accueil&quot;&gt;Njureel,  reinventing the proximity between healthcare professionals and patients&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.geomatica.space&#x2F;&quot;&gt;Geomatica, one of the greatest company in geospatial data (The founder is a very good friend)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I hope you learned something. If you found this article interesting, please share it &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=K0HSD_i2DvA&quot;&gt;around the world&lt;&#x2F;a&gt;. Tell them there are people here who save lives with free and open source software.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 250px&quot; src=&quot;&#x2F;images&#x2F;sample.jpg&quot; alt=&quot;&quot; title=&quot;Sample container&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Free and Open Source Software.... Again!</title>
        <published>2025-05-31T00:00:00+00:00</published>
        <updated>2025-05-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/fossa/"/>
        <id>https://nskm.xyz/posts/fossa/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/fossa/">  &lt;img style=&quot;display: block; margin: 0 auto; width: 400px&quot; src=&quot;&#x2F;images&#x2F;liberty.jpg&quot; alt=&quot;&quot; title=&quot;Liberty&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;table-of-content&quot;&gt;Table Of Content:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#1&quot;&gt;1 Intro &lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#4&quot;&gt;2. Why contribute&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#13&quot;&gt;3. Skepticism&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#14&quot;&gt;4. How to contribute&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#15&quot;&gt;5. Success stories&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fossa&#x2F;#16&quot;&gt;6. More on the topic&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;1&quot;&gt;Intro&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m tired of seeing that the majority of Africans still don&#x27;t &lt;a href=&quot;#&quot;&gt;get it&lt;&#x2F;a&gt;, and probably never will, that free and open source software represents the optimal path forward for our continent. &lt;a href=&quot;https:&#x2F;&#x2F;roylab.xyz&#x2F;&quot;&gt;One of&lt;&#x2F;a&gt; my brightest students asked me to talk about free and open source software, and gave me 2 hours to do so. For him, for Africa, for the future, &lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;h2M4FDyKANQAAAAC&#x2F;tenor.gif&quot;&gt;here I am&lt;&#x2F;a&gt;...&lt;&#x2F;p&gt;
&lt;p&gt;IT&#x27;s been almost 20 years I see myself as a &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;SubscriberLink&#x2F;1023299&#x2F;7ba649b1ede41895&#x2F;&quot;&gt;free software&lt;&#x2F;a&gt; advocate, therefore my perspectives are inherently biased. Hopefully, the bias is not huge. Let&#x27;s cue the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=UAs9-VL66vo&quot;&gt;music&lt;&#x2F;a&gt; please!&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2&quot;&gt;&lt;ins&gt;&lt;em&gt;Free software:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The Free software movement, as defined by the &lt;a href=&quot;https:&#x2F;&#x2F;www.fsf.org&#x2F;&quot;&gt;Free Software Foundation&lt;&#x2F;a&gt;, is a social&#x2F;political movement about freedom, ethics, and user rights&#x2F;freedoms. Richard Stallman created the movement in 1983 and the &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;philosophy&#x2F;free-sw.html#four-freedoms&quot;&gt;4 essential user freedoms are&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Freedom to run the program for any purpose&lt;&#x2F;li&gt;
&lt;li&gt;Freedom to study how the program works and change it&lt;&#x2F;li&gt;
&lt;li&gt;Freedom to redistribute copies to help others&lt;&#x2F;li&gt;
&lt;li&gt;Freedom to distribute modified versions to benefit the community&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;3&quot;&gt;&lt;ins&gt;&lt;em&gt;Open source software:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The term &quot;open source&quot; was coined to rebrand free software with a business-friendly focus. It emphasizes practical benefits like better quality, reliability, and development methodology rather than ethical considerations. Bruce Perens created the &lt;a href=&quot;https:&#x2F;&#x2F;opensource.org&#x2F;&quot;&gt;Open Source Initiative&lt;&#x2F;a&gt; in 1998 and Open source criteria include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Source code must be available&lt;&#x2F;li&gt;
&lt;li&gt;Free redistribution&lt;&#x2F;li&gt;
&lt;li&gt;Derived works allowed&lt;&#x2F;li&gt;
&lt;li&gt;No discrimination against groups or fields of use&lt;&#x2F;li&gt;
&lt;li&gt;License must not restrict other software&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If we read these &lt;em&gt;two definitions&lt;&#x2F;em&gt; calmly, we can see that there is a very important nuance that should be made here: &lt;strong&gt;the user freedom and independence&lt;&#x2F;strong&gt; is at the center of everything for a free software advocate. This is not necessarily the case for an open source advocate.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;4&quot;&gt;Why contribute:&lt;&#x2F;h2&gt;
&lt;p&gt;Here are compelling reasons why African people should fully embrace Free and Open Source software :&lt;&#x2F;p&gt;
&lt;h3 id=&quot;5&quot;&gt;&lt;ins&gt;&lt;em&gt;Learning:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Free and Open Source Software often attract talented developers. When your code get reviewed by maintainers at companies around the globe, you receive mentorship that money can&#x27;t buy. You&#x27;ll encounter diverse codebases, architectural patterns, problem-solving approaches that you might never see in your day job. Free and Open Source Software forces you to read and understand existing code, which dramatically improves your development skills.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;6&quot;&gt;&lt;ins&gt;&lt;em&gt;Economic opportunities:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Open source contributions can help you land jobs or consulting opportunities. There are many companies worldwide are actively seeking talents. Open source provides the perfect &lt;a href=&quot;https:&#x2F;&#x2F;www.wearedevelopers.com&#x2F;world-congress&#x2F;github-open-source-spotlight&quot;&gt;showcase&lt;&#x2F;a&gt; of your &lt;a href=&quot;https:&#x2F;&#x2F;events.linuxfoundation.org&#x2F;open-source-summit-europe&#x2F;&quot;&gt;abilities&lt;&#x2F;a&gt;. Open source software is often the most accessible option for people with limited budgets. There are a lot of startups across the Black Continent that rely on free and open source solutions to build their digital infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;We often talk about &lt;a href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;about&#x2F;development-model&quot;&gt;RedHat&lt;&#x2F;a&gt;, but there are many other companies like: &lt;a href=&quot;https:&#x2F;&#x2F;www.zdnet.com&#x2F;article&#x2F;open-source-is-getting-bigger-and-richer-says-suse&#x2F;&quot;&gt;Suse&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;blog&#x2F;monetizing-and-being-open-source&#x2F;&quot;&gt;Gitlab&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=13774420&quot;&gt;Docker&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;nextcloud.com&#x2F;about&#x2F;&quot;&gt;NextCloud&lt;&#x2F;a&gt;, companies that demonstrate various and successful approaches built on free and open source foundations.&lt;&#x2F;p&gt;
&lt;p&gt;In a nutshell, those companies will offer subscriptions and services for a guaranteed support, security updates, patches, custom implementations, customizations, optimizations, trainings, certifications, consulting, ...&lt;&#x2F;p&gt;
&lt;p&gt;I would like to do a special mention for 2 companies: &lt;a href=&quot;https:&#x2F;&#x2F;www.entrouvert.com&#x2F;expertise&#x2F;logiciels-reellement-libres&#x2F;&quot;&gt;Entr&#x27;Ouvert&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.fr&#x2F;societe&quot;&gt;Logilab&lt;&#x2F;a&gt;. They offer implementations, customizations, trainings, and consulting services exclusively with free software, you can see it &lt;a href=&quot;https:&#x2F;&#x2F;dev.entrouvert.org&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;explore&quot;&gt;there&lt;&#x2F;a&gt;. They have a deep expertise in the free software industry and this expertise became a valuable service to their clients. Also, I have very good friends over there, shoutout o&#x2F;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;7&quot;&gt;&lt;ins&gt;&lt;em&gt;Breaking geographic barriers:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Thanks to Free and Open Source Software, your code quality matters more than your location or background. African developers can showcase their skills on the same &lt;a href=&quot;https:&#x2F;&#x2F;github.com&quot;&gt;platforms&lt;&#x2F;a&gt; as Silicon Valley engineers. Free and Open Source is our opportunity for challenging stereotypes and demonstrating our technical talent to the world.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;78&quot;&gt;&lt;ins&gt;&lt;em&gt;Gaming:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Linux was once held back by its compatibility with PC games, but thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.valvesoftware.com&quot;&gt;Valve&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;steamos&#x2F;&quot;&gt;SteamOS&lt;&#x2F;a&gt;, those days are in the past. Better gaming performance, better battery life, better power management, are &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=CJXp3UYj50Q&quot;&gt;another reasons&lt;&#x2F;a&gt; to use Linux.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;8&quot;&gt;&lt;ins&gt;&lt;em&gt;Community:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The open source community represents humanity at its best, a global network where people freely exchange expertise and genuinely celebrate one another&#x27;s wins. When you realize your contribution has solved someone&#x27;s problem or saved them hours of work, that feeling is pure gold. Belonging to a community, building &lt;a href=&quot;https:&#x2F;&#x2F;www.thesocialcreatures.org&#x2F;thecreaturetimes&#x2F;evolution-of-social-connection&quot;&gt;social connections&lt;&#x2F;a&gt; is essential to our wellbeing, it is as important as food, water and shelter.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;9&quot;&gt;&lt;ins&gt;&lt;em&gt;Digital sovereignty:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2307.01791&quot;&gt;Digital sovereignty&lt;&#x2F;a&gt; encompasses control over critical digital infrastructure like internet networks, data centers, communication systems and mobile&#x2F;web platforms. Digital sovereignty is the ability to regulate how &lt;em&gt;our&lt;&#x2F;em&gt; data is collected, stored, and processed within &lt;em&gt;our&lt;&#x2F;em&gt; jurisdiction.&lt;&#x2F;p&gt;
&lt;p&gt;What happens when a country&#x27;s government systems, banking infrastructure, or communication networks depend entirely on software and services controlled by foreign companies. This is where free and open source software becomes crucial for digital sovereignty.&lt;&#x2F;p&gt;
&lt;p&gt;When you use non free and non open source software:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you&#x27;re dependent on the vendor&#x27;s decisions, pricing, and continued support.&lt;&#x2F;li&gt;
&lt;li&gt;you can&#x27;t see how it works, modify it for your needs, or ensure it doesn&#x27;t contain &lt;a href=&quot;https:&#x2F;&#x2F;cyberlaw.ccdcoe.org&#x2F;wiki&#x2F;African_Union_headquarters_hack_(2018)&quot;&gt;backdoors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;you &lt;a href=&quot;https:&#x2F;&#x2F;www.dw.com&#x2F;en&#x2F;will-meta-lawsuits-shape-africas-data-privacy-laws&#x2F;a-72567105&quot;&gt;lose the right to determine how your data is used&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;10&quot;&gt;&lt;ins&gt;&lt;em&gt;The others are moving&lt;&#x2F;em&gt;:&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;publiccode.eu&#x2F;en&#x2F;&quot;&gt;Public money, public code&lt;&#x2F;a&gt; an initiative advocating that software developed with public funds should be made freely available under a free and open-source license.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;code.gouv.fr&#x2F;fr&#x2F;&quot;&gt;Pôle open source et communs numériques&lt;&#x2F;a&gt;, Initiative to support government administrations in using free and open source software, assist their efforts to publish and share source code, and create connections with the open source ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;blog.documentfoundation.org&#x2F;blog&#x2F;2024&#x2F;04&#x2F;04&#x2F;german-state-moving-30000-pcs-to-libreoffice&#x2F;&quot;&gt;The German federal state&lt;&#x2F;a&gt; has decided to move from Microsoft Windows and Microsoft Office to Linux and LibreOffice (and other free and open source software) on the 30,000 PCs used in the local government.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eu-os.eu&#x2F;&quot;&gt;EU OS&lt;&#x2F;a&gt;, a proof-of-concept for an Operating System for a typical organization inside the European Union public sector.&lt;&#x2F;p&gt;
&lt;p&gt;To move away from dependence on US software solutions and acquire genuine digital sovereignty, the &lt;a href=&quot;https:&#x2F;&#x2F;www.lyon.fr&#x2F;actualite&#x2F;action-municipale&#x2F;la-ville-de-lyon-renforce-sa-souverainete-numerique&quot;&gt;City of Lyon&lt;&#x2F;a&gt; has embarked on a major transformation of its digital tools.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;At this point, I don&#x27;t even know what else should I say to convince you...&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.zdnet.com&#x2F;article&#x2F;why-denmark-is-dumping-microsoft-office-and-windows-for-libreoffice-and-linux&#x2F;&quot;&gt;Denmark&lt;&#x2F;a&gt; is transitioning away from Microsoft products in a key ministry due to a strategy focused on digital sovereignty and reducing reliance on foreign, particularly US-based, tech giants. This involves replacing Windows and Office 365 with open-source alternatives like Linux and LibreOffice.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;economictimes.indiatimes.com&#x2F;news&#x2F;international&#x2F;us&#x2F;after-danish-cities-germanys-schleswig-holstein-state-government-to-ban-microsoft-programs-at-work&#x2F;articleshow&#x2F;121833653.cms&quot;&gt;Schleswig-Holstein state&lt;&#x2F;a&gt; government is shifting completely to free and open source software, aiming to achieve what officials call &quot;digital sovereignty&quot; and to reduce reliance on U.S.-based tech giants [...] This isn’t just about software. It&#x27;s about control over sensitive data.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;11&quot;&gt;&lt;ins&gt;&lt;em&gt;You&#x27;re already consuming:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If you&#x27;ve ever used &lt;a href=&quot;https:&#x2F;&#x2F;opensource.google&#x2F;&quot;&gt;Google&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;opensource.fb.com&#x2F;&quot;&gt;Facebook&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;whatsapp&quot;&gt;WhatsApp&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;opensource.microsoft.com&#x2F;&quot;&gt;Microsoft&lt;&#x2F;a&gt; or watched a &lt;a href=&quot;https:&#x2F;&#x2F;netflix.github.io&#x2F;&quot;&gt;Netflix&lt;&#x2F;a&gt; movie today, you&#x27;ve been relying on free and open source software without even knowing it. These tech giants don&#x27;t reinvent the wheel, they build their services on top of thousands of open source projects. None of those things would exist without free and open source software.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;13&quot;&gt;Skepticism:&lt;&#x2F;h2&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 300px&quot; src=&quot;&#x2F;images&#x2F;skeptic.jpg&quot; alt=&quot;skeptical&quot; title=&quot;If free software is so great, why do I get the feeling that no one uses it?&quot;&#x2F;&gt;
&lt;p&gt;Technological proficiency is important, but &lt;strong&gt;correctly managing the cultural&lt;&#x2F;strong&gt; shift required to embrace free and open source software is also very important. There are a number of &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5GXGdavLu6Y&quot;&gt;complex reasons&lt;&#x2F;a&gt; why mass adoption of free and open software has not yet taken place in Africa.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cultural-resistance-and-habits&quot;&gt;&lt;ins&gt;&lt;em&gt;Cultural resistance and habits:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Users are used to the interfaces and workflows of proprietary software. Change naturally generates resistance, especially when the benefits are not immediately perceptible to the end-user.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;institutional-inertia&quot;&gt;&lt;ins&gt;&lt;em&gt;Institutional inertia:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Public and private organizations are often prisoners of their past technological choices. Migrating complex systems requires massive investment in training, data migration and process adaptation. This &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;shorts&#x2F;7RXK-nR83f4&quot;&gt;vendor lock-in&lt;&#x2F;a&gt; is particularly strong in public administration.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;perception-of-complexity-and-support&quot;&gt;&lt;ins&gt;&lt;em&gt;Perception of complexity and support:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In my humble opinion, this perception no longer corresponds to current reality. Yet, many still consider free and open source software to be more technical and less user-friendly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lobbying-and-political-influence&quot;&gt;&lt;ins&gt;&lt;em&gt;Lobbying and political influence:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Large technology companies exert considerable &lt;a href=&quot;https:&#x2F;&#x2F;corporateeurope.org&#x2F;en&#x2F;2023&#x2F;09&#x2F;lobbying-power-amazon-google-and-co-continues-grow&quot;&gt;influence&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.lbc.co.uk&#x2F;world-news&#x2F;british-icc-chief-prosecutor-lost-email-bank-accounts-frozen-trump-sanctions&#x2F;&quot;&gt;pressure&lt;&#x2F;a&gt; on political decisions and public procurement, hindering the adoption of alternative solutions.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;economic-reasons&quot;&gt;&lt;ins&gt;&lt;em&gt;Economic reasons:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Business models built around proprietary software generate huge revenues. Companies like Microsoft, Adobe or Oracle have built entire ecosystems that create mutual financial dependency. To change would represent considerable transition costs and a loss of revenue for many players.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;to-go-even-deeper-on-this-subject&quot;&gt;&lt;ins&gt;&lt;em&gt;To go even deeper on this subject:&lt;&#x2F;em&gt;&lt;&#x2F;ins&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Here is a really interesting &lt;a href=&quot;https:&#x2F;&#x2F;papers.ssrn.com&#x2F;sol3&#x2F;papers.cfm?abstract_id=3138085&quot;&gt;study&lt;&#x2F;a&gt;, intitled &lt;strong&gt;&lt;em&gt;Adoption Barriers of Open-Source Software: A Systematic Review&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; and led by &lt;a href=&quot;https:&#x2F;&#x2F;papers.ssrn.com&#x2F;sol3&#x2F;cf_dev&#x2F;AbsByAuth.cfm?per_id=2321721&quot;&gt;Dmitrij Petrov&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;https:&#x2F;&#x2F;papers.ssrn.com&#x2F;sol3&#x2F;cf_dev&#x2F;AbsByAuth.cfm?per_id=2544892&quot;&gt;Nikolaus Obwegeser&lt;&#x2F;a&gt;. A study that tried to find all the significant barriers that hinder the wider adoption of Free and Open source software. Have been found 19 high-level factors that challenge or inhibit the adoption of FLOSS in various contexts. Long story short....&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 900px&quot; src=&quot;&#x2F;images&#x2F;adoption_barriers_of_foss.png&quot; alt=&quot;&quot; title=&quot;Barriers of FOSS&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;14&quot;&gt;How to contribute:&lt;&#x2F;h2&gt;
&lt;p&gt;There are so many &lt;a href=&quot;https:&#x2F;&#x2F;contribute.cncf.io&#x2F;contributors&#x2F;getting-started&#x2F;&quot;&gt;ways&lt;&#x2F;a&gt; to &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;get-started&#x2F;exploring-projects-on-github&#x2F;finding-ways-to-contribute-to-open-source-on-github&quot;&gt;contribute&lt;&#x2F;a&gt; to free and open source software. There are so many &lt;a href=&quot;https:&#x2F;&#x2F;www.freecodecamp.org&#x2F;news&#x2F;how-to-contribute-to-open-source-projects-beginners-guide&#x2F;#:~:text=Adding%20a%20description%20to%20a,the%20project%27s%20work%20folder%20correctly.&quot;&gt;articles&lt;&#x2F;a&gt;, so many &lt;a href=&quot;https:&#x2F;&#x2F;opensource.guide&#x2F;how-to-contribute&#x2F;&quot;&gt;guides&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;opensauced&#x2F;how-i-got-hired-contributing-to-open-source-projects-546i&quot;&gt;tutorials&lt;&#x2F;a&gt;. The choice is &lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;resources&#x2F;articles&#x2F;how-to-contribute-to-open-source&quot;&gt;yours&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you really want me to answer the question, this is more or less how it should be done (on top of my head).&lt;&#x2F;p&gt;
&lt;h4 id=&quot;0-contribution-types&quot;&gt;0. Contribution types:&lt;&#x2F;h4&gt;
&lt;p&gt;There are several ways you can contribute to free and open source projects.&lt;&#x2F;p&gt;
&lt;p&gt;Bug fixes involve addressing opened issues, improving error handling, and resolving technical problems that users have encountered. Feature contributions include adding new functionality, enhancing user experience and interface design, and optimizing performance to make applications run more efficiently.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;diataxis.fr&#x2F;&quot;&gt;Documentation&lt;&#x2F;a&gt; improvements focus on enhancing readability, adding helpful examples and tutorials, providing translations for broader accessibility, and fixing typos or grammatical errors.&lt;&#x2F;p&gt;
&lt;p&gt;The last contribution type I would like to talk about is funding. Funding through &lt;a href=&quot;https:&#x2F;&#x2F;my.fsf.org&#x2F;join&quot;&gt;donating&lt;&#x2F;a&gt; or direct &lt;a href=&quot;https:&#x2F;&#x2F;palletsprojects.com&#x2F;donate&quot;&gt;sponsoring&lt;&#x2F;a&gt; can provide crucial financial support to help free and open source projects continue their development.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-tips&quot;&gt;1. Tips:&lt;&#x2F;h4&gt;
&lt;p&gt;Before diving into contributions, it&#x27;s essential to read the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;main&#x2F;CONTRIBUTING.rst&quot;&gt;CONTRIBUTING.md&lt;&#x2F;a&gt; file or any other available documentation to understand the project&#x27;s specific guidelines and processes.&lt;&#x2F;p&gt;
&lt;p&gt;Starting small with simple fixes like correcting typos or &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;numpy&#x2F;numpy&#x2F;issues&#x2F;29258&quot;&gt;improving documentation&lt;&#x2F;a&gt; can be incredibly valuable and help you get familiar with the contribution workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Remember to be patient during the review process, as &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;pull&#x2F;19565&quot;&gt;reviews&lt;&#x2F;a&gt; are conducted by human beings who need time to thoroughly examine your work. Don&#x27;t hesitate to ask &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=5k0ndcJiECo&quot;&gt;questions&lt;&#x2F;a&gt; when you&#x27;re stuck, and feel free to ask even more &lt;a href=&quot;https:&#x2F;&#x2F;palletsprojects.com&#x2F;contributing&#x2F;questions&quot;&gt;questions&lt;&#x2F;a&gt; to clarify requirements or processes.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s also important to focus on making one logical change per Pull Request to keep your contributions clear and manageable for reviewers.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-discover-explore&quot;&gt;2. Discover &amp;amp; explore:&lt;&#x2F;h4&gt;
&lt;p&gt;Begin your open source journey by &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;firstcontributions&#x2F;first-contributions&quot;&gt;finding&lt;&#x2F;a&gt; a project that you &lt;strong&gt;actively use&lt;&#x2F;strong&gt; or &lt;strong&gt;genuinely care about&lt;&#x2F;strong&gt;, as this personal connection will help sustain your &lt;strong&gt;motivation&lt;&#x2F;strong&gt;. Take time to thoroughly read the project&#x27;s documentation and contributing guidelines to understand how the community operates and what standards they maintain. Browse through the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;numpy&#x2F;numpy&#x2F;issues&quot;&gt;project&#x27;s issues&lt;&#x2F;a&gt; section, paying special attention to those tagged with &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jazzband&#x2F;django-silk&#x2F;issues?q=is%3Aissue%20state%3Aopen%20label%3A%22good%20first%20issue%22&quot;&gt;&quot;good first issue&quot;&lt;&#x2F;a&gt; or &quot;beginner&quot; labels, as these are specifically designed to help newcomers get started with meaningful contributions.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;3-setup-your-environment&quot;&gt;3. Setup your environment:&lt;&#x2F;h4&gt;
&lt;p&gt;Getting started with development requires setting up your workspace properly. First, &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;pull-requests&#x2F;collaborating-with-pull-requests&#x2F;working-with-forks&#x2F;fork-a-repo&quot;&gt;fork&lt;&#x2F;a&gt; the repository to create your own copy of the project. Next, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-clone&quot;&gt;clone&lt;&#x2F;a&gt; this forked repository to your local machine where you can make changes and test your work.&lt;&#x2F;p&gt;
&lt;p&gt;Take time to set up the development environment according to the project&#x27;s instructions, which may involve &lt;a href=&quot;#&quot;&gt;installing&lt;&#x2F;a&gt; specific dependencies or configuring tools. Run any available &lt;a href=&quot;#&quot;&gt;unit tests&lt;&#x2F;a&gt; to ensure everything is working correctly in your setup, as this confirms your environment is properly configured. Finally, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-switch&quot;&gt;create a new branch&lt;&#x2F;a&gt; for your work to keep your changes organized and separate from the main codebase.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;4-make-your-contribution&quot;&gt;4. Make your contribution:&lt;&#x2F;h4&gt;
&lt;p&gt;When working on your contribution, it&#x27;s crucial to follow the project&#x27;s established &lt;a href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0008&#x2F;&quot;&gt;coding style and conventions&lt;&#x2F;a&gt; to maintain consistency across the codebase. Focus on writing your code, fixing bugs, or adding features while keeping the project&#x27;s standards and best practices in mind. Remember to update &lt;a href=&quot;#&quot;&gt;documentation&lt;&#x2F;a&gt; whenever your changes affect how users or developers interact with the project. Additionally, add or update &lt;a href=&quot;#&quot;&gt;tests&lt;&#x2F;a&gt; to cover your changes, ensuring that new functionality works as expected and that bug fixes prevent regression.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;5-test-prepare&quot;&gt;5. Test &amp;amp; prepare&lt;&#x2F;h4&gt;
&lt;p&gt;Before submitting your work, thoroughly &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;tree&#x2F;main&#x2F;tests&quot;&gt;test&lt;&#x2F;a&gt; your changes by running tests locally to catch any issues early in the process. Carefully review your changes to ensure they meet the project&#x27;s quality standards and actually solve the intended problem.&lt;&#x2F;p&gt;
&lt;p&gt;Write clear, &lt;a href=&quot;https:&#x2F;&#x2F;www.conventionalcommits.org&#x2F;en&#x2F;v1.0.0&#x2F;&quot;&gt;descriptive commit messages&lt;&#x2F;a&gt; that explain what your changes do and why they were necessary, as this helps maintainers understand your contribution. Double-check your work against the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;internals&#x2F;contributing&#x2F;&quot;&gt;contributing guide&lt;&#x2F;a&gt; to make sure you&#x27;ve followed all the project&#x27;s requirements and conventions.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;6-submit-your-work&quot;&gt;6. Submit your work&lt;&#x2F;h4&gt;
&lt;p&gt;Once your contribution is ready, &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-push&quot;&gt;push&lt;&#x2F;a&gt; your branch to your forked repository to make it available for review. Create a &lt;a href=&quot;https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;pull-requests&#x2F;collaborating-with-pull-requests&#x2F;proposing-changes-to-your-work-with-pull-requests&#x2F;about-pull-requests&quot;&gt;Pull Request&lt;&#x2F;a&gt; from your branch to the original project&#x27;s main branch, providing a clear pathway for your changes to be reviewed and potentially merged.&lt;&#x2F;p&gt;
&lt;p&gt;Fill out the PR template with detailed information about what your changes do, why they&#x27;re needed, and how they&#x27;ve been tested. If your contribution addresses specific issues, link those related issues in your PR description to provide context and help maintainers track the resolution of reported problems.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;7-collaborate-refine&quot;&gt;7. Collaborate &amp;amp; refine&lt;&#x2F;h4&gt;
&lt;p&gt;After submitting your Pull Request, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;healthsites&#x2F;healthsites&#x2F;pulls?q=+is%3Apr+author%3Alemeteore+&quot;&gt;actively engage with the review process&lt;&#x2F;a&gt; by responding promptly and thoughtfully to code review feedback from maintainers and other contributors. Make any requested changes to address concerns or suggestions, treating each piece of feedback as an opportunity to improve your contribution and learn from experienced developers.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout this process, engage in discussions &lt;strong&gt;respectfully and professionally&lt;&#x2F;strong&gt;, remembering that constructive feedback is meant to help improve the project rather than criticize your work personally. Pay attention to any failing CI checks and address them promptly, as these automated tests help ensure your changes don&#x27;t break existing functionality.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;8-merge-celebrate&quot;&gt;8. Merge &amp;amp; celebrate:&lt;&#x2F;h4&gt;
&lt;p&gt;Your contribution gets merged into the main project, congratulations 🎉. This marks a significant achievement in your open source journey. You&#x27;re now officially a project contributor, joining a community of developers who have helped shape and improve the software. Most importantly, your code now helps users worldwide, potentially solving problems, adding useful features, or improving the experience for countless people who rely on the project.&lt;&#x2F;p&gt;
&lt;p&gt;Here is an &lt;a href=&quot;https:&#x2F;&#x2F;www.cncf.io&#x2F;blog&#x2F;2023&#x2F;04&#x2F;03&#x2F;outlining-the-structure-of-your-open-source-software-project&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; discussing, among other things, the tasks that are needed to be taken care of for different sizes of the open source project. We see that the bigger the project, the more ways there are to contribute.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;15&quot;&gt;Success stories:&lt;&#x2F;h2&gt;
&lt;p&gt;After &lt;a href=&quot;https:&#x2F;&#x2F;x.com&#x2F;fossfa&quot;&gt;searching&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.crunchbase.com&#x2F;organization&#x2F;fossfa&quot;&gt;very&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;FOSSFA&quot;&gt;extensively&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.instagram.com&#x2F;fossfa&#x2F;&quot;&gt;everywhere&lt;&#x2F;a&gt; on the internet, I found no &lt;strong&gt;current&lt;&#x2F;strong&gt; organizations in Africa, that even remotely resembles the Free Software Foundation.&lt;&#x2F;p&gt;
&lt;p&gt;If you find interesting (and recent) informations about free and open source software initiaves&#x2F;organizations in Africa, if you are in one way or another, linked to an active Linux User Group in Africa, please, if you know any African initiative&#x2F;organization that promotes free and open source software in Africa, please let me know. I&#x27;ll be glad to update the article.&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 500px&quot; src=&quot;&#x2F;images&#x2F;open-source-contributions.jpg&quot; alt=&quot;&quot; title=&quot;Hopefully, you won&#x27;t leave! Because we need your help!&quot;&#x2F;&gt;
&lt;h2 id=&quot;16&quot;&gt;More on the topic:&lt;&#x2F;h2&gt;
&lt;p&gt;We could easily spend days on this topic! Since we only have two hours, here are some excellent resources to continue your journey into this fascinating subject.&lt;&#x2F;p&gt;
&lt;p&gt;In french:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Ef8jkpJEDVc&quot;&gt;La liberté du logiciel expliquée en moins de 3 min!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Xazuo7Rva2Y&quot;&gt;Se lancer dans l&#x27;open source à 100% (et en vivre !)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=JWJmFTcH1Bw&quot;&gt;Le logiciel libre comme levier de souveraineté&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=YQTEq9BRefo&quot;&gt;Open Source: Comprendre, Contribuer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=y4AjuV0O3wo&quot;&gt;Comment devenir un contributeur Open Source ?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8U80yLOZLp4&quot;&gt;Open source &amp;amp; logiciel libre&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In english:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=PVD1LNDxOnc&quot;&gt;Open Source explained&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opensource.guide&#x2F;how-to-contribute&#x2F;&quot;&gt;How to contribute to Open Source&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;resources&#x2F;articles&#x2F;how-to-contribute-to-open-source&quot;&gt;How to contribute to Open Source, a step by step guide&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;philosophy&#x2F;open-source-misses-the-point.en.html&quot;&gt;Why Open Source misses the point of Free Software&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;1013776&#x2F;&quot;&gt;Lessons from open source in the Mexican government&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s be optimistic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;livingopensource.org&#x2F;the-rise-of-open-source-software-in-africa-current-trends-and-futureprospects&#x2F;&quot;&gt;The rise of Open Source software in Africa: current trends and future prospects&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.africantechroundup.com&#x2F;open-source-proprietary-software-african-tech-round-up&#x2F;&quot;&gt;Open Source vs proprietary software: what is best for Africa?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.ictworks.org&#x2F;digital-colonialism-african-software-development&#x2F;&quot;&gt;How to break digital colonialism in African software development&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.universityworldnews.com&#x2F;post.php?story=20241203094802197&quot;&gt;Ten university teams worked on open-source operating system&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By the way...:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Free Software Foundation (FSF) &lt;a href=&quot;https:&#x2F;&#x2F;www.fsf.org&#x2F;fsf40&quot;&gt;turns forty&lt;&#x2F;a&gt; this year&lt;&#x2F;li&gt;
&lt;li&gt;PyCon Africa and PyConZA are &lt;a href=&quot;https:&#x2F;&#x2F;za.pycon.org&#x2F;&quot;&gt;joining forces!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;2025.djangocon.africa&#x2F;&quot;&gt;DjangoCon Africa&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Co-locating &lt;a href=&quot;https:&#x2F;&#x2F;discourse.ubuntu.com&#x2F;t&#x2F;ubucon-africa-djangocon-africa-2025&#x2F;59940&quot;&gt;the 1st UbuCon Africa with the passionate Django community!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;oshwa.org&#x2F;about&#x2F;&quot;&gt;The Open Source Hardware Association&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Framework &lt;a href=&quot;https:&#x2F;&#x2F;frame.work&#x2F;about&quot;&gt;electronics are open to repair and upgrade&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In the next few weeks, I will publish findings regarding the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ssssss&#x2F;&quot;&gt;Syndromic Surveillance System&lt;&#x2F;a&gt; I&#x27;m currently working on. Expect a detailed writeup showing exactly how free and open source software is driving a positive change to the West Africa&#x27;s public health infrastructure. Stay tuned...&lt;&#x2F;p&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 200px&quot; src=&quot;&#x2F;images&#x2F;stay_tuned.gif&quot; alt=&quot;&quot; title=&quot;stay tuned&quot;&#x2F;&gt;
&lt;p&gt;Thanks for sharing!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>C Pointers</title>
        <published>2024-06-18T00:00:00+00:00</published>
        <updated>2024-06-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/ptrs/"/>
        <id>https://nskm.xyz/posts/ptrs/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/ptrs/">&lt;p&gt;In my &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;&quot;&gt;last&lt;&#x2F;a&gt; post, I&#x27;ve written about lots of things but not about C pointers. I thought the topic deserves a post in itself because it&#x27;s one of the most important features of the C language.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with some &lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=24ntpKNiUMs&quot;&gt;music&lt;&#x2F;a&gt; please.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 550px&quot; src=&quot;&#x2F;assets&#x2F;pointers.png&quot; alt=&quot;C Pointers&quot; title=&quot;C Pointers&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#i&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#d&quot;&gt;Declaration &amp;amp; initialization&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#o&quot;&gt;Operators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#u&quot;&gt;Use cases&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#a&quot;&gt;Arrays &amp;amp; strings manipulation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#p&quot;&gt;Pass by reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#m&quot;&gt;Memory allocation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#s&quot;&gt;Data structure implementation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#f&quot;&gt;Functions pointers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#h&quot;&gt;Hardware interface&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;ptrs&#x2F;#g&quot;&gt;Going further&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;i&quot;&gt;Introduction:&lt;&#x2F;h2&gt;
&lt;p&gt;A pointer is a variable that contains the memory address of another variable. A pointer allows
us to &lt;em&gt;indirectly&lt;&#x2F;em&gt; access and manipulate the value of the variable that is pointed to. Like other variables, C pointers have a type.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img
    style=&quot;display: block; margin: 0 auto; width: 600px&quot;
    src=&quot;&#x2F;assets&#x2F;pointers_repr.png&quot;
    alt=&quot;Pointers&quot;
    title=&quot;Pointers&quot;&#x2F;&gt;&lt;&#x2F;p&gt;
  &lt;center&gt;
    &lt;a href=&quot;https:&#x2F;&#x2F;codeforwin.org&quot;&gt;Source&lt;&#x2F;a&gt;
  &lt;&#x2F;center&gt;
&lt;h2 id=&quot;d&quot;&gt;Declaration and initialization:&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; bar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;83&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int *&lt;&#x2F;span&gt;&lt;span&gt;ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;foo;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Pointer variable, type int, receives the address of foo variable*
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int **&lt;&#x2F;span&gt;&lt;span&gt;ptrptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;ptr; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; pointer to a pointer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptr is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, and ptr is pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptrptr is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; &amp;amp; ptrptr is pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptrptr, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo after modification via ptr: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;ptrptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of foo after modification via ptr to ptr: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, foo);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;bar;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptr is now: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, and ptr is now pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value of ptrptr, still: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; &amp;amp; ptrptr is now pointing to: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%p&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptrptr, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void *&lt;&#x2F;span&gt;&lt;span&gt;)ptr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And the output of the previous program is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;Value of foo: 42
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptr is: 0x7ffc6155fd60, and ptr is pointing to: 42
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptrptr is: 0x7ffc6155fd68 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;ptrptr is pointing to: 0x7ffc6155fd60
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Value of foo after modification via ptr: 12
&lt;&#x2F;span&gt;&lt;span&gt;Value of foo after modification via ptr to ptr: 13
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptr is now: 0x7ffc6155fd64, and ptr is now pointing to: 83
&lt;&#x2F;span&gt;&lt;span&gt;Value of ptrptr, still: 0x7ffc6155fd68 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;ptrptr is now pointing to: 0x7ffc6155fd64
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;o&quot;&gt;C pointer operators:&lt;&#x2F;h2&gt;
&lt;p&gt;C offers operators for pointer manipulation:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Address-of operator (&amp;amp;): to return the memory address of a variable&lt;&#x2F;li&gt;
&lt;li&gt;Dereference operator (*): to access the value stored at the memory address pointed to&lt;&#x2F;li&gt;
&lt;li&gt;Arithmetic operators: to perform arithmetic operations on C pointers, addition (+), subtraction (-), increment (++), and decrement (--)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;u&quot;&gt;Use cases for C pointers:&lt;&#x2F;h2&gt;
&lt;p&gt;All modern programming languages have pointers in some form or other. Pointers are used everywhere there is a program, even when we don&#x27;t see them. Let&#x27;s explore some of those use cases.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a&quot;&gt;Manipulating array and string elements:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers can be used to access and manipulate elements in arrays and strings. C Pointers provide a way to efficiently iterate over arrays and perform operations on each item of the sequence.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int *&lt;&#x2F;span&gt;&lt;span&gt;aptr = arr;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print items of the sequence using array indices
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, arr[i]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print elements of the array using pointer
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;aptr);
&lt;&#x2F;span&gt;&lt;span&gt;  aptr++;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print items of the sequence using pointer arithmetic
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and the fact that arr is actually a pointer to the first item of the arr
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;arr+i);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; an array of characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; str[] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world from West Africa&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;sptr = str; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a pointer to the first element of the array
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(i &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; while i is less than 28, print the character at i-th index 
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str[i]);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; increment i to go to the next index
&lt;&#x2F;span&gt;&lt;span&gt;  i++;
&lt;&#x2F;span&gt;&lt;span&gt; }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; while the value that is pointed to is different from the &amp;quot;\0&amp;quot; character
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sptr != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; print the char
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sptr);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; increment pointer (to go to the next character)
&lt;&#x2F;span&gt;&lt;span&gt;  sptr = sptr + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; m = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(m &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;28&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; str is actually a pointer to the first item of the object
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; so str+m is the address of the m-ieth item of the object
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;(str+m));
&lt;&#x2F;span&gt;&lt;span&gt;  m++;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; array of pointers to characters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;names[] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Alice&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bob&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Charlie&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;David&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Emma&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Pointer to the first element of the first element of the array of strings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char **&lt;&#x2F;span&gt;&lt;span&gt;ptr_names = names; 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; j = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; j &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; j++) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Print elements of the array of strings using indices
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, names[j]);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; x = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; x &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;; x++) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Print the element currently pointed to
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ptr_names);
&lt;&#x2F;span&gt;&lt;span&gt;  ptr_names = ptr_names + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;p&quot;&gt;Passing arguments by reference:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers can be used to pass arguments by reference to functions, allowing the function to modify the value of the original variable. This is particularly useful in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;working with large data structures&lt;&#x2F;li&gt;
&lt;li&gt;you need to modify the value of a variable in a function&lt;&#x2F;li&gt;
&lt;li&gt;you need to optimize code by reducing the number of copies of data that need to be made&lt;&#x2F;li&gt;
&lt;li&gt;you need to return more than one value&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s suppose this is a laaaaaarge struct
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; id;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; salary;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Employee&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;update_employee(Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;emp) {
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;salary *= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.1&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; 10% raise
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; We create the large structure once
&lt;&#x2F;span&gt;&lt;span&gt;  Employee e1 = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;John Doe&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5000&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e1.name, e1.salary);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; We pass the large structure by reference
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; to avoid the overhead of copying the entire structure.
&lt;&#x2F;span&gt;&lt;span&gt;  update_employee(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;e1);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee after update: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e1.name, e1.salary);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;m&quot;&gt;Allocating memory:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers are also used to allocate memory dynamically at run-time using functions like &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;malloc.3.html&quot;&gt;malloc()&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;calloc.3p.html&quot;&gt;calloc()&lt;&#x2F;a&gt;, and &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;realloc.3p.html&quot;&gt;realloc()&lt;&#x2F;a&gt;. Examples:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a huuuuuuuge structure
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; id;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; salary;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Employee&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; thanks to pointer &amp;amp; to malloc,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; we can create the structure inside the create_employee function
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and use the structure even after the function goes out of scope
&lt;&#x2F;span&gt;&lt;span&gt;Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;create_employee(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Allocate memory space on heap, size should be the same as width of Employee struct
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Allocate a pointer on stack,
&lt;&#x2F;span&gt;&lt;span&gt;  Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; e2 = malloc(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(Employee));
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; always verify the allocation worked fine
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(e2 == nullptr) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Memory allocation failed!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the ptr e2 contains the value of the memory address of the struct that is on the heap  
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; e2;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;init_employee(Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;emp, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;id, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const char* &lt;&#x2F;span&gt;&lt;span&gt;name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float &lt;&#x2F;span&gt;&lt;span&gt;salary) {
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;id = id;
&lt;&#x2F;span&gt;&lt;span&gt;  strcpy(emp-&amp;gt;name, name);
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;salary = salary;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;update_employee(Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;* &lt;&#x2F;span&gt;&lt;span&gt;emp) {
&lt;&#x2F;span&gt;&lt;span&gt;  emp-&amp;gt;salary *= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.1&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; 10% raise
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Employee&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; e2 = create_employee();
&lt;&#x2F;span&gt;&lt;span&gt;  init_employee(e2, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nsukami Patrick&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6000&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e2-&amp;gt;name, e2-&amp;gt;salary);
&lt;&#x2F;span&gt;&lt;span&gt;  update_employee(e2);
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Employee after update: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, Salary: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, e2-&amp;gt;name, e2-&amp;gt;salary);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; never forget to free the allocated memory
&lt;&#x2F;span&gt;&lt;span&gt;  free(e2);
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;s&quot;&gt;Implementing data structures:&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a href=&quot;#&quot;&gt;Linked lists&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Stacks&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Queues&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Trees&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Graphs&lt;&#x2F;a&gt; and many other data structures are implemented using C Pointers. Example:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;f&quot;&gt;Calling functions:&lt;&#x2F;h3&gt;
&lt;p&gt;A function pointer, is a pointer which point to the memory address of a function instead of pointing to the address of a data object. They are used to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;store functions in data structures&lt;&#x2F;li&gt;
&lt;li&gt;pass functions as arguments to other functions&lt;&#x2F;li&gt;
&lt;li&gt;call functions dynamically at runtime&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here are some &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;fp&#x2F;&quot;&gt;examples&lt;&#x2F;a&gt; on how to use function pointers in C.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;h&quot;&gt;Interfacing with hardware:&lt;&#x2F;h3&gt;
&lt;p&gt;C Pointers are often used in low-level programming to interact with hardware devices and memory-mapped registers. They provide a way to access specific memory addresses and manipulate hardware directly. This part goes way beyond what my brain is able to understand. Hopefully, I&#x27;ll be able to show you an example in another article.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;g&quot;&gt;Going further:&lt;&#x2F;h2&gt;
&lt;p&gt;To learn more about C pointers, we recommend the following &lt;strong&gt;pointers&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;i.imgur.com&#x2F;SIN2jJm.png&quot;&gt;0x7ffc6155fd68&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pointer_(dog_breed)&quot;&gt;0x7ffc6155fd69&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pointer_(computer_programming)&quot;&gt;0x7ffc6155fd70&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;playlist?list=PLdo5W4Nhv31a8UcMN9-35ghv8qyFWD9_S&quot;&gt;0x7ffc6155fd71&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;setleds.1.html&quot;&gt;0x7ffc6155fd72&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.adafruit.com&#x2F;product&#x2F;2264&quot;&gt;0x7ffc6155fd73&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 550px&quot; src=&quot;&#x2F;assets&#x2F;ptrs.jpg&quot; alt=&quot;Pointers&quot; title=&quot;Pointers&quot;&#x2F;&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>C</title>
        <published>2023-09-25T00:00:00+00:00</published>
        <updated>2023-09-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/cp/"/>
        <id>https://nskm.xyz/posts/cp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/cp/">&lt;p&gt;I spent some time adding &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.fr&#x2F;blogentry&#x2F;13884378&quot;&gt;type annotations&lt;&#x2F;a&gt; to some Python code. Shoutout to all the people at &lt;a href=&quot;https:&#x2F;&#x2F;logilab.fr&quot;&gt;Logilab&lt;&#x2F;a&gt;, a really awesome team doing really awesome things. All those type annotations made me more and more interested in static typing... and in C programming.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Target audience&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: people who already have an experience with programming. People who may have written some C programs in the past and who want to refresh their memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Context&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;: I&#x27;m working on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I&#x27;m working on &lt;code&gt;Linux 5.13.0-52-generic #59-Ubuntu SMP Wed Jun 15 20:17:13 UTC 2022 x86_64&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;And I&#x27;m using &lt;code&gt;GCC (Ubuntu 11.2.0-7ubuntu2) 11.2.0&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=6YSNKq-6SjM&quot;&gt;Music please&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;assets&#x2F;force.jpg&quot; alt=&quot;Force&quot; title=&quot;Force&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h2 id=&quot;toc&quot;&gt;ToC&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#setup&quot;&gt;Setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#primitive&quot;&gt;Primitive types&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#integers&quot;&gt;integers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#floats&quot;&gt;floats&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#bool&quot;&gt;booleans&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#void&quot;&gt;void&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#composite&quot;&gt;Composite types&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#structs&quot;&gt;structs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#enums&quot;&gt;enums&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#unions&quot;&gt;unions&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#arrays&quot;&gt;arrays&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#strings&quot;&gt;strings&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;cp&#x2F;#constants&quot;&gt;Constants&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;The setup:&lt;&#x2F;h2&gt;
&lt;p&gt;To write C programs, we need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;a href=&quot;#&quot;&gt;operating system&lt;&#x2F;a&gt; that respect your freedom and privacy.&lt;&#x2F;li&gt;
&lt;li&gt;A C compiler such as &lt;a href=&quot;https:&#x2F;&#x2F;gcc.gnu.org&#x2F;&quot;&gt;gcc&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;&quot;&gt;clang&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;text editor&lt;&#x2F;a&gt; that &lt;a href=&quot;&#x2F;images&#x2F;trollface.jpg&#x2F;&quot;&gt;&lt;em&gt;respects&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; your freedom and privacy.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) a Bash script to generate the project &lt;a href=&quot;&#x2F;snips&#x2F;scfldc&#x2F;&quot;&gt;boilerplate&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;(Optional) a &lt;a href=&quot;&#x2F;snips&#x2F;scfldc&#x2F;&quot;&gt;Makefile&lt;&#x2F;a&gt; to format, build, install and run the program quickly.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h2 id=&quot;types&quot;&gt;Types:&lt;&#x2F;h2&gt;
&lt;p&gt;Variable, a named location in the computer&#x27;s memory where data can be stored and accessed. Type, define the size, the format, the behavior, the operations that can be performed on the variable. Let&#x27;s talk about the common types in C programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;primitive&quot;&gt;Primitive types:&lt;&#x2F;h2&gt;
&lt;p&gt;Primitive data types, or &quot;basic data types&quot; or &quot;fundamental data types&quot; are the most basic data types that can be used for representing simple values such as numbers, characters, etc... The primitive data types are...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;integers&quot;&gt;Integer types&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;char: represents a single character (usually 1 byte)&lt;&#x2F;li&gt;
&lt;li&gt;short: represents a small integer&lt;&#x2F;li&gt;
&lt;li&gt;int: represents an integer&lt;&#x2F;li&gt;
&lt;li&gt;long: represents a long integer&lt;&#x2F;li&gt;
&lt;li&gt;long long: represents a very long integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned short: represent a small positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned int: represents a positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned long: represents a long positive integer&lt;&#x2F;li&gt;
&lt;li&gt;unsigned long long: represents a very long positive integer&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This list is not exhaustive, there is also what we call &lt;strong&gt;fixed width integer types&lt;&#x2F;strong&gt; and what we call &lt;strong&gt;minimum width integer types&lt;&#x2F;strong&gt;. We won&#x27;t talk about them here, please browse this &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;stdint.h.html&quot;&gt;link&lt;&#x2F;a&gt; for reference.&lt;&#x2F;p&gt;
&lt;p&gt;To find the range of a particular type, we can look for the &lt;code&gt;limits.h&lt;&#x2F;code&gt; file  &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;limits.h.html&quot;&gt;online&lt;&#x2F;a&gt;. Or, we can also look for the same file inside our computer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt; find &#x2F;usr -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;limits.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;uapi&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-51&#x2F;include&#x2F;vdso&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;uapi&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;src&#x2F;linux-headers-5.13.0-52&#x2F;include&#x2F;vdso&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;linux&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;c++&#x2F;11&#x2F;tr1&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;gcc&#x2F;x86_64-linux-gnu&#x2F;11&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;perl5&#x2F;5.32&#x2F;Tk&#x2F;pTk&#x2F;compat&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;llvm-13&#x2F;lib&#x2F;clang&#x2F;13.0.0&#x2F;include&#x2F;limits.h
&lt;&#x2F;span&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we open, let&#x27;s say, the file &lt;code&gt;&#x2F;usr&#x2F;include&#x2F;limits.h&lt;&#x2F;code&gt;, we can see interesting informations like :&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MAX     UCHAR_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MIN     SCHAR_MIN
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define CHAR_MAX     SCHAR_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  endif
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed short int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define SHRT_MIN      (&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32768&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define SHRT_MAX      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32767
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum value an `unsigned short int&amp;#39; can hold.  (Minimum is 0.)  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define USHRT_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65535
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define INT_MIN       (&lt;&#x2F;span&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;INT_MAX &lt;&#x2F;span&gt;&lt;span&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define INT_MAX       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2147483647
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum value an `unsigned int&amp;#39; can hold.  (Minimum is 0.)  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  define UINT_MAX      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4294967295&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;U
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Minimum and maximum values a `signed long int&amp;#39; can hold.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  if __WORDSIZE == 64
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define LONG_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;9223372036854775807&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#  else
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#   define LONG_MAX     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2147483647&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;L
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;floats&quot;&gt;Floating-point types:&lt;&#x2F;h3&gt;
&lt;p&gt;Used to represent real numbers with decimal points. More informations &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;float.h.html&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;float: represents a single-precision floating-point number&lt;&#x2F;li&gt;
&lt;li&gt;double: represents a double-precision floating-point number&lt;&#x2F;li&gt;
&lt;li&gt;long double: represents an extended-precision floating-point number&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is an example showing how to use float values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; input[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; radius, area;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter the radius of the circle: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; input, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    radius = strtof(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    area = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Area of the circle: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, area);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have found the file containing all the constants definitions for float values, but I am not (yet) able to correctly understand what&#x27;s going on in this header file:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt; find &#x2F;usr -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;float.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;tcl8.6&#x2F;tcl-private&#x2F;compat&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;c++&#x2F;11&#x2F;tr1&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;gcc&#x2F;x86_64-linux-gnu&#x2F;11&#x2F;include&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;lib&#x2F;llvm-13&#x2F;lib&#x2F;clang&#x2F;13.0.0&#x2F;include&#x2F;float.h
&lt;&#x2F;span&gt;&lt;span&gt;lim  (trunk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;%) &amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is a snippet of things that may be of interest for anyone looking for the ranges:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defined&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt; __STDC_VERSION__ &amp;amp;&amp;amp; __STDC_VERSION__ &amp;gt; 201710L
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Maximum finite positive value with MANT_DIG digits in the
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;   significand taking their maximum value.  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef FLT_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef DBL_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef LDBL_NORM_MAX
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define FLT_NORM_MAX    __FLT_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define DBL_NORM_MAX    __DBL_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define LDBL_NORM_MAX   __LDBL_NORM_MAX__
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;* Whether each type matches an IEC 60559 format (1 for format, 2 for
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;   format and operations).  *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef FLT_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef DBL_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#undef LDBL_IS_IEC_60559
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define FLT_IS_IEC_60559        __FLT_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define DBL_IS_IEC_60559        __DBL_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define LDBL_IS_IEC_60559       __LDBL_IS_IEC_60559__
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;bool&quot;&gt;Boolean type:&lt;&#x2F;h3&gt;
&lt;p&gt;The data type that can have two possible values: true or false. Include the &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;9699919799&#x2F;basedefs&#x2F;stdbool.h.html&quot;&gt;&quot;stdbool.h&quot;&lt;&#x2F;a&gt; header file in your program to use this data type. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdbool.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;bool &lt;&#x2F;span&gt;&lt;span&gt;strtobool(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const char* &lt;&#x2F;span&gt;&lt;span&gt;str) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;true&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;1&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return true&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else if &lt;&#x2F;span&gt;&lt;span&gt;(strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;false&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span&gt;|| strcmp(str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;0&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return false&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    fprintf(stderr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Invalid input: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; answer[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;bool&lt;&#x2F;span&gt;&lt;span&gt; is_learning;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your name: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; name, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Your name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Are you learning C programming: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(answer, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; answer, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    is_learning = strtobool(answer);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(is_learning)
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Very good, keep learning.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;You should learn C programming.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;void&quot;&gt;Void type:&lt;&#x2F;h3&gt;
&lt;p&gt;Void is a keyword to use as a placeholder where you would put a data type, to represent &quot;no data&quot;. The void data type represents the absence of type. Void types are used in the following situations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;to state that the specific type of the variable is not known &lt;em&gt;yet&lt;&#x2F;em&gt; (void pointers).&lt;&#x2F;li&gt;
&lt;li&gt;to state that the function returns no result (void functions).&lt;&#x2F;li&gt;
&lt;li&gt;to state that the function has no parameters.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;IMPORTANT: We can&#x27;t directly dereference void pointers because the compiler doesn&#x27;t know the size or type of data being pointed to. We need to explicitly cast them to the correct type before dereferencing.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Here&#x27;s an example to illustrate the usage of void type:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; greet is a function that
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returns no result
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and takes an unkown&#x2F;undefined list of arguments
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; notice how we can pass all the arguments we want
&lt;&#x2F;span&gt;&lt;span&gt;  greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A function declared with the void data type can&#x27;t return a value, we cannot use the return keyword inside a void function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;cscripts  &amp;gt;&amp;gt; gcc main.c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;.&#x2F;a.out 
&lt;&#x2F;span&gt;&lt;span&gt;main.c: In function ‘greet’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:57:10: warning: ‘return’ with a value, in function returning void
&lt;&#x2F;span&gt;&lt;span&gt;   57 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   return&lt;&#x2F;span&gt;&lt;span&gt; 5432&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|          &lt;&#x2F;span&gt;&lt;span&gt;^~~~
&lt;&#x2F;span&gt;&lt;span&gt;main.c:56:6: note: declared here
&lt;&#x2F;span&gt;&lt;span&gt;   56 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;void greet(void){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|      &lt;&#x2F;span&gt;&lt;span&gt;^~~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; greet is a function that
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returns an int
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and takes no arguments
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Because greet returns a result, I can retrieve and print it
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Greet returned the value: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, greet());
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}                                                                                                            
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we try to pass an argument to the greet function, we will receive an error message:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;cscripts  &amp;gt;&amp;gt; gcc main.c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;.&#x2F;a.out 
&lt;&#x2F;span&gt;&lt;span&gt;main.c: In function ‘main’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:57:44: error: too many arguments to function ‘greet’
&lt;&#x2F;span&gt;&lt;span&gt;   57 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   &lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Greet returned the value: %d\n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|                                            &lt;&#x2F;span&gt;&lt;span&gt;^~~~~
&lt;&#x2F;span&gt;&lt;span&gt;main.c:52:5: note: declared here
&lt;&#x2F;span&gt;&lt;span&gt;   52 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;int greet(void){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|     &lt;&#x2F;span&gt;&lt;span&gt;^~~~~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Last example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; age = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char*&lt;&#x2F;span&gt;&lt;span&gt; name = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nsukami_&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; foo is a pointer that point to a not yet knwon data type
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void*&lt;&#x2F;span&gt;&lt;span&gt; foo;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s point to an integer
&lt;&#x2F;span&gt;&lt;span&gt;  foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;age;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; explicit cast to the correct type before dereferencing
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;age is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int*&lt;&#x2F;span&gt;&lt;span&gt;)foo));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s point to something else, for ex, a string
&lt;&#x2F;span&gt;&lt;span&gt;  foo = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;name;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; explicit cast to the correct type before dereferencing
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;((&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char**&lt;&#x2F;span&gt;&lt;span&gt;)foo));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;composite&quot;&gt;Composite types&lt;&#x2F;h2&gt;
&lt;p&gt;Any data type which can be constructed using the language&#x27;s primitive data types and other composite types.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;structs&quot;&gt;Structures:&lt;&#x2F;h3&gt;
&lt;p&gt;Structs (short for structure), a user-defined data type that allows us to group together related data items of different types. Those data items are known as members or fields.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; An address is something with 2 attributes
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a city street AND an house number
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct&lt;&#x2F;span&gt;&lt;span&gt; address {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; citystreet[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; housenumber;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Address&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Address my_address = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Planet 42, Rue de la Liberté&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5432&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  };
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I live in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. My house number is: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, my_address.citystreet, my_address.housenumber);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; how to update one of the fields
&lt;&#x2F;span&gt;&lt;span&gt;  my_address.housenumber = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;443&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I live in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;. My house number is now: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, my_address.citystreet, my_address.housenumber);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;enums&quot;&gt;Enum data type:&lt;&#x2F;h3&gt;
&lt;p&gt;An enumeration is a &lt;em&gt;special kind&lt;&#x2F;em&gt; of data type defined by the user. An enumeration consists of a set of constant &lt;em&gt;integers&lt;&#x2F;em&gt; that are named by the user.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef enum&lt;&#x2F;span&gt;&lt;span&gt; Level {
&lt;&#x2F;span&gt;&lt;span&gt;  LOW = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  MEDIUM,
&lt;&#x2F;span&gt;&lt;span&gt;  HIGH
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Level&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  Level level = MEDIUM;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;switch &lt;&#x2F;span&gt;&lt;span&gt;(level) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Low level&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Medium level&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;High level&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;default&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Unkown level value&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;} 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We said earlier an enumeration is a &lt;em&gt;special kind&lt;&#x2F;em&gt; of data type because.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;unions&quot;&gt;Unions:&lt;&#x2F;h3&gt;
&lt;p&gt;An union is a user-defined data type that allows different data types to be stored in the same memory location. It enables us to create a variable that can hold different types of data, but only one type at a time.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Struct that combines an enum and a union
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;typedef struct &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; The type of our object could be either INT, either FLOAT, either STRING
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    INT,
&lt;&#x2F;span&gt;&lt;span&gt;    FLOAT,
&lt;&#x2F;span&gt;&lt;span&gt;    STRING
&lt;&#x2F;span&gt;&lt;span&gt;  } type;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; all 3 values share the same memory location, only one can be set
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; value can be a int OR a float OR a string
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;union &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; intValue;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; floatValue;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; stringValue[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  } value;
&lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;Object&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Function to print the object based on its type
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;print(Object o) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; check the type of our object 
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;switch&lt;&#x2F;span&gt;&lt;span&gt;(o.type) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span&gt;INT:
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; then access the correct value
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Integer: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.intValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case &lt;&#x2F;span&gt;&lt;span&gt;FLOAT:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Float: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.floatValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;case&lt;&#x2F;span&gt;&lt;span&gt; STRING:
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;String: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, o.value.stringValue);
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;break&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Creating objects of different types
&lt;&#x2F;span&gt;&lt;span&gt;  Object o1, o2, o3;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o1.type = INT;
&lt;&#x2F;span&gt;&lt;span&gt;  o1.value.intValue = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o2.type = FLOAT;
&lt;&#x2F;span&gt;&lt;span&gt;  o2.value.floatValue = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  o3.type = STRING;
&lt;&#x2F;span&gt;&lt;span&gt;  strcpy(o3.value.stringValue, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; Printing the data objects
&lt;&#x2F;span&gt;&lt;span&gt;  print(o1);
&lt;&#x2F;span&gt;&lt;span&gt;  print(o2);
&lt;&#x2F;span&gt;&lt;span&gt;  print(o3);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;arrays&quot;&gt;Arrays:&lt;&#x2F;h3&gt;
&lt;p&gt;A type consisting of nonempty items of the same nature stored using contiguous memory location. The number of items (the size) never changes during the array lifetime. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; numbers[] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2.5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4.2&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1.9&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5.6&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; size = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(numbers) &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(numbers[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;float&lt;&#x2F;span&gt;&lt;span&gt; sum = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0&lt;&#x2F;span&gt;&lt;span&gt;, average;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; size; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;        sum += numbers[i];
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    average = sum &#x2F; size;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Average: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%.2f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, average);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;strings&quot;&gt;Strings:&lt;&#x2F;h3&gt;
&lt;p&gt;A string is just a sequence of characters stored inside an array and ending with the null character: &#x27;\0&#x27;. We don&#x27;t have strings as we have them in Python programming.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; name[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your name: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(name, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; name, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Your name is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  exit(EXIT_SUCCESS);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To know what are the functions available for string manipulation, Python developers will type &lt;code&gt;help(str)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;Help on &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;str &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;module builtins:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;str(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;object&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt; |  str(object=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; str
&lt;&#x2F;span&gt;&lt;span&gt; |  str(bytes_or_buffer[, encoding[, errors]]) -&amp;gt; str
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  Create a new string object &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;the given object. If encoding &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;or
&lt;&#x2F;span&gt;&lt;span&gt; |  errors &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is &lt;&#x2F;span&gt;&lt;span&gt;specified, then the object must expose a data buffer
&lt;&#x2F;span&gt;&lt;span&gt; |  that will be decoded using the given encoding &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;and &lt;&#x2F;span&gt;&lt;span&gt;error handler.
&lt;&#x2F;span&gt;&lt;span&gt; |  Otherwise, returns the result of object.__str__() (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;defined)
&lt;&#x2F;span&gt;&lt;span&gt; |  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;or &lt;&#x2F;span&gt;&lt;span&gt;repr(object).
&lt;&#x2F;span&gt;&lt;span&gt; |  encoding defaults to sys.getdefaultencoding().
&lt;&#x2F;span&gt;&lt;span&gt; |  errors defaults to &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;strict&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  Methods defined here:
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __add__(self, value, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return self+value.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __contains__(self, key, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return bool(key &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self).
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __eq__(self, value, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt; |      Return self==value.
&lt;&#x2F;span&gt;&lt;span&gt; |
&lt;&#x2F;span&gt;&lt;span&gt; |  __format__(self, format_spec, &#x2F;)
&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;C developers will look inside the &lt;code&gt;&amp;lt;string.h&amp;gt;&lt;&#x2F;code&gt; header &lt;a href=&quot;https:&#x2F;&#x2F;pubs.opengroup.org&#x2F;onlinepubs&#x2F;009695399&#x2F;basedefs&#x2F;string.h.html&quot;&gt;file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;nskm2  &amp;gt;&amp;gt; find &#x2F;usr&#x2F;include -type f -name &amp;quot;string.h&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;linux&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;tcl8.6&#x2F;tcl-private&#x2F;compat&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;usr&#x2F;include&#x2F;string.h
&lt;&#x2F;span&gt;&lt;span&gt;nskm2  &amp;gt;&amp;gt; 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They can also read the man pages, &lt;code&gt;man string&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;STRING(3)                                  Linux Programmer&amp;#39;s Manual                                 STRING(3)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;NAME
&lt;&#x2F;span&gt;&lt;span&gt;       stpcpy,  strcasecmp, strcat, strchr, strcmp, strcoll, strcpy, strcspn, strdup, strfry, strlen, strncat,
&lt;&#x2F;span&gt;&lt;span&gt;       strncmp, strncpy, strncasecmp, strpbrk, strrchr, strsep, strspn, strstr, strtok, strxfrm, index, rindex
&lt;&#x2F;span&gt;&lt;span&gt;       - string operations
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SYNOPSIS
&lt;&#x2F;span&gt;&lt;span&gt;       #include &amp;lt;strings.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       int strcasecmp(const char *s1, const char *s2);
&lt;&#x2F;span&gt;&lt;span&gt;              Compare the strings s1 and s2 ignoring case.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       int strncasecmp(const char *s1, const char *s2, size_t n);
&lt;&#x2F;span&gt;&lt;span&gt;              Compare the first n bytes of the strings s1 and s2 ignoring case.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *index(const char *s, int c);
&lt;&#x2F;span&gt;&lt;span&gt;              Return a pointer to the first occurrence of the character c in the string s.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *rindex(const char *s, int c);
&lt;&#x2F;span&gt;&lt;span&gt;              Return a pointer to the last occurrence of the character c in the string s.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       #include &amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;       char *stpcpy(char *dest, const char *src);
&lt;&#x2F;span&gt;&lt;span&gt;              Copy a string from src to dest, returning a pointer to the end of the resulting string at dest.
&lt;&#x2F;span&gt;&lt;span&gt; Manual page string(3) line 1 (press h for help or q to quit)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;constants&quot;&gt;Constants:&lt;&#x2F;h2&gt;
&lt;p&gt;A fixed value that cannot be, &lt;em&gt;that should not&lt;&#x2F;em&gt; be changed during the execution of a program.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;If we have a fixed value that is used in calculations, we can define it as a constant to avoid hard-coding the value multiple times.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s define PI as a constant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; PI = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3.14159&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; radius = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; let&amp;#39;s reuse our constant
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; area = PI &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; radius;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Trying to modify our constant will give us an error message:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;main.c: In function ‘main’:
&lt;&#x2F;span&gt;&lt;span&gt;main.c:129:6: error: assignment of read-only variable ‘PI’
&lt;&#x2F;span&gt;&lt;span&gt;  129 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|   &lt;&#x2F;span&gt;&lt;span&gt;PI = 4.5&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|      &lt;&#x2F;span&gt;&lt;span&gt;^
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Another way to use constants is this one. Instead of using arbitrary numbers directly in your code, you can define them as constants with meaningful names to improve code readability and maintainability.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; LENGTH = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; MIN_AGE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;18&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; MAX_AGE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; input[LENGTH];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; age;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Enter your age: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(fgets(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt; input, stdin) != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  age = strtol(input, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(age &amp;lt; MIN_AGE || age &amp;gt; MAX_AGE) {
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; is an invalid age! Please enter an age between &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, age, MIN_AGE, MAX_AGE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;When declaring an array, we can use a constant to specify its size, making it easier to modify if needed.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; In this example, `ARRAY_SIZE` is declared as a constant to specify the size of an array. By using a
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; constant, you can easily change the size of the array by modifying the constant&amp;#39;s value in a single place.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int&lt;&#x2F;span&gt;&lt;span&gt; ARRAY_SIZE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; arr[ARRAY_SIZE];
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;We can also declare function parameters as &lt;code&gt;const&lt;&#x2F;code&gt; to ensure that the function does not modify the parameter:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; This helps prevent accidental modifications and indicates that the function is read-only.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;const int &lt;&#x2F;span&gt;&lt;span&gt;arr[], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;size) {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; i = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;; i &amp;lt; size; i++) {
&lt;&#x2F;span&gt;&lt;span&gt;        printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, arr[i]);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h2&gt;
&lt;p&gt;I really hope you&#x27;ve learned something. I did \o&#x2F; In the next episode, I will try to write about header files or pointers or something else depending on the current moon, the weather and the stars alignment. Also, thanks to &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@orbifx&quot;&gt;Orbifx&lt;&#x2F;a&gt; for taking the time to answer all my questions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;more-on-the-topic&quot;&gt;More on the topic:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;hal.inria.fr&#x2F;hal-02383654&#x2F;file&#x2F;ModernC.pdf&quot;&gt;Modern C, Jens Gustedt&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gnu-c-manual&#x2F;gnu-c-manual.pdf&quot;&gt;The GNU C Reference Manual&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;amjadmajid&#x2F;Makefile&quot;&gt;Explanation about how to write a Makefile&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n2655.pdf&quot;&gt;Make false and true first-class language features v4
proposal for C23&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;on-a-completely-differnt-note&quot;&gt;On a completely differnt note:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=snvzAfYOFks&quot;&gt;Des organismes aux algorithmes, l&#x27;odyssée computationnelle du vivant | Xavier Berthet | TEDxINPENSAT&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;2023.djangocon.africa&#x2F;&quot;&gt;The first DjangoCon Africa, in Zanzibar, Tanzania.&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Decorators</title>
        <published>2023-02-06T00:00:00+00:00</published>
        <updated>2023-02-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/decor/"/>
        <id>https://nskm.xyz/posts/decor/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/decor/">&lt;p&gt;I was watching a &lt;em&gt;really&lt;&#x2F;em&gt; interesting &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=RL7BECNn-RI&quot;&gt;video&lt;&#x2F;a&gt; about buildings architecture in New York, when one of my &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;DIT&lt;&#x2F;a&gt; student asked me to explain to him what was happening in this &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;flask-user-authentication-example&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;main&#x2F;utils.py#L7&quot;&gt;piece of code&lt;&#x2F;a&gt;. A function I have written few months ago to check for valid authentication tokens. In this post, I will try to show how decorators in &lt;a href=&quot;https:&#x2F;&#x2F;python.org&quot;&gt;Python&lt;&#x2F;a&gt;, a powerful concept, allows us to apply new functionality without modifying the existing structure of an object. &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=cDk9L72ZkuE&quot;&gt;Music please&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width: 600px&quot; src=&quot;&#x2F;assets&#x2F;decorated.png&quot; alt=&quot;&quot; title=&quot;Somewhere in Africa&quot;&#x2F;&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#f&quot;&gt;1 A function doing one thing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#g&quot;&gt;2 A decorator, modifying the behaviour of the function&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#h&quot;&gt;3 A decorator should keep important informations&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#i&quot;&gt;4 A decorator should receive a flexible number of argument&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#j&quot;&gt;5 A decorator can also have parameters&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#k&quot;&gt;6 We are still able to access the decorated function&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#l&quot;&gt;7 An interesting example&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;decor&#x2F;#m&quot;&gt;8 Even more interesting, how decorators are used elsewhere&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;f&quot;&gt;1. A function:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose we want to join 2 paths:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pathlib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Path
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]: a = Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]: a
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;]: b = Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]: a.joinpath(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s suppose we usually combine 2 paths together. So much that we created a function for that purpose:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;]: path_t = str | Path
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;22&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Join 2 paths together&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b, a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bar&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a, b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;24&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;25&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;corge&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;26&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;26&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;g&quot;&gt;2. A decorator modifying the behaviour of the function:&lt;&#x2F;h1&gt;
&lt;p&gt;While it may seem confusing at first, a decorator is really just &lt;em&gt;a function that takes a function and returns a function&lt;&#x2F;em&gt;. Let me explain.&lt;&#x2F;p&gt;
&lt;p&gt;Suppose we usually combine our home path with another path. Let&#x27;s suppose the first parameter is often our home path. Let&#x27;s suppose we can&#x27;t modify the original function. Python functions are &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;First-class_citizen&quot;&gt;first-class citizens&lt;&#x2F;a&gt;. That means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We can pass a function as an argument of another function.&lt;&#x2F;li&gt;
&lt;li&gt;We can assign a function to a variable.&lt;&#x2F;li&gt;
&lt;li&gt;We can return a function as a value from another function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;38&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func: Callable[[path_t, path_t], path_t]) -&amp;gt; Callable[[path_t], path_t]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A wrapper that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;39&lt;&#x2F;span&gt;&lt;span&gt;]: f = homeprefix(jp)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;]: f(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;40&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;]: f(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;41&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;]: f(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt;]: f(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&#x2F;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;43&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;44&lt;&#x2F;span&gt;&lt;span&gt;]: f(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;spam&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;44&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;spam&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As strange as it may seems, we could have done the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;]: jp = homeprefix(jp) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# there is an alternative syntax
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;46&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;46&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;47&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;48&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foobar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;48&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foobar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;49&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;49&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of &lt;code&gt;jp = homeprefix(jp)&lt;&#x2F;code&gt; we could use the following syntax which better vehicle our intent: &lt;strong&gt;modifying the behaviour of an existing function&lt;&#x2F;strong&gt;. Simply put: &lt;strong&gt;decorating&lt;&#x2F;strong&gt; our original function:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;51&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# here we are, decorating jp function 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Join 2 paths together&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;52&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;52&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;53&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&#x2F;qux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;53&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&#x2F;qux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;54&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;54&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;55&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;55&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;56&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;h&quot;&gt;3. A decorator should keep important informations:&lt;&#x2F;h1&gt;
&lt;p&gt;Now we have another problem. Because we are literally replacing one function with another, we&#x27;re also losing important informations like the docstring and the name:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;61&lt;&#x2F;span&gt;&lt;span&gt;]: ?jp
&lt;&#x2F;span&gt;&lt;span&gt;Signature: jp(m)
&lt;&#x2F;span&gt;&lt;span&gt;Docstring: A function that takes one parameter.
&lt;&#x2F;span&gt;&lt;span&gt;File:      ~&#x2F;GIT&#x2F;nskm2&#x2F;&amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;59&lt;&#x2F;span&gt;&lt;span&gt;-b4f67b1e800d&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type:      function
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;62&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__name__
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;62&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;wrapper&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;63&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s the reason we have &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html#functools.wraps&quot;&gt;functools.wraps&lt;&#x2F;a&gt;. &lt;code&gt;Wraps&lt;&#x2F;code&gt; takes the decorated function and adds the functionality of copying over the function name, docstring, arguments list, etc to &lt;strong&gt;the returned function&lt;&#x2F;strong&gt;. And since wraps is itself a decorator:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;63&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;64&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;66&lt;&#x2F;span&gt;&lt;span&gt;]: ?jp
&lt;&#x2F;span&gt;&lt;span&gt;Signature: jp(path1: str | pathlib.Path, path2: str | pathlib.Path) -&amp;gt; str | pathlib.Path
&lt;&#x2F;span&gt;&lt;span&gt;Docstring: A function that join &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;paths together.
&lt;&#x2F;span&gt;&lt;span&gt;File:      ~&#x2F;GIT&#x2F;nskm2&#x2F;&amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;-1703cd8a40dc&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type:      function
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;67&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__name__
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;67&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;jp&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;68&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;i&quot;&gt;4. A decorator should receive a flexible number of argument:&lt;&#x2F;h1&gt;
&lt;p&gt;Now, let&#x27;s suppose our original function can take many arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;101&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;102&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;abc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;102&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bac&#x2F;abc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;103&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bac&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;103&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;bac&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;104&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;abc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;104&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;abc&#x2F;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The previous decorator is not flexible enough because the returned function can&#x27;t take more than 1 parameter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;106&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(m):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, m)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;107&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;108&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;108&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;a&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;109&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;---------------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;TypeError                                 Traceback (most recent call last)
&lt;&#x2F;span&gt;&lt;span&gt;Cell In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;109&lt;&#x2F;span&gt;&lt;span&gt;], line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;----&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TypeError: jp() takes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1 &lt;&#x2F;span&gt;&lt;span&gt;positional argument but &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span&gt;were given
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;110&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s rewrite our decorator so that the returned function can take an infinte number or arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;113&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(func):
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(*args):  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# here is our update: using *args 
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;114&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(*args: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join many paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;args:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(*args[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:])
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;raise &lt;&#x2F;span&gt;&lt;span&gt;ValueError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;args should be longer&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;115&lt;&#x2F;span&gt;&lt;span&gt;]: jp()
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;115&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;116&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;116&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;b&#x2F;c&#x2F;d&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;117&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;d&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;117&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;b&#x2F;c&#x2F;d&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;118&lt;&#x2F;span&gt;&lt;span&gt;]: jp(Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;), Path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;118&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;119&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the help of the special parameters *args and **kwargs, decorators become more generic. That way if we need the same kind of decorator in different functions with different arguments, we can write just one decorator. In general, a decorator is written like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;decorator(func):
&lt;&#x2F;span&gt;&lt;span&gt;    @wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;wrapper(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;        func(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;wrapper
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;j&quot;&gt;5. A decorator can also have parameters:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose people using the decorator want to be able to set what should the prefix used as the first parameter of our jp function. Let&#x27;s suppose we want the decorator to receive one parameter, which is the prefix:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;70&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;homeprefix(prefix): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this function builds and returns a decorator 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(func): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this function is the decorator 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;wraps(func)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the function wrapping the original function 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that takes one parameter.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:             &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;func(prefix, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;71&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;homeprefix(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;]: jp(a)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: jp(b)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;bar&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;74&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;74&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We understand better what&#x27;s going on when we do this instead:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;]: decorator = homeprefix(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;patrick&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# setup a prefix 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;76&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;decorator  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# decorate 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;jp(path1: path_t, path2: path_t) -&amp;gt; path_t:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A function that join 2 paths together.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;isinstance(path1, str):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:         path1 = Path(path1)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;path1.joinpath(path2)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;corge&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;patrick&#x2F;corge&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;78&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quux&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;78&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;patrick&#x2F;quux&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;79&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;k&quot;&gt;6. We are still able to access the decorated function:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose for some reason we want to test the function as if it was not decorated. Let&#x27;s suppose we still want to use the underlying function. To achieve that, we&#x27;ll use the &lt;code&gt;__wrapped__&lt;&#x2F;code&gt; attribute (assuming we used the &lt;code&gt;functools.wrap&lt;&#x2F;code&gt; function). &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html?highlight=__wrapped__&quot;&gt;Somewhere&lt;&#x2F;a&gt; in the documentation, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The original underlying function is accessible through the &lt;strong&gt;wrapped&lt;&#x2F;strong&gt; attribute. This is useful for introspection, for bypassing the cache, or for rewrapping the function with a different cache.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;127&lt;&#x2F;span&gt;&lt;span&gt;]: jp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;127&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;]: jp.__wrapped__(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# original function 
&lt;&#x2F;span&gt;&lt;span&gt;Out[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;]: PosixPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;129&lt;&#x2F;span&gt;&lt;span&gt;]: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;l&quot;&gt;7. An interesting example:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;csv
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sqlite3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;here = pathlib.Path(__file__)
&lt;&#x2F;span&gt;&lt;span&gt;db = here.parent.parent.parent &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sqlite_stuff&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook.db&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;connect(db):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to connect to an SQLite database and execute a query.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    conn = sqlite3.connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;    conn.isolation_level = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            query = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;            rset = conn.execute(query).fetchall()
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rset
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;columns(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;columns, limit=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to specify what columns should be retrieved.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cols = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;, &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.join(columns)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            query = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs).split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;            start, end = query[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].strip(), query[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].strip()
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;{start} {cols} {end}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; limit &lt;&#x2F;span&gt;&lt;span&gt;{limit}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;as_csv(where=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;result.csv&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot;A decorator to save the result as a csv file.&amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;outer(f):
&lt;&#x2F;span&gt;&lt;span&gt;        @wraps(f)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;inner(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs):
&lt;&#x2F;span&gt;&lt;span&gt;            rset = f(*args, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span&gt;kwargs)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(where, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;w&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, newline=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;dest:
&lt;&#x2F;span&gt;&lt;span&gt;                csv_writer = csv.writer(
&lt;&#x2F;span&gt;&lt;span&gt;                    dest, delimiter=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;,&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, quoting=csv.QUOTE_ALL, lineterminator=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\r\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                )
&lt;&#x2F;span&gt;&lt;span&gt;                csv_writer.writerows(rset)
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;len(rset)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;inner
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;outer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;###
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@as_csv()
&lt;&#x2F;span&gt;&lt;span&gt;@connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;@columns(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;title&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;artistId&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;run(table=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;albums&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    query = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select * from &lt;&#x2F;span&gt;&lt;span&gt;{table}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;query
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    print(run())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;8-even-more-interesting&quot;&gt;8. Even more interesting:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sqlite3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;functools &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;wraps
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;here = pathlib.Path(__file__)
&lt;&#x2F;span&gt;&lt;span&gt;db = here.parent.parent.parent &#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;sqlite_stuff&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook&amp;quot; &lt;&#x2F;span&gt;&lt;span&gt;&#x2F; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;chinook.db&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;connect(cls):
&lt;&#x2F;span&gt;&lt;span&gt;    conn = sqlite3.connect(db)
&lt;&#x2F;span&gt;&lt;span&gt;    conn.isolation_level = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# sqlite3.IMMEDIATE
&lt;&#x2F;span&gt;&lt;span&gt;    setattr(cls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;conn&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, conn)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;select(cls):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;select(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls.conn.execute(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select * from &lt;&#x2F;span&gt;&lt;span&gt;{cls.__name__}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).fetchall()
&lt;&#x2F;span&gt;&lt;span&gt;    setattr(cls, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;select&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, select)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;cls
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@select
&lt;&#x2F;span&gt;&lt;span&gt;@connect
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Albums:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    a = Albums()
&lt;&#x2F;span&gt;&lt;span&gt;    print(a.select())
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;m&quot;&gt;8. Even more interesting, how decorators are used elsewhere:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;cubicweb.org&#x2F;&quot;&gt;Cubicweb&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubes&#x2F;api&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;cubicweb_api&#x2F;routes.py#L137&quot;&gt;decorator&lt;&#x2F;a&gt; used to raise an AuthenticationError if no user is detected.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;2.2.x&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pallets&#x2F;flask&#x2F;blob&#x2F;afc13b9390ae2e40f4731e815b49edc9ef52ed4b&#x2F;examples&#x2F;tutorial&#x2F;flaskr&#x2F;auth.py#L19&quot;&gt;decorator&lt;&#x2F;a&gt;  that redirects anonymous users to the login page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;flask.palletsprojects.com&#x2F;en&#x2F;2.2.x&#x2F;patterns&#x2F;viewdecorators&#x2F;#templating-decorator&quot;&gt;Templating decorator&lt;&#x2F;a&gt; invented by the &lt;a href=&quot;https:&#x2F;&#x2F;turbogears.org&#x2F;&quot;&gt;TurboGears&lt;&#x2F;a&gt; guys a while back to automatically render a template.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;main&#x2F;django&#x2F;views&#x2F;decorators&#x2F;http.py&quot;&gt;decorators&lt;&#x2F;a&gt; to manipulate &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Headers&quot;&gt;http headers&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;9-more-on-this-topic&quot;&gt;9. More on this topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I hope that you found this post helpful. To learn about this topic, please, browse the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0318&#x2F;&quot;&gt;PEP 318 – Decorators for Functions and Methods&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;wiki.python.org&#x2F;moin&#x2F;PythonDecoratorLibrary&quot;&gt;PythonDecoratorLibrary&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functools.html&quot;&gt;functools&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;glossary.html#term-decorator&quot;&gt;decorator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;sqlite3.html#&quot;&gt;DB-API 2.0 interface for SQLite databases&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;15357776&#x2F;what-is-the-difference-between-functools-wraps-and-update-wrapper&quot;&gt;The difference between wraps and update_wrapper&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.artima.com&#x2F;weblogs&#x2F;viewpost.jsp?thread=241209&quot;&gt;Python Decorators III: A Decorator-Based Build System&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;2692&#x2F;&quot;&gt;Interior decorating&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Test driven interview</title>
        <published>2022-10-16T00:00:00+00:00</published>
        <updated>2022-10-16T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/tdi/"/>
        <id>https://nskm.xyz/posts/tdi/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/tdi/">&lt;h1 id=&quot;introduction&quot;&gt;Introduction:&lt;&#x2F;h1&gt;
&lt;p&gt;Test Driven Development &lt;em&gt;TDD&lt;&#x2F;em&gt; is a method of implementing software that rely on software requirements being converted to test cases before software is fully developed.&lt;&#x2F;p&gt;
&lt;p&gt;Red, Green and Refactor is the 3 phases of TDD. When followed, this order of steps helps ensure that you have tests for the code you are writing and you are writing only the code that you have to test for.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;context&quot;&gt;Context:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s suppose we should implement some requirements. Let&#x27;s suppose all the requirements and specifications are written using unit tests. See this &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&quot;&gt;repository&lt;&#x2F;a&gt;. Our mission is to write enough code to make all the tests pass. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;y.com.sb&#x2F;watch?v=gptoH8rzG14&quot;&gt;dive in&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#setup&quot;&gt;Setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#tests&quot;&gt;Tests&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Requirements&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#firstreq&quot;&gt;First requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#secondreq&quot;&gt;Second requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#thirdreq&quot;&gt;Third requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#fourthreq&quot;&gt;Fourth requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#fifthreq&quot;&gt;Fifth requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;tdi&#x2F;#lastreq&quot;&gt;Last requirement&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;&#x2F;h2&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git create-branch feat-1  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create a new branch for feature work
&lt;&#x2F;span&gt;&lt;span&gt;Basculement sur la nouvelle branche &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;feat-1&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; python3.10 -m venv .env  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# create a virtual environment
&lt;&#x2F;span&gt;&lt;span&gt;~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; source .env&#x2F;bin&#x2F;activate  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# activate virtual environment
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; pip install -r requirements.txt  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# install requirements
&lt;&#x2F;span&gt;&lt;span&gt;Collecting django&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;.2,&amp;gt;=3.1
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached Django-3.1.14-py3-none-any.whl (7.8 MB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting djangorestframework&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;.13,&amp;gt;=3.12
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached djangorestframework-3.12.4-py3-none-any.whl (957 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting sqlparse&amp;gt;=0.2.2
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached sqlparse-0.4.3-py3-none-any.whl (42 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting asgiref&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;,&amp;gt;=3.2.10
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached asgiref-3.5.2-py3-none-any.whl (22 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Collecting pytz
&lt;&#x2F;span&gt;&lt;span&gt;  Using cached pytz-2022.4-py2.py3-none-any.whl (500 kB)
&lt;&#x2F;span&gt;&lt;span&gt;Installing collected packages: pytz, sqlparse, asgiref, django, djangorestframework
&lt;&#x2F;span&gt;&lt;span&gt;Successfully installed asgiref-3.5.2 django-3.1.14 djangorestframework-3.12.4 pytz-2022.4 sqlparse-0.4.3
&lt;&#x2F;span&gt;&lt;span&gt;WARNING: You are using pip version 22.0.4&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span&gt;however, version 22.3 is available.
&lt;&#x2F;span&gt;&lt;span&gt;You should consider upgrading via the &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;.env&#x2F;bin&#x2F;python3.10 -m pip install --upgrade pip&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; command.
&lt;&#x2F;span&gt;&lt;span&gt;(.env) ~&#x2F;GIT&#x2F;interview  (feat-1) 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;tests&quot;&gt;How to launch tests ?&lt;&#x2F;h2&gt;
&lt;p&gt;According to the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;4.1&#x2F;topics&#x2F;testing&#x2F;overview&#x2F;#running-tests&quot;&gt;documentation&lt;&#x2F;a&gt;, we can run tests using the test command of your project&#x27;s manage.py utility. Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;eradman.com&#x2F;entrproject&#x2F;&quot;&gt;run that command&lt;&#x2F;a&gt; when any of the Python files changes. We also tell Django to stop running the test suite after first failed test. In a different terminal, let&#x27;s type one of the following commands:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# you can ask git ls-files command to watch for all the python files
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; git ls-files&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt; -- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.py&amp;#39; &amp;#39;:!:*__.py&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# you can ask find command to watch for all the python files
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; find src -type f -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; -not -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__*&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the ack command seems more readable
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt; ack -f --python &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;entr sh -c &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python src&#x2F;manage.py test --failfast --force-color -v 2 src&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Here is our first error:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;django.db.utils.OperationalError: no such table: inventory_product
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;firstreq&quot;&gt;1. First requirements: we need a Product model.&lt;&#x2F;h2&gt;
&lt;p&gt;We need to create a model named Product inside an application named inventory. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L12&quot;&gt;Somewhere&lt;&#x2F;a&gt; within the tests file, we can read:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create_coke(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;Product.objects.create(
&lt;&#x2F;span&gt;&lt;span&gt;            description=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Coca-Cola&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            unit_price=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            stock=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;models.py#L4&quot;&gt;open&lt;&#x2F;a&gt; the &lt;code&gt;models.py&lt;&#x2F;code&gt; file and write the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Product(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    description = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = models.FloatField()
&lt;&#x2F;span&gt;&lt;span&gt;    stock = models.IntegerField()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After running the migration scripts:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python src&#x2F;manage.py makemigrations &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;python src&#x2F;manage.py migrate
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The tests tells us to return an &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Status&#x2F;201&quot;&gt;http status 201&lt;&#x2F;a&gt; after Product creation. Right now, we have a 404. We need to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;create a REST API.&lt;&#x2F;li&gt;
&lt;li&gt;we should be able to create a Product via the API.&lt;&#x2F;li&gt;
&lt;li&gt;and the returned http status should be 201 _created.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_create_product (modules.inventory.tests.ProductTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 45, in test_create_product
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 201)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 404 != 201
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 1 test in 0.010s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;secondreq&quot;&gt;We need a REST API for managing a Product.&lt;&#x2F;h2&gt;
&lt;p&gt;Another &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L44&quot;&gt;part&lt;&#x2F;a&gt; of the tests is telling us we need an url named &lt;code&gt;api&#x2F;products&#x2F;&lt;&#x2F;code&gt;. Let&#x27;s create a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;serializers&#x2F;#modelserializer&quot;&gt;serializer&lt;&#x2F;a&gt;, a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;viewsets&#x2F;#modelviewset&quot;&gt;viewset&lt;&#x2F;a&gt; and a &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;routers&#x2F;&quot;&gt;router&lt;&#x2F;a&gt;. Here is the code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# &#x2F;src&#x2F;modules&#x2F;inventory&#x2F;views.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;serializers  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from .&lt;&#x2F;span&gt;&lt;span&gt;models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Product
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Product
&lt;&#x2F;span&gt;&lt;span&gt;        fields = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__all__&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.ModelViewSet&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Product.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = ProductSerializer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# &#x2F;src&#x2F;pos&#x2F;urls.py
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;path, include
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;modules.inventory.views &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;router = routers.DefaultRouter()
&lt;&#x2F;span&gt;&lt;span&gt;router.register(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;products&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, ProductsViewSet)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    path(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;api&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, include(router.urls)),
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After the changes, we notice some progress. The test tells us that if we attempt to delete a Product, we should receive an &lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;HTTP&#x2F;Status&#x2F;405&quot;&gt;http status 405&lt;&#x2F;a&gt; instead of 204. Litteraly, we have been able to delete a Product while it shouldn&#x27;t be allowed:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_delete_product (modules.inventory.tests.ProductTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 142, in test_delete_product
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 405)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 204 != 405
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 2 tests in 0.011s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;thirdreq&quot;&gt;A Product cannot be deleted.&lt;&#x2F;h2&gt;
&lt;p&gt;I should have take the time to carefully read all the tests. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L139&quot;&gt;Indeed&lt;&#x2F;a&gt;, one of them clearly states that we can&#x27;t delete a Product. Obviously, the ModelViewSet is not a good choice. We should update our viewset in a way that forbids product deletion. The operations: &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L36&quot;&gt;creating&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L18&quot;&gt;listing&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L95&quot;&gt;updating&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py#L57&quot;&gt;getting one product&lt;&#x2F;a&gt; should still be permitted. To achieve that, we&#x27;ll use some &lt;a href=&quot;https:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;api-guide&#x2F;generic-views&#x2F;#mixins&quot;&gt;mixins&lt;&#x2F;a&gt; offered by the framework. The product viewset becomes:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets, mixins
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ProductsViewSet(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.CreateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.ListModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.UpdateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.RetrieveModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.GenericViewSet&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Product.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = ProductSerializer
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;let-s-commit-what-have-been-done-so-far&quot;&gt;Let&#x27;s commit what have been done so far.&lt;&#x2F;h3&gt;
&lt;p&gt;All the tests related to Product are passing. We can commit and push what we&#x27;ve done so far.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git commit -m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Add Product API&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;[feat-1 a11ffeb] Add Product API
&lt;&#x2F;span&gt;&lt;span&gt; 5 files changed, 76 insertions(+), 6 deletions(-)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;modules&#x2F;inventory&#x2F;migrations&#x2F;0001_initial.py
&lt;&#x2F;span&gt;&lt;span&gt; rewrite src&#x2F;modules&#x2F;inventory&#x2F;views.py (98%)
&lt;&#x2F;span&gt;&lt;span&gt; create mode 100644 src&#x2F;modules&#x2F;orders&#x2F;migrations&#x2F;0001_initial.py
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; git push origin feat-1 
&lt;&#x2F;span&gt;&lt;span&gt;Énumération des objets: 25, fait.
&lt;&#x2F;span&gt;&lt;span&gt;Décompte des objets: 100% (24&#x2F;24), fait.
&lt;&#x2F;span&gt;&lt;span&gt;Compression par delta en utilisant jusqu&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;à 4 fils d&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;exécution
&lt;&#x2F;span&gt;&lt;span&gt;Compression des objets: 100% (14&#x2F;14), fait.
&lt;&#x2F;span&gt;&lt;span&gt;Écriture des objets: 100% (14&#x2F;14), 1.80 Kio &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;1.80 Mio&#x2F;s, fait.
&lt;&#x2F;span&gt;&lt;span&gt;Total 14 (delta 6), réutilisés 0 (delta 0), réutilisés du pack 0
&lt;&#x2F;span&gt;&lt;span&gt;remote: 
&lt;&#x2F;span&gt;&lt;span&gt;remote: Create a new pull request for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;feat-1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;remote:   https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;compare&#x2F;master...feat-1
&lt;&#x2F;span&gt;&lt;span&gt;remote: 
&lt;&#x2F;span&gt;&lt;span&gt;remote: . Processing 1 references
&lt;&#x2F;span&gt;&lt;span&gt;remote: Processed 1 references in total
&lt;&#x2F;span&gt;&lt;span&gt;To https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview.git
&lt;&#x2F;span&gt;&lt;span&gt; * &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;new branch&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;      feat-1 -&amp;gt; feat-1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
  &lt;img style=&quot;display: block; margin: 0 auto; width:100; height:100&quot; src=&quot;&#x2F;images&#x2F;ofcourse.gif&quot; alt=&quot;Of course&quot; title=&quot;Of course&quot;&#x2F;&gt;
&lt;h2 id=&quot;fourthreq&quot;&gt;We need another model named Order.&lt;&#x2F;h2&gt;
&lt;p&gt;All the tests located in the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;inventory&#x2F;tests.py&quot;&gt;inventory&lt;&#x2F;a&gt; application are passing. This is why we decided to commit and push. There is one test currently failing, it it located inside the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;master&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py&quot;&gt;orders&lt;&#x2F;a&gt; application. The test tells us we need to create a model named Order:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;=====================================================================&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAIL: test_create_order (modules.orders.tests.OrdersTestCase)
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;home&#x2F;nsukami&#x2F;GIT&#x2F;interview&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, line 87, in test_create_order
&lt;&#x2F;span&gt;&lt;span&gt;    self.assertEqual(response.status_code, 201)
&lt;&#x2F;span&gt;&lt;span&gt;AssertionError: 404 != 201
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 7 tests in 0.054s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;FAILED (failures=1)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s continue reading the tests. &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L90&quot;&gt;Line 90&lt;&#x2F;a&gt;, we read that an item should have 4 attributes: &lt;code&gt;description, quantity, unit_price, total&lt;&#x2F;code&gt;. We also read that an Order has 2 attributes: &lt;code&gt;items&lt;&#x2F;code&gt; and &lt;code&gt;total&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;order = Order.objects.get()
&lt;&#x2F;span&gt;&lt;span&gt;expected = {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;id&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: order.id,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;items&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;description&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Coca-Cola&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;quantity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;unit_price&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;description&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Potato Chips&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;quantity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;unit_price&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2000&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;total&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2500&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, our models may look like the following:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Order(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    @property
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;total(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# this field is just a sum, depending on all the items in the current Order
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([x.total &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.items.all()])
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrderItem(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    order = models.ForeignKey(Order, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, on_delete=models.CASCADE)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# For being able to retrieve the description and the unit_price fields ?
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I add Product as a foreign key ? 
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I duplicate the fields ?
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    @property
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;total(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the total is obviouly a property that will be calculated 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# based on the number of items in the Order &amp;amp; the unit price for each item 
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;float(self.unit_price * self.quantity)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;fifthreq&quot;&gt;We should be able to update the stock depending on the number of items ordered:&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L114&quot;&gt;Line 114&lt;&#x2F;a&gt; of the tests tells us, a Product should have a method to refresh its stock:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;pyhon&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-pyhon &quot;&gt;&lt;code class=&quot;language-pyhon&quot; data-lang=&quot;pyhon&quot;&gt;&lt;span&gt;self.chips.refresh_from_db()
&lt;&#x2F;span&gt;&lt;span&gt;self.assertEqual(self.chips.stock, 8)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s update our Product model and add the new method. This method will substract the number of Product ordered from the current stock:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Product(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    description = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = models.FloatField()
&lt;&#x2F;span&gt;&lt;span&gt;    stock = models.IntegerField()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;refresh_from_db(self):
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;modules.orders.models &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;OrderItem
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        self.stock = self.stock - sum(
&lt;&#x2F;span&gt;&lt;span&gt;            oi.quantity &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;oi &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;OrderItem.objects.filter(id=self.id)
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        self.save()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;lastreq&quot;&gt;We should be able to update a Product without modifiying already made Orders:&lt;&#x2F;h2&gt;
&lt;p&gt;After reading the &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;src&#x2F;modules&#x2F;orders&#x2F;tests.py#L141&quot;&gt;Line 141&lt;&#x2F;a&gt;, we know that the fields &lt;code&gt;description and unit_price&lt;&#x2F;code&gt; will be duplicated inside the OrderItem model. During the OrderItem creation, we should copy those fields from the Product model. This task will be achieved using our serializers:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ItemSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    quantity = serializers.IntegerField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    unit_price = serializers.FloatField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    description = serializers.CharField(required=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = OrderItem
&lt;&#x2F;span&gt;&lt;span&gt;        fields = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;description&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quantity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;unit_price&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;total&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrderSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    items = ItemSerializer(many=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;create(self, validated_data):
&lt;&#x2F;span&gt;&lt;span&gt;        order = Order.objects.create()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I want to be able to access the id, the id represent the Product id
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# So, I&amp;#39;m using initial_data instead of validated_data
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# I&amp;#39;ll need to find a proper way
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;item_data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.initial_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]:
&lt;&#x2F;span&gt;&lt;span&gt;            product = Product.objects.get(id=item_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;            OrderItem.objects.create(
&lt;&#x2F;span&gt;&lt;span&gt;                id=product.id,
&lt;&#x2F;span&gt;&lt;span&gt;                order=order,
&lt;&#x2F;span&gt;&lt;span&gt;                description=product.description,
&lt;&#x2F;span&gt;&lt;span&gt;                unit_price=product.unit_price,
&lt;&#x2F;span&gt;&lt;span&gt;                quantity=item_data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;quantity&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;],
&lt;&#x2F;span&gt;&lt;span&gt;            )
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;order
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Order
&lt;&#x2F;span&gt;&lt;span&gt;        fields = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;items&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;total&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;OrdersViewSet(
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.CreateModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.ListModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;mixins.RetrieveModelMixin&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.GenericViewSet&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Order.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = OrderSerializer
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h1&gt;
&lt;p&gt;It&#x27;s been a long time since I&#x27;ve written Django and DRF code. I really enjoyed the exercise. The final result can be found &lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;nsukami&#x2F;interview&#x2F;src&#x2F;branch&#x2F;feat-1&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python src&#x2F;manage.py test src --failfast
&lt;&#x2F;span&gt;&lt;span&gt;Creating test database for alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;System check identified no issues (0 silenced).
&lt;&#x2F;span&gt;&lt;span&gt;............
&lt;&#x2F;span&gt;&lt;span&gt;----------------------------------------------------------------------
&lt;&#x2F;span&gt;&lt;span&gt;Ran 12 tests in 0.093s
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;OK
&lt;&#x2F;span&gt;&lt;span&gt;Destroying test database for alias &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;while-i-still-have-your-attention&quot;&gt;While I still have your attention:&lt;&#x2F;h1&gt;
&lt;p&gt;A &lt;a href=&quot;https:&#x2F;&#x2F;djangochat.com&#x2F;episodes&#x2F;django-unicorn-adam-hill&quot;&gt;conversation&lt;&#x2F;a&gt; with Adam Hill about writing software, the perfect settings file set up, and more. Adam is a software engineer at The Motley Fool and the author of multiple open source packages including &lt;a href=&quot;https:&#x2F;&#x2F;www.django-unicorn.com&#x2F;&quot;&gt;Django Unicorn&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The videos for the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=0kOLsFQGxyk&amp;amp;list=PLY_che_OEsX3eIKKLUKvQXfVJhCHYWATM&quot;&gt;DjangoCon Europe 2022&lt;&#x2F;a&gt; are available. Can someone tell me please when the &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;weblog&#x2F;2019&#x2F;nov&#x2F;18&#x2F;introducing-djangocon-africa&#x2F;&quot;&gt;DjangoCon Africa&lt;&#x2F;a&gt; event will be held ? So I can prepare myself ?&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;more-on-the-topic&quot;&gt;More on the topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I really hope you have learned something. To dive even more deeper in the topic, let me please recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;125&#x2F;&quot;&gt;Marketing interview&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Test-driven_development&quot;&gt;Test Driven Development&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;unittest.html&quot;&gt;Unit testing framework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Learn&#x2F;Server-side&#x2F;Django&#x2F;Testing&quot;&gt;Testing a Django web application&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;test-driven-django-development.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;Test Driven Web Development with Django&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;4.1&#x2F;topics&#x2F;testing&#x2F;overview&#x2F;&quot;&gt;Writing and running tests&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;google.aip.dev&#x2F;&quot;&gt;API Improvement Proposal&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;dsfpa&#x2F;&quot;&gt;Django single file project&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=rR4n-0KYeKQ&quot;&gt;How we write&#x2F;review code in big tech companies&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Linear regression</title>
        <published>2022-07-24T00:00:00+00:00</published>
        <updated>2022-07-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/linreg/"/>
        <id>https://nskm.xyz/posts/linreg/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/linreg/">&lt;p&gt;For the &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;Dakar Institute of Technology&lt;&#x2F;a&gt;, I give Python introductory classes. During one of my sessions I was asked about simple linear regression with Python. Let the music &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=adBfKzfemtI&quot;&gt;play&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;disclaimer_not_ds.0eb9147b61b70fa9.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;toc&quot;&gt;TOC:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#introduction&quot;&gt;Introduction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#first-solution&quot;&gt;First solution&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#reading-the-data-set&quot;&gt;Reading the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#plotting-the-data-set&quot;&gt;Plotting the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#splitting-the-data-set&quot;&gt;Splitting the data set&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#ordinary-least-squares&quot;&gt;Least squares estimates&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#mean&quot;&gt;Mean&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#variance&quot;&gt;Variance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#covariance&quot;&gt;Covariance&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#estimates&quot;&gt;Estimates&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#prediction&quot;&gt;Prediction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#error&quot;&gt;How good is the model&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#final-plot&quot;&gt;Regression line&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#class&quot;&gt;The complete program&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#statistics&quot;&gt;Another solution using the statistics module&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;linreg&#x2F;#code&quot;&gt;Just give me the code please&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;introduction&quot;&gt;Introduction:&lt;&#x2F;h1&gt;
&lt;p&gt;Simple linear regression is a commonly used type of predictive analysis. The idea of regression is to examine if a set of predictor variables do a good job in predicting an outcome variable.&lt;&#x2F;p&gt;
&lt;p&gt;Linear regression models are used in many industries such as healthcare (predicting disease from biological factors), economics (predicting growth), businesses (predicting product sales), etc ...&lt;&#x2F;p&gt;
&lt;p&gt;For simple linear regression, the relationship between the independent variable &lt;strong&gt;x&lt;&#x2F;strong&gt; and the dependent variable &lt;strong&gt;y&lt;&#x2F;strong&gt; is expressed as: &lt;code&gt;y = slope * x + intercept + noise&lt;&#x2F;code&gt;, where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;slope&lt;&#x2F;em&gt; and &lt;em&gt;intercept&lt;&#x2F;em&gt; are the regression parameters that are estimated&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;noise&lt;&#x2F;em&gt; is the variability of the data (difference between predicted and actual values of &lt;strong&gt;y&lt;&#x2F;strong&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;first-solution&quot;&gt;First solution:&lt;&#x2F;h1&gt;
&lt;p&gt;Let&#x27;s write a Python program to achieve this task. We&#x27;ll use the following &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;data set&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reading-the-data-set&quot;&gt;1. Reading the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;To read the data, we&#x27;ll write a function in charge of opening and reading the file containing our data. We assume each line will consist of an int value, followed by a tabulation and a float value. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;open the file&lt;&#x2F;li&gt;
&lt;li&gt;get all the lines except the first one (the header)&lt;&#x2F;li&gt;
&lt;li&gt;convert first column to int, convert second column to float&lt;&#x2F;li&gt;
&lt;li&gt;return a tuple containing 2 things:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;read_text(
&lt;&#x2F;span&gt;&lt;span&gt;    filename: t.Union[pathlib.Path, t.AnyStr],
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; t.Tuple[t.Collection[float], t.Collection[float]]:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(filename, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;        slines = [line.strip().split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;[li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;f.readlines()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:]]]
&lt;&#x2F;span&gt;&lt;span&gt;        nlines = [(int(x), float(y)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;slines]
&lt;&#x2F;span&gt;&lt;span&gt;        X, Y = zip(*nlines)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;X, Y
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Bonjour&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plotting-the-data-set&quot;&gt;2. Plotting the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;We&#x27;ll have to do some plotting. The following program is just one we use to setup our &lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;stable&#x2F;api&#x2F;_as_gen&#x2F;matplotlib.pyplot.subplots.html#matplotlib-pyplot-subplots&quot;&gt;plots&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;_, ax = plt.subplots()
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of our points&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first step in finding a linear regression equation is to determine if there is a relationship between the two variables. To determine if there is a relationship between x and y we can scatter plot the data set.&lt;&#x2F;p&gt;
&lt;p&gt;Scatter plots are used to observe relationships between variables. We&#x27;ll need one function to do a scatter plot: put dots on our graph and see each individual data point.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;scatter_plot(
&lt;&#x2F;span&gt;&lt;span&gt;    x: t.Collection[float], y: t.Collection[float], ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    ax.scatter(x, y, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using this function with our &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;data set&lt;&#x2F;a&gt;, we can see the following chart:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;scatter_plot.04b695a96b3966b3.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;We&#x27;ll need a function to draw a line. If we correctly find estimates for our regression parameters (slope and the intercept), we should be able to draw a line that will go through the cloud of data points:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;line_plot(a: int, b: int, ax: mpl.axes.Axes) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    y = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;x]
&lt;&#x2F;span&gt;&lt;span&gt;    ax.plot(x, y)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;splitting-the-data-set&quot;&gt;3. Splitting the data set:&lt;&#x2F;h2&gt;
&lt;p&gt;We don’t want our model to over learn from the data and perform poorly when presented data never seen before. We also need to have a mechanism to assess how well our model is generalizing. Hence, we&#x27;ll need to separate our input data into &lt;em&gt;at least&lt;&#x2F;em&gt; 2 sets: training and testing:&lt;&#x2F;p&gt;
&lt;h4 id=&quot;1-training-data-set&quot;&gt;1. Training data set:&lt;&#x2F;h4&gt;
&lt;p&gt;This is the set of data that will be used only for learning. We will use only one part of the data set to find the best parameters for our model.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;2-testing-data-set&quot;&gt;2. Testing data set:&lt;&#x2F;h4&gt;
&lt;p&gt;It would be best if we evaluate the model with new data that hasn’t been seen by the model before. So we need a set of data used to provide an evaluation without bias of the model that was fitted on the training data set.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s write a function that will split our data. We&#x27;ll keep 80% for the training and 20% for testing. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;randomly pick 20% of all the indexes in our collection&lt;&#x2F;li&gt;
&lt;li&gt;with those 20% indexes, create a list containing 20% of the collections&lt;&#x2F;li&gt;
&lt;li&gt;from those 20% indexes, create a list containing 80% of the collections&lt;&#x2F;li&gt;
&lt;li&gt;return all the sets&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;split_seq = t.Tuple[
&lt;&#x2F;span&gt;&lt;span&gt;    t.Collection[float], t.Collection[float], t.Collection[float], t.Collection[float]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;split_train_test(
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float], Y: t.Collection[float], frac: float = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.2
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; split_seq:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    indexes = list(range(len(X)))
&lt;&#x2F;span&gt;&lt;span&gt;    indexes_test = set(random.sample(indexes, int(frac * len(X))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 20% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;    X_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;    Y_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 80% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;    X_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;    Y_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;X_train, X_test, Y_train, Y_test
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s visualize how the 2 sets are rendered in a scatter plot:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;train_test_split.01769c608aeb949a.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;ordinary-least-squares&quot;&gt;4. Least squares for the slope and the intercept:&lt;&#x2F;h1&gt;
&lt;p&gt;How do we estimate our parameters α and β ? That’s the learning procedure. There are different optimization techniques to implement this part. To determine the optimum values of these two parameters, we should find the line that best fit the data set.&lt;&#x2F;p&gt;
&lt;p&gt;To determine the optimum values of these two parameters, we need to find the &lt;strong&gt;slope&lt;&#x2F;strong&gt; and the &lt;strong&gt;intercept&lt;&#x2F;strong&gt; so that when we sum all the errors between the predicted y values and the observed y values, this sum should be the least possible.&lt;&#x2F;p&gt;
&lt;p&gt;The following chart will show us all the distances (or all the differences, or all the errors) between each point on the dataset and the regression line:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plotting_OLS.9924776937a70e5c.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s see how the chart looks like when the parameters are not correctly estimated &lt;em&gt;(the regression line does not &quot;fit&quot; the data set)&lt;&#x2F;em&gt; :&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plotting_bad_OLS.3f873a7960094d1f.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;And here is the function used to plot the errors. This function will:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Take the estimated coefficients α and β&lt;&#x2F;li&gt;
&lt;li&gt;Take the list of X and the list of Y&lt;&#x2F;li&gt;
&lt;li&gt;For all points in our data set:
&lt;ul&gt;
&lt;li&gt;predict &lt;code&gt;y&lt;&#x2F;code&gt; based on α and β&lt;&#x2F;li&gt;
&lt;li&gt;draw a dashed line between 2 points: &lt;code&gt;(x, y)&lt;&#x2F;code&gt; and &lt;code&gt;(x, y_pred)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;plot_errors(
&lt;&#x2F;span&gt;&lt;span&gt;    a: float,
&lt;&#x2F;span&gt;&lt;span&gt;    b: float,
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    Y: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    ax: mpl.axes.Axes,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(X, Y):
&lt;&#x2F;span&gt;&lt;span&gt;        y_pred = a * x + b
&lt;&#x2F;span&gt;&lt;span&gt;        ax.plot([x, x], [y, y_pred], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Errors&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, linestyle=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dashed&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;the-total-error-of-this-model-is-the-sum-of-all-the-errors-for-each-point&quot;&gt;The total error of this model is the sum of all the errors for each point:&lt;&#x2F;h1&gt;
&lt;p&gt;We should sum all the errors and look for the least error. Here is the formula:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The SSE (Sum of Squared Errors) is equal to the sum of the square of Y observed - Y calculated, for all point in the data set.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;lse_formula.1b56ea6087956cd1.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;If we do all the correct &lt;a href=&quot;&#x2F;assets&#x2F;Simple_Linear_Regression_Leastsquares.pdf&quot;&gt;algebraic manipulation&lt;&#x2F;a&gt;, we should find that:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;slope_intercept_formulas.4b449a01bfa75294.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;p&gt;Seeing those formulas, those familiar with statistics already know we&#x27;ll need to define a function to calculate a mean, another function to calculate a variance and a function to calculate a covariance. βeta hat can be defined as Covariance(X, Y) &#x2F; Variance(X).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mean&quot;&gt;5.1 Mean:&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;em&gt;arithmetic&lt;&#x2F;em&gt; mean, is a measure of central tendency of a finite set of numbers: specifically, the sum of the values divided by the number of values:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;mean(lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum(lst) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;variance&quot;&gt;5.2 Variance:&lt;&#x2F;h2&gt;
&lt;p&gt;The variance  is the measure of the &lt;strong&gt;spread&lt;&#x2F;strong&gt; in a data set. The variance is a measure of how far each number in the data set is from the mean, and thus from every other number in the data set. The higher the variance, the more spread out the variables are.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;variance(lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    m = mean(lst)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([(x - m) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;lst]) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;variance: 582.8381391772394
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is 2 ways to plot the variance. We can do it manually, or we can use a &lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;stable&#x2F;api&#x2F;_as_gen&#x2F;matplotlib.pyplot.boxplot.html#matplotlib-pyplot-boxplot&quot;&gt;box plot&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plotting_variance.b71e17d987149681.png&quot; &#x2F;&gt;

&lt;&#x2F;center&gt;
  &lt;img style=&quot;display: block; margin: 0 auto&quot; src=&quot;&#x2F;assets&#x2F;jcvd_split.gif&quot; alt=&quot;Jean-Claude Van Damme split looks like a box plot&quot; title=&quot;Jean-Claude Van Damme split looks like a box plot&quot;&#x2F;&gt;
&lt;br&gt;
&lt;p&gt;Here is the function used to plot the variance:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;plot_variance(
&lt;&#x2F;span&gt;&lt;span&gt;    X: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;    Y: t.Collection[float],
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    fig: mpl.figure.Figure
&lt;&#x2F;span&gt;&lt;span&gt;    ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    _, ax = plt.subplots(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of variance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# box plot
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].boxplot([X], vert=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;, showmeans=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# mean line
&lt;&#x2F;span&gt;&lt;span&gt;    ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].axvline(x=mean(X), ymin=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, ymax=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;orange&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# distance from point to mean line
&lt;&#x2F;span&gt;&lt;span&gt;    x_mean = mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(X, Y):
&lt;&#x2F;span&gt;&lt;span&gt;        ax[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;].plot(
&lt;&#x2F;span&gt;&lt;span&gt;            [x, x_mean],
&lt;&#x2F;span&gt;&lt;span&gt;            [y, y],
&lt;&#x2F;span&gt;&lt;span&gt;            marker=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;o&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;green&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Mean&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            linestyle=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dotted&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;    plt.show()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;covariance&quot;&gt;5.3 Covariance:&lt;&#x2F;h2&gt;
&lt;p&gt;The covariance is a measure of the relationship between two variables. Covariance is the extent to which the variance in one variable depends on another variable. The higher the covariance, the stronger the relationship.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;covariance(X: t.Sequence[float], Y: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    mean_x, mean_y, length_x = mean(X), mean(Y), len(X)
&lt;&#x2F;span&gt;&lt;span&gt;    covar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(X)):
&lt;&#x2F;span&gt;&lt;span&gt;        covar += (X[i] - mean_x) * (Y[i] - mean_y)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;covar &#x2F; length_x
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;covariance: 2059.003344867359
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;estimates&quot;&gt;5.4 Estimates:&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a function for calculating the variance and another one for calculating the covariance, we can write a function that will calculate our slope and our intercept using this 2 formulas seen earlier:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;estimate_coefficients(X: t.Collection[float], Y: t.Collection[float]) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;    b1 = covariance(X, Y) &#x2F; variance(X)
&lt;&#x2F;span&gt;&lt;span&gt;    b0 = mean(Y) - b1 * mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;b0, b1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;prediction&quot;&gt;5.5. Prediction:&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have extracted our coefficients, let&#x27;s see if we can make a prediction, we&#x27;ll use the testing data set:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;b, a = estimate_coefficients(X_train, Y_train)
&lt;&#x2F;span&gt;&lt;span&gt;Y_predicted = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;X_test]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, j &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;zip(Y_test, Y_predicted):
&lt;&#x2F;span&gt;&lt;span&gt;    print(i, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, j)   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# print Y observed in testing set next to Y predicted using our coefficients
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt; python3 script.py
&lt;&#x2F;span&gt;&lt;span&gt;392.5 	 389.8167994835544
&lt;&#x2F;span&gt;&lt;span&gt;15.7 	 65.88576964183908
&lt;&#x2F;span&gt;&lt;span&gt;48.8 	 45.426967757099156
&lt;&#x2F;span&gt;&lt;span&gt;113.0 	 99.98377278307227
&lt;&#x2F;span&gt;&lt;span&gt;48.7 	 52.246568385345796
&lt;&#x2F;span&gt;&lt;span&gt;40.3 	 38.607367128852516
&lt;&#x2F;span&gt;&lt;span&gt;59.6 	 76.11517058420904
&lt;&#x2F;span&gt;&lt;span&gt;152.8 	 147.72097718079874
&lt;&#x2F;span&gt;&lt;span&gt;73.4 	 161.360178437292
&lt;&#x2F;span&gt;&lt;span&gt;21.3 	 59.066169013592436
&lt;&#x2F;span&gt;&lt;span&gt;55.6 	 48.83676807122248
&lt;&#x2F;span&gt;&lt;span&gt;194.5 	 123.85237498193551
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;error&quot;&gt;5.6. How good is our model:&lt;&#x2F;h2&gt;
&lt;p&gt;We need to able to measure how good our model is. Among the methods available to achieve this task, let&#x27;s use the most common and the most used: the &lt;a href=&quot;#&quot;&gt;Root mean squared error&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rmse&quot;&gt;RMSE:&lt;&#x2F;h3&gt;
&lt;p&gt;One way (the most common way?) to assess how well our model fits our data set is to calculate the Root Mean Squared Error. The RMSE is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the square root&lt;&#x2F;li&gt;
&lt;li&gt;of the mean&lt;&#x2F;li&gt;
&lt;li&gt;of the square of all of the errors&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s write a function to calculate the RMSE:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(actual: t.Sequence[float], predicted: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;    sum_error = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual)):
&lt;&#x2F;span&gt;&lt;span&gt;        prediction_error = predicted[i] - actual[i]
&lt;&#x2F;span&gt;&lt;span&gt;        sum_error += prediction_error**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2
&lt;&#x2F;span&gt;&lt;span&gt;    mean_error = sum_error &#x2F; float(len(actual))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we develop mutliple models, and we want to verify which one performs better:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Calculate the RMSE value for each model&lt;&#x2F;li&gt;
&lt;li&gt;The lower the RMSE value, the better the model.&lt;&#x2F;li&gt;
&lt;li&gt;A RMSE value of 0 indicate a perfect fit.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The data set we&#x27;re working with has a range: [Y_min, Y_max]. This range is important in determining whether a given RMSE value is &quot;low&quot; or &quot;high&quot;. There is no &quot;good&quot; or no &quot;bad&quot; RMSE value. It always depends on the range of the data set we&#x27;re working with.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;normalized-rmse&quot;&gt;Normalized RMSE:&lt;&#x2F;h3&gt;
&lt;p&gt;The NRMSE is the RMSE divided by Y_max - Y_min. The result will be between 0 and 1, where values closer to 0 represent better fitting models. The normalization facilitates the comparison between data sets with different scales:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(
&lt;&#x2F;span&gt;&lt;span&gt;    actual: t.Sequence[float], predicted: t.Sequence[float]
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;    mean_error = sum([(predicted[i] - actual[i])**&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual))]) &#x2F; float(len(actual))
&lt;&#x2F;span&gt;&lt;span&gt;    rmse = math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;span&gt;    nrmse = rmse &#x2F; (max(predicted) - min(predicted))
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rmse, nrmse
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt; python3 script.py 
&lt;&#x2F;span&gt;&lt;span&gt;The RMSE is 23.27666203730159
&lt;&#x2F;span&gt;&lt;span&gt;Normalized RMSE is 0.06371542339113609
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;final-plot&quot;&gt;5.7. Regression line:&lt;&#x2F;h2&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;plot_regression_line.156ebbadc8a6d8e7.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;class&quot;&gt;The complete program:&lt;&#x2F;h1&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;math
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;random
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;requests  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;matplotlib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;mpl  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;matplotlib.pyplot &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;plt  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;t
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pathlib
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;dataclasses &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;dataclass, field
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# setup plots
&lt;&#x2F;span&gt;&lt;span&gt;fig: mpl.figure.Figure
&lt;&#x2F;span&gt;&lt;span&gt;ax: mpl.axes.Axes
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;fig, ax = plt.subplots()
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_xlabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;X-coordinates &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_ylabel(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Y-coordinates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.set_title(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Graphical representation of our points&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;ax.grid(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;splits = t.Tuple[
&lt;&#x2F;span&gt;&lt;span&gt;    t.Collection[float], t.Collection[float], t.Collection[float], t.Collection[float]
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@dataclass
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;SimpleLinearRegression:
&lt;&#x2F;span&gt;&lt;span&gt;    filename: t.Union[pathlib.Path, str] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;dataset.txt&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    __X: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    __Y: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    X_train: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    Y_train: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    X_test: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    Y_test: t.Collection[float] = field(init=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__post_init__(self) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;open(self.filename, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;f:
&lt;&#x2F;span&gt;&lt;span&gt;            slines = [
&lt;&#x2F;span&gt;&lt;span&gt;                line.strip().split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\t&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;[li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;li &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;f.readlines()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;:]]
&lt;&#x2F;span&gt;&lt;span&gt;            ]
&lt;&#x2F;span&gt;&lt;span&gt;            nlines = [(float(x), float(y)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x, y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;slines]
&lt;&#x2F;span&gt;&lt;span&gt;            self.__X, self.__Y = zip(*nlines)
&lt;&#x2F;span&gt;&lt;span&gt;            self.__split_train_test()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;scatter_plot(self, ax: mpl.axes.Axes, color: str = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;red&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, label=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        ax.scatter(self.__X, self.__Y, color=color, label=label)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;line_plot(self, ax: mpl.axes.Axes) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = self.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        x = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;130&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        y = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;x]
&lt;&#x2F;span&gt;&lt;span&gt;        ax.plot(x, y, color=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;green&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__mean(self, lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum(lst) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__var(self, lst: t.Collection[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        m = self.__mean(lst)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;sum([(x - m) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;lst]) &#x2F; len(lst)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__cov(self, X: t.Sequence[float], Y: t.Sequence[float]) -&amp;gt; float:
&lt;&#x2F;span&gt;&lt;span&gt;        mean_x = self.__mean(X)
&lt;&#x2F;span&gt;&lt;span&gt;        mean_y = self.__mean(Y)
&lt;&#x2F;span&gt;&lt;span&gt;        covar = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.0
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(X)):
&lt;&#x2F;span&gt;&lt;span&gt;            covar += (X[i] - mean_x) * (Y[i] - mean_y)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;covar &#x2F; len(X)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__split_train_test(self, frac: float = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0.2&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        indexes = list(range(len(self.__X)))
&lt;&#x2F;span&gt;&lt;span&gt;        indexes_test = set(random.sample(indexes, int(frac * len(self.__X))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 20% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;        self.X_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;        self.Y_test = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# get 80% of Xs based on the indexes, do the same for Ys
&lt;&#x2F;span&gt;&lt;span&gt;        self.X_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__X) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;        self.Y_train = [n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i, n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;enumerate(self.__Y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;not in &lt;&#x2F;span&gt;&lt;span&gt;indexes_test]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;estimate_coefficients(
&lt;&#x2F;span&gt;&lt;span&gt;        self,
&lt;&#x2F;span&gt;&lt;span&gt;    ) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;        mean_x, mean_y = self.__mean(self.X_train), self.__mean(self.Y_train)
&lt;&#x2F;span&gt;&lt;span&gt;        b1 = self.__cov(self.X_train, self.Y_train) &#x2F; self.__var(  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span&gt;            self.X_train
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        b0 = mean_y - b1 * mean_x
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;b0, b1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;rmse(self) -&amp;gt; t.Tuple[float, float]:
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = self.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        predicted = [a * x + b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;self.X_test]
&lt;&#x2F;span&gt;&lt;span&gt;        actual = self.Y_test
&lt;&#x2F;span&gt;&lt;span&gt;        mean_error = sum(
&lt;&#x2F;span&gt;&lt;span&gt;            [(predicted[i] - actual[i]) ** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;range(len(actual))]  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# type:ignore
&lt;&#x2F;span&gt;&lt;span&gt;        ) &#x2F; float(
&lt;&#x2F;span&gt;&lt;span&gt;            len(actual)
&lt;&#x2F;span&gt;&lt;span&gt;        )
&lt;&#x2F;span&gt;&lt;span&gt;        rmse = math.sqrt(mean_error)
&lt;&#x2F;span&gt;&lt;span&gt;        nrmse = math.sqrt(mean_error) &#x2F; (max(predicted) - min(predicted))
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;rmse, nrmse
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# program entry point
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;main() -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        model = SimpleLinearRegression()
&lt;&#x2F;span&gt;&lt;span&gt;        model.scatter_plot(ax)
&lt;&#x2F;span&gt;&lt;span&gt;        model.line_plot(ax)
&lt;&#x2F;span&gt;&lt;span&gt;        b, a = model.estimate_coefficients()
&lt;&#x2F;span&gt;&lt;span&gt;        rmse, nrmse = model.rmse()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The slope is &lt;&#x2F;span&gt;&lt;span&gt;{a}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, the intercept is &lt;&#x2F;span&gt;&lt;span&gt;{b}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        print(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The RMSE and NRMSE are: &lt;&#x2F;span&gt;&lt;span&gt;{rmse}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and &lt;&#x2F;span&gt;&lt;span&gt;{nrmse}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        plt.show()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    main()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;The slope is 3.426108589853597, the intercept is 20.478117458572427
&lt;&#x2F;span&gt;&lt;span&gt;The RMSE and NRMSE are: 27.82841276749733 and 0.07520791645397
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;statistics&quot;&gt;Another solution, using the statistics module:&lt;&#x2F;h1&gt;
&lt;p&gt;Before jumping to big and powerful libraries such as &lt;a href=&quot;https:&#x2F;&#x2F;numpy.org&#x2F;doc&#x2F;stable&#x2F;reference&#x2F;routines.statistics.html&quot;&gt;NumPy&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;docs.scipy.org&#x2F;doc&#x2F;scipy&#x2F;reference&#x2F;stats.html&quot;&gt;SciPy&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pandas-dev&#x2F;pandas&quot;&gt;Pandas&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;raphaelvallat&#x2F;pingouin&quot;&gt;Pingouin&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;statsmodels&#x2F;statsmodels&quot;&gt;Statsmodel&lt;&#x2F;a&gt;, and all the others. We have to notice, Python provides us with a module named &lt;a href=&quot;https:&#x2F;&#x2F;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html&quot;&gt;statistics&lt;&#x2F;a&gt;. Even though the statistics module is not intended to be a competitor to the ones listed above, it&#x27;s interesting to see that inside, there is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.mean&quot;&gt;mean&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.variance&quot;&gt;variance&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.covariance&quot;&gt;covariance&lt;&#x2F;a&gt; function&lt;&#x2F;li&gt;
&lt;li&gt;even a &lt;a href=&quot;https:&#x2F;&#x2F;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;statistics.html#statistics.linear_regression&quot;&gt;linear regression&lt;&#x2F;a&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Our program will suddenly become shorter:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;statistics &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;lestat
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# load dataset
&lt;&#x2F;span&gt;&lt;span&gt;X, Y = read_text(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;dataset.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# extract coefficients
&lt;&#x2F;span&gt;&lt;span&gt;a, b = lestat.linear_regression(X, Y)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h1 id=&quot;code&quot;&gt;Source code:&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;a5n5GalczLsAAAAM&#x2F;relief-phew.gif&quot;&gt;&lt;em&gt;Phew&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;. All the cool devs today will share the source code via a Jupyter notebook stored on Github or on Colab. According to the &lt;a href=&quot;https:&#x2F;&#x2F;sfconservancy.org&#x2F;&quot;&gt;Software Freedom Conservancy&lt;&#x2F;a&gt;, we should all &lt;a href=&quot;https:&#x2F;&#x2F;sfconservancy.org&#x2F;GiveUpGitHub&#x2F;&quot;&gt;Give Up GitHub&lt;&#x2F;a&gt;. And as a free software advocate, I agree with them. The source code can be found &lt;a href=&quot;&#x2F;assets&#x2F;script.py&quot;&gt;here&lt;&#x2F;a&gt; and the data set &lt;a href=&quot;&#x2F;assets&#x2F;dataset.txt&quot;&gt;here&lt;&#x2F;a&gt;. You&#x27;re welcome.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h1&gt;
&lt;p&gt;I really hope you&#x27;ve learned something, really. Talking about the whole subject won&#x27;t be possible in this tiny article. To dive deeper and learn even more, let me please recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;datasette&#x2F;&quot;&gt;Datasette&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;matplotlib.org&#x2F;&quot;&gt;Matplotlib&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;378&#x2F;&quot;&gt;Real programmers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.sciencedirect.com&#x2F;topics&#x2F;engineering&#x2F;root-mean-squared-error&quot;&gt;Root-Mean-Squared Error&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;posit.co&#x2F;&quot;&gt;RStudio is becoming Posit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;scikit-learn.org&#x2F;stable&#x2F;modules&#x2F;generated&#x2F;sklearn.linear_model.LinearRegression.html&quot;&gt;Ordinary least squares Linear Regression with scikit learn&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Wall of Fame</title>
        <published>2022-07-04T00:00:00+00:00</published>
        <updated>2022-07-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/wall/"/>
        <id>https://nskm.xyz/wall/</id>
        
        <content type="html" xml:base="https://nskm.xyz/wall/">&lt;p&gt;Here it is, the Wall of Fame.&lt;&#x2F;p&gt;
&lt;div&gt;

    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_a_core_dev_followed_me.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_a_core_dev_followed_me.8e8245579593b0f8.jpg&quot; alt=&quot;foo&quot; title=&quot;a core dev followed me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_ashwinvis_enjoyed_my_mypy_article.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_ashwinvis_enjoyed_my_mypy_article.574457f975fea21d.png&quot; alt=&quot;foo&quot; title=&quot;ashwinvis enjoyed my mypy article&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Bash_aliases_and_functions.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Bash_aliases_and_functions.3ca5c8e249e0a455.png&quot; alt=&quot;foo&quot; title=&quot;Bash aliases and functions&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Current_status.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Current_status.d406aaba585359c1.jpg&quot; alt=&quot;foo&quot; title=&quot;Current status&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_customized_Hugo_hermit_theme.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_customized_Hugo_hermit_theme.8ae1ad770e1b0734.png&quot; alt=&quot;foo&quot; title=&quot;customized Hugo hermit theme&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Django_donator.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Django_donator.bef05b8e403fe16a.png&quot; alt=&quot;foo&quot; title=&quot;Django donator&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Djibril_being_grateful_to_me.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Djibril_being_grateful_to_me.85ea81234fa4fcbd.png&quot; alt=&quot;foo&quot; title=&quot;Djibril being grateful to me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_donkirby_reusing_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_donkirby_reusing_my_work.b8f37fd3c4e90ef5.png&quot; alt=&quot;foo&quot; title=&quot;donkirby reusing my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Dont_introduce_yourself.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Dont_introduce_yourself.6772b572b264769c.png&quot; alt=&quot;foo&quot; title=&quot;Dont introduce yourself&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Efficacite_de_la_creation.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Efficacite_de_la_creation.f366ac3a8200fb9d.png&quot; alt=&quot;foo&quot; title=&quot;Efficacite de la creation&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Emacs_massive_find_replace.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Emacs_massive_find_replace.1e9e80f82f0c3d1c.png&quot; alt=&quot;foo&quot; title=&quot;Emacs massive find replace&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Exploring_PyPolars.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Exploring_PyPolars.41f3d0e4b395fc6d.png&quot; alt=&quot;foo&quot; title=&quot;Exploring PyPolars&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Figthing_against_Mypy.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Figthing_against_Mypy.de7f548ae09b45f4.png&quot; alt=&quot;foo&quot; title=&quot;Figthing against Mypy&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_First_day_on_Mastodon.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_First_day_on_Mastodon.38d18dd00f5e2a42.png&quot; alt=&quot;foo&quot; title=&quot;First day on Mastodon&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gandi_API.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Gandi_API.2e4372b1327a02b5.png&quot; alt=&quot;foo&quot; title=&quot;Gandi API&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gandi_API_again.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Gandi_API_again.847b2968e784e92c.png&quot; alt=&quot;foo&quot; title=&quot;Gandi API again&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Gnus_once_upon_a_time.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Gnus_once_upon_a_time.8dac3ebd9b08dca3.png&quot; alt=&quot;foo&quot; title=&quot;Gnus once upon a time&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Hercules.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Hercules.8a20d66567588c01.png&quot; alt=&quot;foo&quot; title=&quot;Hercules&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_I_am_a_libertarian_leftist.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_I_am_a_libertarian_leftist.e9c7235b551f63e7.png&quot; alt=&quot;foo&quot; title=&quot;I am a libertarian leftist&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Julien_Palard_reacted_to_my_toot.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Julien_Palard_reacted_to_my_toot.02c9b51bdf84c818.png&quot; alt=&quot;foo&quot; title=&quot;Julien Palard reacted to my toot&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_kingbuzzman_reused_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_kingbuzzman_reused_my_work.8584a39a6c706df8.png&quot; alt=&quot;foo&quot; title=&quot;kingbuzzman reused my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Konami_code.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Konami_code.6edf6e64efe8be15.png&quot; alt=&quot;foo&quot; title=&quot;Konami code&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Logilab_thanks_me_for_my_work.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Logilab_thanks_me_for_my_work.374fce72f1aadf39.png&quot; alt=&quot;foo&quot; title=&quot;Logilab thanks me for my work&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_me.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_me.4e54225d2209fa39.jpg&quot; alt=&quot;foo&quot; title=&quot;me&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Mercurial_aliases.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Mercurial_aliases.7e0820558947e9a7.png&quot; alt=&quot;foo&quot; title=&quot;Mercurial aliases&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Never_knew_I_was_one_of_the_creators_of_Python_Idle.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Never_knew_I_was_one_of_the_creators_of_Python_Idle.538d0f244bd173d0.png&quot; alt=&quot;foo&quot; title=&quot;Never knew I was one of the creators of Python Idle&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Delta_Chat.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Playing_with_Delta_Chat.a3710e84afed5bb2.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Delta Chat&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Git_hooks.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Playing_with_Git_hooks.d0e265d8ee5507c9.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Git hooks&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Playing_with_Quarto.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Playing_with_Quarto.b1953381cb548b9a.png&quot; alt=&quot;foo&quot; title=&quot;Playing with Quarto&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_PR_accepted_to_typeshed_repo.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_PR_accepted_to_typeshed_repo.c7b86067ce4b5ac5.png&quot; alt=&quot;foo&quot; title=&quot;PR accepted to typeshed repo&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Proud_Emacs_Stackexchange_User.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Proud_Emacs_Stackexchange_User.c664f068e88bbb13.png&quot; alt=&quot;foo&quot; title=&quot;Proud Emacs Stackexchange User&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Proud_Emacs_user.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Proud_Emacs_user.4ea7bae1980d4fda.jpg&quot; alt=&quot;foo&quot; title=&quot;Proud Emacs user&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_PSF_member_yes.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_PSF_member_yes.8a574b3de6c0aed4.png&quot; alt=&quot;foo&quot; title=&quot;PSF member yes&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_pycon_africa_speaker.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_pycon_africa_speaker.9bfe680412266c97.jpg&quot; alt=&quot;foo&quot; title=&quot;pycon africa speaker&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Python_release_meassages_are_the_bests.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Python_release_meassages_are_the_bests.f36dffb844ed6e2f.png&quot; alt=&quot;foo&quot; title=&quot;Python release meassages are the bests&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Python_subprocess_example.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Python_subprocess_example.64a643f6d69895bb.png&quot; alt=&quot;foo&quot; title=&quot;Python subprocess example&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Reading.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Reading.e1323ecf5a19501c.jpg&quot; alt=&quot;foo&quot; title=&quot;Reading&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Rules_for_a_good_life.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Rules_for_a_good_life.d6c4185e1ab08970.jpg&quot; alt=&quot;foo&quot; title=&quot;Rules for a good life&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_sqlite_select_as_CSV.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_sqlite_select_as_CSV.1f30c9897fc1bb83.png&quot; alt=&quot;foo&quot; title=&quot;sqlite select as CSV&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Taking_stance.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Taking_stance.a14757f3246d4612.png&quot; alt=&quot;foo&quot; title=&quot;Taking stance&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Time_to_upgrade_distribution.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Time_to_upgrade_distribution.8e5e464c1d4dad81.png&quot; alt=&quot;foo&quot; title=&quot;Time to upgrade distribution&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_When_I_was_dealing_with_Paypox_wtf.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_When_I_was_dealing_with_Paypox_wtf.13ea33a6beb67dd2.png&quot; alt=&quot;foo&quot; title=&quot;When I was dealing with Paypox wtf&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_When_I_was_working_on_Vialegal.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_When_I_was_working_on_Vialegal.a471c4021dd87533.png&quot; alt=&quot;foo&quot; title=&quot;When I was working on Vialegal&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Why_I_dont_use_social.media.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Why_I_dont_use_social.media.a93363674756712b.png&quot; alt=&quot;foo&quot; title=&quot;Why I dont use social.media&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_Yasnippets_to_send_a_resume.png&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_Yasnippets_to_send_a_resume.9f43176f3144c85c.png&quot; alt=&quot;foo&quot; title=&quot;Yasnippets to send a resume&quot;&gt;
    &lt;&#x2F;a&gt;
    


    &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;wof&#x2F;pictures&#x2F;HOF_You_are_your_own_timezone.jpg&quot; target=&quot;_blank&quot;&gt;
      &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;HOF_You_are_your_own_timezone.ebbd3ce55e8bf6ff.jpg&quot; alt=&quot;foo&quot; title=&quot;You are your own timezone&quot;&gt;
    &lt;&#x2F;a&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Writing</title>
        <published>2022-05-20T00:00:00+00:00</published>
        <updated>2022-05-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/blg/"/>
        <id>https://nskm.xyz/posts/blg/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/blg/">&lt;p&gt;I often receive resumes from people looking for a job and asking me for help. To all of them I always ask: &quot;Do you have a website ?&quot;, &quot;Do you write ?&quot;. And most of the time, the answer is negative.&lt;&#x2F;p&gt;
&lt;p&gt;Writing skills are important because they allow the reader to get their first impression of who is the writer. For example: writing skills displayed in resume, cover letter email communications, website. In my humble opinion, if you&#x27;re looking for a job as a software engineer, you should have a tiny space on the internet. A space in which you write about what you experiment, what you code, what you build.&lt;&#x2F;p&gt;
&lt;p&gt;This article is an attempt to answer, why I think everybody (every software engineer)  should have a website. Or at least, why everybody should write. This article is also &lt;em&gt;kind of&lt;&#x2F;em&gt; a recap of a talk I gave for the &lt;a href=&quot;https:&#x2F;&#x2F;dit.sn&quot;&gt;Dakar Institute of Tecnology&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;wr.45c3c0f8e7026afa.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;br&gt;
&lt;br&gt;
&lt;h1 id=&quot;some-reasons-for-you-to-start-writing&quot;&gt;&lt;u&gt;Some reasons for you to start writing: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;1-improve-your-knowledge-on-a-topic&quot;&gt;&lt;em&gt;1. Improve your knowledge on a topic&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You&#x27;ll often have to write about subjects that you are not familiar with, so finding quality sources quickly is a skill you&#x27;ll develop. Before you write a single word, you need to do your research about the topic you&#x27;re writing on. The more you do research, the more you find quality sources, the more you improve your knowledge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-organize-your-thoughts&quot;&gt;&lt;em&gt;2. Organize your thoughts&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can write down more than you can easily remember, so that your capacity to consider a number of ideas at the same time is broadened. Once those ideas are written down, you can move them around, change them. You can also reject those that are finally not good enough. You will stay with good, original clearly defined ideas. And you will be able to organize and communicate them easily.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-share-your-expertise-meet-fellow-specialist-and-grow-your-knowledge&quot;&gt;&lt;em&gt;3. Share your expertise, meet fellow specialist and grow your knowledge&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Knowledge is the only thing that grows when shared. Sharing your knowledge helps you grow your knowledge by doing research, synthesizing multiple and different viewpoints. Sharing your expertise means inviting people to read you, inviting people to a new conversation. A conversation is always an occasion to meet new people and to grow as a human.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-make-money&quot;&gt;&lt;em&gt;4. Make money&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Even professions that don&#x27;t focus on writing require written communication skills. The tech industry for example, is more and more looking for people who are able to write. Those writings include things like instruction manuals, user manuals, journal articles, product descriptions, memos, wikis, documentations, etc...&lt;&#x2F;p&gt;
&lt;p&gt;You can have a look :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.indeed.com&#x2F;q-Technical-Writer-jobs.html?vjk=1e9cd66778e25548&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.upwork.com&#x2F;freelance-jobs&#x2F;technical-writing&#x2F;&quot;&gt;then here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.glassdoor.com&#x2F;Job&#x2F;technical-writer-jobs-SRCH_KO0,16.htm&quot;&gt;here again&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;careers.google.com&#x2F;jobs&#x2F;results&#x2F;93728821645058758-technical-writer-google-cloud&#x2F;?distance=50&amp;amp;q=technical%20writer&quot;&gt;also  here&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;By the way:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;realpython.com&#x2F;write-for-us&#x2F;&quot;&gt;Real Python is hiring&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;895695&#x2F;&quot;&gt;LWN is hiring too&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;em&gt;disclaimer: I&#x27;m not paid by anybody to share those job offers&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;what-are-the-topic-to-write-about&quot;&gt;&lt;u&gt;What are the topic to write about: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Coming up with writing inspiration is tough. My advice would be, &lt;strong&gt;in all the cases, always write about something you really like, or something you really enjoy.&lt;&#x2F;strong&gt; As a technical writer, you can write different kinds of articles:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-story&quot;&gt;&lt;em&gt;1. Story&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Human beings are interested in stories about people. If your reader knows you a little through your blog, the reader will remember who you are and the reader will be more interested by your technical articles. &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;ask&quot;&gt;Here&lt;&#x2F;a&gt; you&#x27;ll find different kinds of stories.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-opinion&quot;&gt;&lt;em&gt;2. Opinion&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Giving an opinion is a common way of interacting with other people. Of course you don&#x27;t simply share an opinion, you&#x27;ll also share the compelling and interesting argument that support this opinion. Also, please don&#x27;t spend your time attacking others people or spreading controversial ideas. Here is an &lt;a href=&quot;https:&#x2F;&#x2F;drewdevault.com&#x2F;2019&#x2F;12&#x2F;09&#x2F;Developers-shouldnt-distribute.html&quot;&gt;axample&lt;&#x2F;a&gt; of a shared opinion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-how-tos&quot;&gt;&lt;em&gt;3. HOW-TOs&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;An how-to is a document providing detailed and practical step-by-step guide on how to do something. In a precise, step-by-step approach, you should walk your reader through the process. You should make sure your reader can reproduce the same results by following the provided steps.  &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;howto&#x2F;pyporting.html&quot;&gt;Example&lt;&#x2F;a&gt; of an HOWTO.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-how-something-work&quot;&gt;&lt;em&gt;4. How something work&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are people &lt;em&gt;like me&lt;&#x2F;em&gt; who want to know how almost everything works. This kind of article is suitable when you want to deep dive into a very specific topic. For example, somebody already using Django sessions, may be suddenly wondering how does Django sessions work under the hood ? Here is an &lt;a href=&quot;https:&#x2F;&#x2F;eli.thegreenplace.net&#x2F;2011&#x2F;06&#x2F;24&#x2F;how-django-sessions-work-introduction&quot;&gt;article&lt;&#x2F;a&gt; showing how Django sessions work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-reviews&quot;&gt;&lt;em&gt;5. Reviews&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You have read, used, tested, played with something. In a review, your attempt will be to write about what was your experience. You&#x27;ll describe the thing, you&#x27;ll share what were your feelings about the thing, you&#x27;ll show the strengths and the weaknesses of the thing. Example of &lt;a href=&quot;https:&#x2F;&#x2F;emptysqua.re&#x2F;blog&#x2F;review-of-autotools-a-practitioners-guide&#x2F;&quot;&gt;review&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;identifying-the-target-audience&quot;&gt;&lt;u&gt;Identifying the target audience: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Identifying your intended audience will help you write effective content that achieves your goals. What are you writing ? Who are you writing for ? Knowing your audience will help you adapt your content accordingly. And if you don&#x27;t know who to write for, then the following is a serie of questions you can ask yourself:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Who am I writing for ?&lt;&#x2F;li&gt;
&lt;li&gt;What subject am I writing about ?&lt;&#x2F;li&gt;
&lt;li&gt;What does my audience already know about the subject?&lt;&#x2F;li&gt;
&lt;li&gt;What does my audience want to know about the subject?&lt;&#x2F;li&gt;
&lt;li&gt;What are the questions will my audience have?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;finding-the-audience&quot;&gt;&lt;u&gt;Finding the audience: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;For example, &lt;strong&gt;as a Python specialist&lt;&#x2F;strong&gt;, the audience can be found in different places. Pycoder weekly news want to hear from you about projects you are working on, conferences you are running, and articles you want to &lt;a href=&quot;https:&#x2F;&#x2F;pycoders.com&#x2F;submissions&quot;&gt;share&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Awesome Python is another newsletter who want you to &lt;a href=&quot;https:&#x2F;&#x2F;python.libhunt.com&#x2F;contribute&quot;&gt;contribute&lt;&#x2F;a&gt; links to blog posts, tutorials, libraries, events, videos, books.&lt;&#x2F;p&gt;
&lt;p&gt;You can als share your posts on &lt;a href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;&quot;&gt;Lobsters&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;tilde.news&#x2F;&quot;&gt;Tilde News&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;&quot;&gt;dev.to&lt;&#x2F;a&gt;, on &lt;a href=&quot;https:&#x2F;&#x2F;towardsdatascience.com&#x2F;about&quot;&gt;towardsdatascience&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;improving-your-writing&quot;&gt;&lt;u&gt;Improving your writing: &lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The following is what I recommend. In all the cases, you should find what is best for you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-practice&quot;&gt;&lt;em&gt;1. Practice&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most effective writers write every day, &lt;em&gt;at least a bit&lt;&#x2F;em&gt;.  The more you write, the more your brain form connections between neurons. Those connections get stronger the more often you write. After some time and regular practice, you no longer have to think about it. This is when writing becomes a habit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-make-time&quot;&gt;&lt;em&gt;2. Make time&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Prepare to spend between 90 minutes and 3 hours writing. But hey, 15 minutes can be useful if you do it every day. Don&#x27;t fool yourself, thinking you&#x27;ll wait for a big chunk of free time to start. That will never happen.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-when&quot;&gt;&lt;em&gt;3. When&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You are much smarter and more resilient after you have slept properly and ate. Again, find what suits you best. According to some studies, creativity peaks in the morning. My experience tells me that&#x27;s true.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-frequency&quot;&gt;&lt;em&gt;4. Frequency&lt;&#x2F;em&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Write only when you feel it.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;tools-for-writing-ssg&quot;&gt;&lt;u&gt;Tools for writing... SSG:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;You should provide yourself with the right technology. Here again, I can tell you what I do, but there are plenty of differents tools, you &lt;a href=&quot;https:&#x2F;&#x2F;app.hackernoon.com&#x2F;signup&quot;&gt;should&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pages.github.com&#x2F;&quot;&gt;always&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;jekyllrb.com&#x2F;&quot;&gt;find&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;substack.com&#x2F;for-bloggers&quot;&gt;what&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;write.as&#x2F;start&quot;&gt;suits&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.blogger.com&#x2F;about&#x2F;?bpli=1&quot;&gt;you&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;creators&quot;&gt;best&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ve choosen to build my website using a Static Site Generator (SSG). An ssg is a tool that generates a full static HTML website based on raw data (text files) and a set of templates (html, css, js files). :&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;ssg2.3f40eef587b8186f.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p style=&quot;text-align:center&quot;&gt; &lt;a href=&quot;https:&#x2F;&#x2F;devopedia.org&#x2F;static-site-generators&quot;&gt;Image source&lt;&#x2F;a&gt; &lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;why-ssg&quot;&gt;&lt;u&gt;Why SSG:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;No need for internet for writing, no need to login somewhere before writing.&lt;&#x2F;li&gt;
&lt;li&gt;no need for a particular environment, just a text editor, and a browser.&lt;&#x2F;li&gt;
&lt;li&gt;No vendor lock in, no dependency on any product for writing or migrating your content.&lt;&#x2F;li&gt;
&lt;li&gt;No need for a program to dynamically generate webpages. Web pages load faster.&lt;&#x2F;li&gt;
&lt;li&gt;No dependencies running on the server, just a web server. Increased security&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;i-m-convinced-can-you-show-me-an-example-please&quot;&gt;&lt;u&gt;I&#x27;m convinced, can you show me an example please:&lt;&#x2F;u&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;blg&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; you&#x27;re reading right now, was generated from a &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;markdown.md&quot;&gt;markdown file&lt;&#x2F;a&gt; using an SSG named &lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; and a theme named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;barlog-m&#x2F;oceanic-zen&quot;&gt;Oceanic Zen&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;br&gt;
&lt;p&gt;To finish this article, I would like to quote &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Leslie_Lamport&quot;&gt;Leslie Lamport&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&quot;If you’re thinking without writing, you only think you’re thinking.&quot;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;— Leslie Lamport&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h1 id=&quot;links&quot;&gt;Links:&lt;&#x2F;h1&gt;
&lt;p&gt;To learn more on this topic, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yieldcode.blog&#x2F;post&#x2F;why-engineers-should-write&#x2F;&quot;&gt;Why engineers should focus on writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=RnY5iJea5ww&amp;amp;t=77s&quot;&gt;Think and write, with Leslie Lamport&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=HOXwDWCoqQg&quot;&gt;Jordan Peterson on the importance of reading and writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=vyVpRiqOvt4&quot;&gt;How writing online made me a millionaire&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=tod1sraj8we&quot;&gt;How to improve your clarity of thought (&quot;writing is thinking&quot;)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=fxLFjOa-9UY&quot;&gt;Programmers that don&#x27;t blog should start right now&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=p8dve3MqQW4&quot;&gt;Benefits of writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=mmU25Xd0BGs&quot;&gt;Technical blogging for Python programmers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=aTgPJQ9Dy7Q&quot;&gt;Look deeper -- write -- the wonders of writing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=t4vKPhjcMZg&quot;&gt;What nobody tells you about documentation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Verba_volant,_scripta_manent&quot;&gt;Spoken words fly away, written words remain&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Circadian_rhythm&quot;&gt;Circadian rythm&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;links-again&quot;&gt;Links again:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;jamstack.org&#x2F;generators&#x2F;&quot;&gt;Static Site Generators&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;blog&#x2F;2022&#x2F;04&#x2F;18&#x2F;comparing-static-site-generators&#x2F;&quot;&gt;How to choose the right static site generator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola, your one-stop static site engine&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;getpublii.com&#x2F;&quot;&gt;Publii, Static Site Generator with GUI&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo, the world’s fastest framework for building websites&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git.disroot.org&#x2F;orbifx&#x2F;logarion&quot;&gt;Logarion, a suite of tools, for discovering, collecting &amp;amp; exchanging texts&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;even-more-links&quot;&gt;Even more links:&lt;&#x2F;h1&gt;
&lt;p&gt;Things that were discussed during the talk:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Literate_programming&quot;&gt;Literate programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=Mr3WTR0a5SM&quot;&gt;Knuth on Literate Programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;orgmode.org&#x2F;worg&#x2F;org-contrib&#x2F;babel&#x2F;&quot;&gt;Babel: active code in Org-mode&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pandoc.org&#x2F;&quot;&gt;Pandoc, a universal document converter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;quarto.org&#x2F;&quot;&gt;Quarto, open-source scientific and technical publishing system built on Pandoc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;wr2.c2d34d34c2abf8e1.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Function pointers</title>
        <published>2022-04-29T16:15:50+00:00</published>
        <updated>2022-04-29T16:15:50+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/fp/"/>
        <id>https://nskm.xyz/posts/fp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/fp/">&lt;p&gt;In Python, we say, functions are &lt;em&gt;first class citizen&lt;&#x2F;em&gt;. This means, functions can be used like any other objects. They can be stored inside variables, they can be passed as argument to a function, they can be returned from a function. The following is a very basic example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;square = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;lambda &lt;&#x2F;span&gt;&lt;span&gt;x: x * x
&lt;&#x2F;span&gt;&lt;span&gt;cube = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;lambda &lt;&#x2F;span&gt;&lt;span&gt;x: x * x * x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;operations = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;: square, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;: cube}
&lt;&#x2F;span&gt;&lt;span&gt;choice = int(input(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Square (1) or Cube (2) ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;value = int(input(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;print(operations[choice](value))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Let&#x27;s start with a very simple function to print out a simple &quot;hello world&quot; using a function pointer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; defining a function ptr
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a function taking no argument and returning nothing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello world!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; make our function pointer points to greet function
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; call greet function via the function pointer
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;slowly-please&quot;&gt;&lt;strong&gt;Slowly please?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The first interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a &lt;em&gt;pointer to a function&lt;&#x2F;em&gt;, named &lt;strong&gt;greet_ptr&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using the &lt;strong&gt;*&lt;&#x2F;strong&gt; notation to signify that it is a pointer.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should receive no argument: &lt;strong&gt;()&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The function should return nothing: &lt;strong&gt;void&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We need parenthesis, otherwise it becomes &lt;strong&gt;void *greet_ptr()&lt;&#x2F;strong&gt;, a function returning a &lt;strong&gt;void pointer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr();
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;greet_ptr&lt;&#x2F;code&gt; is a pointer, so it should receive &lt;em&gt;the address&lt;&#x2F;em&gt; of a function.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;greet&lt;&#x2F;code&gt; is a function, taking no argument, and returning void.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;greet_ptr()&lt;&#x2F;code&gt;: let&#x27;s execute the code living at the address stored by greet_ptr.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-if-the-function-pointed-to-takes-arguments&quot;&gt;&lt;strong&gt;What if the function pointed to, takes arguments?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Simple example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; defining a function ptr
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; make our function pointer points to greet function
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; call greet function via the function pointer
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a pointer to a function, named &lt;strong&gt;greet_ptr&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;We&#x27;re using the &lt;strong&gt;*&lt;&#x2F;strong&gt; notation to signify that it is a pointer.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should take one argument of type char pointer &lt;strong&gt;(char *)&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should return nothing: &lt;strong&gt;void&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We need parenthesis, otherwise it becomes &lt;strong&gt;void *greet_ptr(char *)&lt;&#x2F;strong&gt;, a function taking a string and returning a &lt;strong&gt;void pointer.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;greet_ptr still points to greet function.&lt;&#x2F;li&gt;
&lt;li&gt;let&#x27;s execute the code living at the address stored by greet_ptr.&lt;&#x2F;li&gt;
&lt;li&gt;This executable, &lt;code&gt;greet&lt;&#x2F;code&gt; is waiting for a parameter of type &lt;code&gt;char *&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;So the parameter &lt;code&gt;&quot;foo&quot;&lt;&#x2F;code&gt; will be passed to the function &lt;code&gt;greet&lt;&#x2F;code&gt; before execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-is-the-address-of-a-function&quot;&gt;&lt;strong&gt;What is the address of a function?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Before going further, we have to keep one thing in mind. &lt;strong&gt;a function name (label) is the address of the function.&lt;&#x2F;strong&gt; Yes. A &lt;code&gt;function name (label)&lt;&#x2F;code&gt; is converted to a &lt;code&gt;pointer to itself&lt;&#x2F;code&gt;. This means that function names can be assigned to a function pointer without using &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; to pass an address. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;greet_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;void (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;hello_ptr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(){
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;greet;
&lt;&#x2F;span&gt;&lt;span&gt;  hello_ptr = greet; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; notice, there is no &amp;amp;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(greet_ptr == hello_ptr)
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Pointers containing the same address.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  greet_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  hello_ptr(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;function-pointers-as-arguments&quot;&gt;&lt;strong&gt;Function pointers as arguments?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Remember, a function name (label) is converted to a pointer to itself, so it can be passed whenever we need a function pointer. So, we can write function taking function pointers as arguments. Example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;sayHello(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;sayHi(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name){
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hey &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; a function that takes a function and a string as parameters
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fctPtr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name) {
&lt;&#x2F;span&gt;&lt;span&gt;  fctPtr(name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greetBar(){
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  greet(sayHi, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;baz&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  greetBar();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The first interesting lines are:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;greet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fctPtr)(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;name) {
&lt;&#x2F;span&gt;&lt;span&gt;  fctPtr(name);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;We&#x27;re defining a function, named &lt;code&gt;greet&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;greet&lt;&#x2F;code&gt;  function takes 2 arguments:
&lt;ol&gt;
&lt;li&gt;a function pointer: &lt;code&gt;void (*fctPtr)(char *)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;a char pointer: &lt;code&gt;char *name&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to, should be called with an argument of type &lt;code&gt;char *&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;The function pointed to is then called: &lt;code&gt;fctPtr(name)&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;p&gt;The next interesting line is:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span&gt;greet(sayHello, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;foo&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;sayHello&lt;&#x2F;code&gt; is a function name (label)
&lt;ol&gt;
&lt;li&gt;that will be converted to a pointer to itself.&lt;&#x2F;li&gt;
&lt;li&gt;then, that pointer will be passed to &lt;code&gt;greet&lt;&#x2F;code&gt; function.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;The function &lt;code&gt;sayHello&lt;&#x2F;code&gt; will be called with &lt;code&gt;&quot;foo&quot;&lt;&#x2F;code&gt; as parameter.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;we-can-also-use-function-pointers-as-return-values&quot;&gt;&lt;strong&gt;We can also use function pointers as return values.&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;We &lt;em&gt;already&lt;&#x2F;em&gt; know a pointer can be returned from a function. A function pointer, &lt;em&gt;is&lt;&#x2F;em&gt; a &lt;em&gt;pointer&lt;&#x2F;em&gt;, so there is no big deal here.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;the-original-python-example-in-c&quot;&gt;&lt;strong&gt;The original Python example in C?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;square (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;x) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;cube (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;x) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; x;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main () {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; choice, value;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; an array of pointers to functions
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; those functions should take an int and return an int
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fp[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;])(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) = {square, cube};
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Square (1) or Cube (2) ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  scanf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;choice);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Value ?: &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  scanf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;value);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;fp[choice-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])(value));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;any-real-life-examples&quot;&gt;&lt;strong&gt;Any real life examples?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Function pointers gives C programmers, &lt;strong&gt;first-class citizen&lt;&#x2F;strong&gt;  &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;First-class_function&quot;&gt;functionality&lt;&#x2F;a&gt;: being able to pass functions as argument to other functions, and being able to return functions as value from other functions.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;more-on-the-topic&quot;&gt;&lt;strong&gt;More on the topic:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;10758811&#x2F;c-syntax-for-functions-returning-function-pointers&#x2F;10759352#10759352&quot;&gt;C syntax for functions returning function pointers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My journey to type checking 7521 lines of Python</title>
        <published>2021-11-08T03:40:17+00:00</published>
        <updated>2021-11-08T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/stcmp2/"/>
        <id>https://nskm.xyz/posts/stcmp2/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/stcmp2/">&lt;p&gt;I&#x27;ve spent the last couple of months adding &lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;type hints&lt;&#x2F;a&gt; to the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=all&amp;amp;author_username=nsukami&quot;&gt;RQL package&lt;&#x2F;a&gt;. In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp&#x2F;&quot;&gt;first&lt;&#x2F;a&gt; part, I talked you &lt;strong&gt;the reasons&lt;&#x2F;strong&gt; I think Mypy may be useful. In this part, I&#x27;ll talk about the &lt;strong&gt;process I&#x27;ve followed&lt;&#x2F;strong&gt; for adding type annotations to RQL.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recap-of-the-first-part&quot;&gt;Recap of the first part:&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Type hints are mainly useful for the &lt;a href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;talks&#x2F;python-foss&#x2F;&quot;&gt;maintainers&lt;&#x2F;a&gt;, &lt;strong&gt;&lt;em&gt;the human readers&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of &lt;strong&gt;&lt;em&gt;large code bases&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. The  people who &lt;strong&gt;read&lt;&#x2F;strong&gt; and &lt;strong&gt;debug&lt;&#x2F;strong&gt; and &lt;strong&gt;maintain&lt;&#x2F;strong&gt; large software systems &lt;strong&gt;they did not write&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The major benefit for you won&#x27;t be fewer bugs or unit tests, but the ability to more easily read and reason about code written by someone else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h2 id=&quot;outline&quot;&gt;Outline:&lt;&#x2F;h2&gt;
&lt;p&gt;First, I&#x27;ll talk about what &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#mypy&quot;&gt;Mypy&lt;&#x2F;a&gt; is and what should be it&#x27;s initial &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#initial-setup&quot;&gt;setup&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, I&#x27;ll briefly show you how I deconstructed the project (&lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#import-structure&quot;&gt;import structure&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#classes-hierarchy&quot;&gt;classes hierarchy&lt;&#x2F;a&gt;) to have another perspective of how the project is built.&lt;&#x2F;p&gt;
&lt;p&gt;I will also show 3 different ways to &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#type-hints-generation&quot;&gt;generate&lt;&#x2F;a&gt; type annotations and &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#type-information-inline-or-via-stubs&quot;&gt;where&lt;&#x2F;a&gt; I think those type annotations should reside.&lt;&#x2F;p&gt;
&lt;p&gt;Finaly, I&#x27;ll talk about things that still need to be &lt;a href=&quot;&#x2F;posts&#x2F;stcmp2&#x2F;#improvements&quot;&gt;improved&lt;&#x2F;a&gt;. Mainly, the use of &lt;code&gt;Any&lt;&#x2F;code&gt; and &lt;code&gt;type:ignore&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to jump straight to the part that&#x27;s most interesting.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;mypy&quot;&gt;Mypy:&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;existing_code.html#using-mypy-with-an-existing-codebase&quot;&gt;Mypy&lt;&#x2F;a&gt; is a library that provides optional static type checking. Unlike other programming languages, where the static type-checking takes place at compilation time, Mypy CLI does the type-check on-demand. At Logilab, the type-check was done, locally when developing, but also in the Continuous Integration pipeline, using Gitlab and Tox.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;initial-setup&quot;&gt;Initial setup:&lt;&#x2F;h2&gt;
&lt;p&gt;We need to ensure that Mypy is really being run everywhere it should be and everytime someone pushes code. We don&#x27;t want to spend time applying type annotations that won&#x27;t be checked. If you don&#x27;t check type annotations on a regular basis, they may become wrong after a certain period of time. That means:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-configuring-mypy&quot;&gt;1. Configuring Mypy&lt;&#x2F;h3&gt;
&lt;p&gt;Configuration is done using a &lt;code&gt;mypy.ini&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;532de9f4788887a4c5ff315ad9a515033979c822&#x2F;mypy.ini&quot;&gt;file&lt;&#x2F;a&gt;. At the begining, we do not want strict typing checks. Then, we&#x27;ll try to work towards more strigency, for example: &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#disallow-dynamic-typing&quot;&gt;dissallowing dynamic typing&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#untyped-definitions-and-calls&quot;&gt;disallowing untyped definitions&lt;&#x2F;a&gt;. We&#x27;re working with a legacy code base with no type definitions, let&#x27;s start with more relaxed options.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-ignoring-external-libraries&quot;&gt;2. Ignoring external libraries:&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve done it many weeks later, but I could have done it right from the beginning: tell Mypy to &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;66c3196a4d2925183b6f6c943f6368943c3e4522&quot;&gt;ignore&lt;&#x2F;a&gt; missing type hints from &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;running_mypy.html#missing-type-hints-for-third-party-library&quot;&gt;external libraries&lt;&#x2F;a&gt;. Maybe in another phase, we&#x27;ll annotate them, but for now, they should be ignored.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-set-a-tox-environment-and-ci-job&quot;&gt;3. Set a Tox environment and CI job:&lt;&#x2F;h3&gt;
&lt;p&gt;Add Tox environment to automate the boring stuff and reduce the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;tox.ini#L44&quot;&gt;boilerplate&lt;&#x2F;a&gt;. And add a Gitlab CI &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;.gitlab-ci.yml#L39&quot;&gt;job&lt;&#x2F;a&gt;. that will be in charge of running Mypy every time a new changeset is sent to the Gitlab server.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;import-structure&quot;&gt;Import structure&lt;&#x2F;h2&gt;
&lt;p&gt;I thought a diagram showing the import structure would help me understand the project. I also thought making a graph of the RQL&#x27;s import structure would help me add types a bit faster. My idea was to add annotations from bottom to top. I was wrong. More than once, after adding type annotations to a module, I was obliged to go back to where it was already done. For example, method &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;common_issues.html#incompatible-overrides&quot;&gt;overrides&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thebjorn&#x2F;pydeps&quot;&gt;PyDeps&lt;&#x2F;a&gt; is the module dependency visualization I used, the result being:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;import_structure2.svg&quot; alt=&quot;&quot; title=&quot;Right click &amp;amp; Open in new tab for better view&quot; &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you open the diagram in another tab, you&#x27;ll notice that we can see external libraries too, for example: &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;open-source&#x2F;logilab-database&quot;&gt;logilab-database&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;smurfix&#x2F;yapps&quot;&gt;yapps&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pygments&#x2F;pygments&quot;&gt;pygments&lt;&#x2F;a&gt;. Those are the ones that need to be ignored during type checking.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;classes-hierachy&quot;&gt;Classes hierachy:&lt;&#x2F;h2&gt;
&lt;p&gt;Within &lt;a href=&quot;https:&#x2F;&#x2F;pylint.org&#x2F;&quot;&gt;Pylint&lt;&#x2F;a&gt;, there is a tool named &lt;a href=&quot;https:&#x2F;&#x2F;www.logilab.org&#x2F;blogentry&#x2F;6883&quot;&gt;Pyreverse&lt;&#x2F;a&gt; that analyses Python code and extracts UML class diagrams and package dependencies. Using Pyreverse, we can have a clear view of all the classes and the relation between them:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;classes_RQL2.svg&quot; alt=&quot;&quot; title=&quot;Right click &amp;amp; Open in new tab for better view&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;type-hints-addition&quot;&gt;Type hints addition:&lt;&#x2F;h2&gt;
&lt;p&gt;There are different options for adding type annotations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-manual&quot;&gt;1. Manual&lt;&#x2F;h3&gt;
&lt;p&gt;We can do it manually: finding what are the types flowing through our program, &lt;em&gt;I&#x27;ve been there, it&#x27;s painful&lt;&#x2F;em&gt;. Literally:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Adding breakpoints here and there&lt;&#x2F;li&gt;
&lt;li&gt;Running the function or running the tests&lt;&#x2F;li&gt;
&lt;li&gt;Once inside PDB, asking the &lt;code&gt;type&lt;&#x2F;code&gt; function to tell me who is who&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;  
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;73&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;g(x):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     breakpoint()
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# a long list of non understandable code
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;76&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s assume we launched the tests and somewhere, g is called
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;77&lt;&#x2F;span&gt;&lt;span&gt;]: g([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;72&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;38&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;34&lt;&#x2F;span&gt;&lt;span&gt;])
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) type(x)  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# please, what is the type of the parameter x?
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;list&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) n
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) n
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;lt;ipython-input-&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;75&lt;&#x2F;span&gt;&lt;span&gt;-ef8444a3ab59&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;)g()
&lt;&#x2F;span&gt;&lt;span&gt;-&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb) type(y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# please, what is the type of the returned value?
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;int&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(Pdb)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;After that first run, we may be temped to write our function like one that takes a list and returns an integer:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;80&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# g takes a list and return an integer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;In [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;81&lt;&#x2F;span&gt;&lt;span&gt;]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff3333;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;g(x: list) -&amp;gt; int:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     x[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;foo&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     y = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;42
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# a long list of non understandable code
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;:     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;y
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;: 
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;I said &lt;em&gt;&quot;temped&quot;&lt;&#x2F;em&gt; because, maybe the function takes a dictionary and returns an integer. Only an extensive set of tests will tell us what&#x27;s the best answer.&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-reveal&quot;&gt;2. Reveal:&lt;&#x2F;h3&gt;
&lt;p&gt;I never really use them, but another option is to use &lt;code&gt;reveal_type&lt;&#x2F;code&gt; or &lt;code&gt;reveal_locals&lt;&#x2F;code&gt;  &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;latest&#x2F;common_issues.html#displaying-the-type-of-an-expression&quot;&gt;functions&lt;&#x2F;a&gt;. You just put a &lt;code&gt;reveal_type(expr)&lt;&#x2F;code&gt; in the code, and run it with Mypy. I never really use those 2 functions because most of the time, the revealed type is &lt;code&gt;Any&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;reveal.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-pyannotate&quot;&gt;3. PyAnnotate:&lt;&#x2F;h3&gt;
&lt;p&gt;The third &lt;em&gt;and really helpful&lt;&#x2F;em&gt; option I want to suggest is, using a tool that will give you an &lt;strong&gt;exhaustive list of suggestions&lt;&#x2F;strong&gt;, for example PyAnnotate. &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;pyannotate&quot;&gt;PyAnnotate&lt;&#x2F;a&gt; will help you list all the &lt;strong&gt;call arguments and all the return types observed at runtime&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Similar projects exists, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Instagram&#x2F;MonkeyType&quot;&gt;MonkeyType&lt;&#x2F;a&gt; created by Instagram. &lt;a href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;pytype&#x2F;&quot;&gt;Pytype&lt;&#x2F;a&gt; from Google. And &lt;a href=&quot;https:&#x2F;&#x2F;pyre-check.org&#x2F;&quot;&gt;Pyre&lt;&#x2F;a&gt; created at Facebook... &lt;em&gt;Hem, I mean, Meta&lt;&#x2F;em&gt;. I&#x27;ve used PyAnnotate just because it felt like the most easiest to setup and to use. I should probably give a try to the other options.&lt;&#x2F;p&gt;
&lt;p&gt;In the repository, there is a configuration  &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;pyannotate&#x2F;blob&#x2F;master&#x2F;example&#x2F;example_conftest.py&quot;&gt;example&lt;&#x2F;a&gt; you can use with Pytest. And after running your tests, you should find a new file named &lt;code&gt;type_info.json&lt;&#x2F;code&gt;. This file will contain a json that looks like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql&#x2F;__init__.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;line&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;128&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;func_name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;RQLHelper.compute_solutions&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;type_comments&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Insert, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, Dict[str, function], None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Delete, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Set, None, None, int) -&amp;gt; Set&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, Dict[str, function], Dict[str, str], int) -&amp;gt; Set[str]&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union, None, None, int) -&amp;gt; pyannotate_runtime.collect_types.NoReturnType&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Insert, None, None, int) -&amp;gt; pyannotate_runtime.collect_types.NoReturnType&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;samples&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;path&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql&#x2F;__init__.py&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;line&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;152&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;func_name&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;RQLHelper.simplify&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;type_comments&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;(rql.stmts.Union) -&amp;gt; None&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;samples&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;14
&lt;&#x2F;span&gt;&lt;span&gt;    },    
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Those generated type-hints are &lt;strong&gt;suggestions&lt;&#x2F;strong&gt;. You will have to tweak them first, then apply them. Once applied, you should run mypy on the updated files to verify that everything stays green.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;how-much-should-be-typed&quot;&gt;How much should be typed?&lt;&#x2F;h2&gt;
&lt;p&gt;I won&#x27;t deny, I was &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;existing_code.html#using-mypy-with-an-existing-codebase&quot;&gt;gradually&lt;&#x2F;a&gt; adding annotation to everything, everywhere. There was a feeling of endlessness.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;everywhere.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then I asked myself: &lt;em&gt;&quot;How do I know the RQL package has enough annotations? How do I know that I&#x27;ve done enough?&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I decided to &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;68f034d32bb10d8ce8c7244c361afe219cc0cca8&quot;&gt;follow&lt;&#x2F;a&gt; a path: adding Mypy &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;command_line.html#cmdoption-mypy-txt-report&quot;&gt;coverage reports&lt;&#x2F;a&gt; to the project. The lower the percentage, the happier you should be:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;Mypy Type Check Coverage Summary
&lt;&#x2F;span&gt;&lt;span&gt;================================
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Script: index
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| Module              | Imprecision       | Lines    |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| rql                 |  29.63% imprecise |  324 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql._exceptions     |   0.00% imprecise |   48 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.analyze         |  62.35% imprecise |  603 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.base            |  13.19% imprecise |  288 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.interfaces      |  11.54% imprecise |   78 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.nodes           |  24.20% imprecise | 1438 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.parser          |  77.19% imprecise | 1245 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.parser.__main__ |  19.30% imprecise |   57 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.pygments_ext    |  23.21% imprecise |   56 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.rqlgen          |   1.62% imprecise |  247 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.rqltypes        |  12.92% imprecise |  178 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.stcheck         |  49.25% imprecise |  867 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.stmts           |  30.98% imprecise | 1372 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.undo            |  27.39% imprecise |  387 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;| rql.utils           |  20.72% imprecise |  333 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;span&gt;| Total               |  38.64% imprecise | 7521 LOC |
&lt;&#x2F;span&gt;&lt;span&gt;+---------------------+-------------------+----------+
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Mypy does &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;type_inference_and_annotations.html#type-inference&quot;&gt;type inference&lt;&#x2F;a&gt;, it can guess the types of values based on the context. We see in the picture below that even though there is no type annotations, the program is not flagged as 100% imprecise:
&lt;img src=&quot;&#x2F;images&#x2F;mypy_reports_one.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I finally &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;commit&#x2F;00efe84a7e18f71cf4741dbd71736b6549dfbd0b&quot;&gt;gave up&lt;&#x2F;a&gt;, to focus on what other &lt;em&gt;Logilabians&lt;&#x2F;em&gt;, suggested: &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubicweb&#x2F;-&#x2F;snippets&#x2F;61#LC41&quot;&gt;find&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;cubicweb&#x2F;-&#x2F;issues&#x2F;218&quot;&gt;list&lt;&#x2F;a&gt; what are the &lt;strong&gt;RQL&#x27;s most imported&#x2F;used classes and functions&lt;&#x2F;strong&gt;. If those classes and functions are typed, we&#x27;ll consider we&#x27;ve reach a milestone.&lt;br &#x2F;&gt;
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;type-information-inline-or-via-stubs&quot;&gt;Type information inline or via stubs?&lt;&#x2F;h2&gt;
&lt;p&gt;Mypy gives you the ability to add type annotations to your project without ever modifying the original source code. You do it using what&#x27;s called &quot;stub files&quot;. &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;stubs.html&quot;&gt;Stub&lt;&#x2F;a&gt; files are python-like files, that only contain type-checked variable, function, and class definitions. Nothing else.&lt;&#x2F;p&gt;
&lt;p&gt;I went the other way, I&#x27;ve added type annotations directly within the original source code. In the beginning, it really felt like the easiest thing to do, having everything in the same file. But now that there is more and more types, I think I&#x27;m better improve readability.&lt;&#x2F;p&gt;
&lt;p&gt;I can for example write &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;kinds_of_types.html#type-aliases&quot;&gt;type aliases&lt;&#x2F;a&gt; whenever &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;stcheck.py#L158&quot;&gt;necessary&lt;&#x2F;a&gt;. Interesting inspiration can be found &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dropbox&#x2F;incubator-superset-internal&#x2F;blob&#x2F;4cf3f99ee881a10995212828494f0b126dd5415e&#x2F;superset&#x2F;typing.py&quot;&gt;here&lt;&#x2F;a&gt;. I can also write a snippet that will strip all those annotations and put them inside &lt;code&gt;.pyi&lt;&#x2F;code&gt; files.&lt;&#x2F;p&gt;
&lt;p&gt;From now on, I think I&#x27;ll always use stub files.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;type-checking&quot;&gt;Type Checking:&lt;&#x2F;h2&gt;
&lt;p&gt;The typing module defines a &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#typing.TYPE_CHECKING&quot;&gt;TYPE_CHECKING&lt;&#x2F;a&gt; constant that is &lt;code&gt;False&lt;&#x2F;code&gt; at runtime but treated as &lt;code&gt;True&lt;&#x2F;code&gt; while type checking. This technique is used to tell mypy something without the code being evaluated at runtime, for example resolving import cycles. Example &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;nodes.py#L51&quot;&gt;here&lt;&#x2F;a&gt;, another one &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;blob&#x2F;branch&#x2F;default&#x2F;rql&#x2F;stmts.py#L243&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;improvements&quot;&gt;Improvements:&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;1-less-any&quot;&gt;&lt;em&gt;1. Less Any:&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve been into situations where I&#x27;m not sure what should be the correct type annotation. Instead of leaving an empty type annotation, I put &lt;code&gt;Any&lt;&#x2F;code&gt;, to show other developers that the lack of a restrictive type hint is a conscious choice: either I don&#x27;t know, either I&#x27;m not sure.&lt;&#x2F;p&gt;
&lt;p&gt;Normally, I should use &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#the-any-type&quot;&gt;Any&lt;&#x2F;a&gt; only if it&#x27;s impossible for me to know what the type is going to be.&lt;&#x2F;p&gt;
&lt;p&gt;From the documentation we can &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html#the-any-type&quot;&gt;read&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Notice that no type checking is performed when assigning a value of type Any to a more precise type. For example, the static type checker did not report an error when assigning a to s even though s was declared to be of type str and receives an int value at runtime!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So, to take advantage of Mypy, I should really avoid using &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;search?group_id=23&amp;amp;nav_source=navbar&amp;amp;page=1&amp;amp;project_id=300&amp;amp;repository_ref=branch%2Fdefault&amp;amp;scope=&amp;amp;search=%3A+Any&amp;amp;search_code=true&amp;amp;snippets=false&quot;&gt;Any&lt;&#x2F;a&gt; and see if I can replace it with a proper annotation.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-less-type-ignore-comments&quot;&gt;&lt;em&gt;2. Less type: ignore comments:&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It was also impossible to progress without using &lt;code&gt;# type: ignore&lt;&#x2F;code&gt; comments, to work around the trickier cases. There are still too many &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;search?group_id=23&amp;amp;nav_source=navbar&amp;amp;page=1&amp;amp;project_id=300&amp;amp;search=%3A+ignore&quot;&gt;type: ignore&lt;&#x2F;a&gt; comments. I should have another look and see if I can improve the type annotations and remove some of those type: ignore comments.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;thanks&quot;&gt;Thanks:&lt;&#x2F;h2&gt;
&lt;p&gt;Special thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.linkedin.com&#x2F;in&#x2F;romaricst&quot;&gt;Romaric&lt;&#x2F;a&gt; who took the time to read this article and provide insightful critiques.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;more-on-this-topic&quot;&gt;More on this topic:&lt;&#x2F;h2&gt;
&lt;p&gt;Really hope you&#x27;ve learned something reading this article. As always, the topic is wide and cannot be completely covered here. To discover more about this subject, I strongly recommend the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typeddjango&#x2F;awesome-python-typing&quot;&gt;Awesome typing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=8wjntHrTGPs&quot;&gt;Liskov Substitution Principle with Johan Vergeer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;dropbox.tech&#x2F;application&#x2F;our-journey-to-type-checking-4-million-lines-of-python&quot;&gt;Our journey to type checking 4 million lines of Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;instagram-engineering.com&#x2F;static-analysis-at-scale-an-instagram-story-8f498ab71a0c&quot;&gt;Static analysis at scale: an Instagram story&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>To type or not to type? That is the question</title>
        <published>2021-08-22T03:40:17+00:00</published>
        <updated>2021-08-22T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/stcmp/"/>
        <id>https://nskm.xyz/posts/stcmp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/stcmp/">&lt;p&gt;I&#x27;ve spent the last couple of months adding &lt;a href=&quot;http:&#x2F;&#x2F;mypy-lang.org&#x2F;&quot;&gt;type hints&lt;&#x2F;a&gt; to the &lt;a href=&quot;https:&#x2F;&#x2F;forge.extranet.logilab.fr&#x2F;cubicweb&#x2F;RQL&#x2F;-&#x2F;merge_requests?scope=all&amp;amp;utf8=%E2%9C%93&amp;amp;state=all&amp;amp;author_username=nsukami&quot;&gt;RQL package&lt;&#x2F;a&gt;. In this first part, I&#x27;ll try to tell you &lt;strong&gt;when&lt;&#x2F;strong&gt; I think Mypy may be useful. In a &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp2&#x2F;&quot;&gt;second part&lt;&#x2F;a&gt;, I&#x27;ll talk about the &lt;strong&gt;how&lt;&#x2F;strong&gt;, the process I&#x27;ve followed for adding type annotations to RQL. In a last part, I&#x27;ll talk about what I&#x27;ve &lt;strong&gt;learned&lt;&#x2F;strong&gt; during the process.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;what&quot;&gt;What?&lt;&#x2F;h2&gt;
&lt;p&gt;Yes, in case you were living under a rock, here are the news: you can now write Python &lt;strong&gt;as if&lt;&#x2F;strong&gt; it was a static programming language. The official &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;&quot;&gt;PEP&lt;&#x2F;a&gt;, the official &lt;a href=&quot;http:&#x2F;&#x2F;www.mypy-lang.org&#x2F;&quot;&gt;website&lt;&#x2F;a&gt;. The official &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt;. And the official &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;python&#x2F;mypy&quot;&gt;repository&lt;&#x2F;a&gt; &lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. The &lt;a href=&quot;http:&#x2F;&#x2F;www.alorelang.org&#x2F;&quot;&gt;Alore&lt;&#x2F;a&gt; programming language, the project Mypy borrows heavily from.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;&#x2F;h2&gt;
&lt;p&gt;I remember when I was asked to work on this task. The (my) skepticism was real. Around me, reactions were mixed (confused, disgusted, interesed). I won&#x27;t deny, sometimes, I&#x27;m really wondering if I&#x27;m not better go and learn to write &lt;a href=&quot;https:&#x2F;&#x2F;ocaml.org&#x2F;learn&#x2F;&quot;&gt;OCaml&lt;&#x2F;a&gt;. Python devs are so used to quickly prototype their programs, without worrying about the types of their variables, without worrying about their return types, etc. You cannot just come and tell them that type hints are nice! They need to be convinced.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what.gif&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;More than once, the discussion ended with the &quot;explicit vs implicit&quot;, &quot;static vs dynamic&quot; holy wars, etc... I&#x27;m not trying to fuel those debates. There are pros and cons on each sides. You have to know what are the tools, what suits you best, depending on what you&#x27;re trying to achieve, depending on what is your position (user, author, maintainer).&lt;&#x2F;p&gt;
&lt;p&gt;Assuming you&#x27;re a person who already write Python programs, and you want to discover more about Mypy. If you only look at some introductory examples, they will help you understand &lt;strong&gt;what&#x27;s going on.&lt;&#x2F;strong&gt; They won&#x27;t &lt;strong&gt;convince&lt;&#x2F;strong&gt; you to jump on the type-hints band wagon. The problem with most of the examples is, they&#x27;re too short, or too basic.&lt;&#x2F;p&gt;
&lt;p&gt;No disrepect to the authors, I guess, the intent was to make things easier to understand. Short and simple to get to the point. But short and simple would barely convince you to try.&lt;&#x2F;p&gt;
&lt;p&gt;So, what are the situations in which adding types to your program will be useful, necessary, not a waste of time, priceless, meaningful? To this question, I would say this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Type hints are mainly useful for the &lt;a href=&quot;https:&#x2F;&#x2F;hynek.me&#x2F;talks&#x2F;python-foss&#x2F;&quot;&gt;maintainers&lt;&#x2F;a&gt;, &lt;strong&gt;&lt;em&gt;the human readers&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt; of &lt;strong&gt;&lt;em&gt;large code bases&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;. The  people who &lt;strong&gt;read&lt;&#x2F;strong&gt; and &lt;strong&gt;debug&lt;&#x2F;strong&gt; and &lt;strong&gt;maintain&lt;&#x2F;strong&gt; large software systems &lt;strong&gt;they did not write&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The major benefit for you won&#x27;t be fewer bugs or unit tests, but the ability to more easily read and reason about code written by someone else.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;h2 id=&quot;i-need-to-know-the-types&quot;&gt;I need to know the types:&lt;&#x2F;h2&gt;
&lt;p&gt;When you read&#x2F;debug&#x2F;maintain a large software system you&#x27;ve not written, you&#x27;ll often be in the position in which you ask yourself: &quot;Those function arguments, those variables, what are their types?&quot;, or &quot;Is this function returning something?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Remember, you were reading the source code, now you need to: modifiy the source code, add a couple of: &lt;code&gt;print(foo)&lt;&#x2F;code&gt;, &lt;code&gt;type(bar)&lt;&#x2F;code&gt;, &lt;code&gt;isinstance(baz)&lt;&#x2F;code&gt;, &lt;code&gt;qux.__class__&lt;&#x2F;code&gt;, &lt;code&gt;corge.__dict__&lt;&#x2F;code&gt;. You will probably add &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;functions.html#breakpoint&quot;&gt;breakpoints&lt;&#x2F;a&gt; here and there, to dive inside &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;pdb.html&quot;&gt;pdb&lt;&#x2F;a&gt;. Then start a REPL, then launch the program, then do some instrospection, then see what&#x27;s going on. And finally, discover that the type is not what you were expecting.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;c.tenor.com&#x2F;vZrArZhxAUoAAAAd&#x2F;hugh-laurie-facepalm.gif&quot; alt=&quot;phew&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;what-about-just-reading-the-type&quot;&gt;What about just reading the type?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s be honest, as a &lt;em&gt;reader&lt;&#x2F;em&gt;, as the one who review millions of lines of code, you just want to be able to &lt;em&gt;read&lt;&#x2F;em&gt; what are the types. And I&#x27;m not talking about &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0257&#x2F;&quot;&gt;docstrings&lt;&#x2F;a&gt;. Everybody should document their programs and write docstrings. But let&#x27;s face it, docstrings may be missing, misleading, out of date, not clear enough, etc.... Let&#x27;s compare the 2 following &lt;em&gt;shorts&lt;&#x2F;em&gt; snippets:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# What is tr ???
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ah, tr is a function. What&amp;#39;s returned by tr?
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The method seems to return a string
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Imagine having to find answers to those questions many times in a day?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr: rt.TranslationFunction) -&amp;gt; Optional[str]:
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You see that in the second snippet, all the important informations are on the function header. You don&#x27;t even read the function body and you already know that: &lt;strong&gt;&quot;get_description is a method that takes a function as its only parameter and return a string or nothing&quot;&lt;&#x2F;strong&gt;. That&#x27;s a game changer when you&#x27;re a maintainer.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not a surprise, &lt;a href=&quot;https:&#x2F;&#x2F;google.github.io&#x2F;pytype&#x2F;&quot;&gt;all&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;pyre-check.org&#x2F;&quot;&gt;the&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;pyright&quot;&gt;big&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;monkeytype.readthedocs.io&#x2F;en&#x2F;latest&#x2F;&quot;&gt;companies&lt;&#x2F;a&gt;, the ones with large software systems, are already using type annotations.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;too-verbose-and-confusing-to-read&quot;&gt;Too verbose and confusing to read?&lt;&#x2F;h2&gt;
&lt;p&gt;Adding type annotation can quickly lead to a source code that is too verbose and disgusting to read. The following is something I&#x27;ve written for RQL. I think I can do better (define type aliases, use stub files, use dataclasses, refactor, ...)&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;ScopeNode(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;BaseNode&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;__init__(self):
&lt;&#x2F;span&gt;&lt;span&gt;        self.defined_vars: Dict[str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.Variable&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = {}
&lt;&#x2F;span&gt;&lt;span&gt;        self.with_: List[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.SubQuery&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = []
&lt;&#x2F;span&gt;&lt;span&gt;        self.solutions: rt.SolutionsList = []
&lt;&#x2F;span&gt;&lt;span&gt;        self._varmaker = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.where: Optional[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.base.Node&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.having: Iterable[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.base.Node&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = ()
&lt;&#x2F;span&gt;&lt;span&gt;        self.schema: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;        self.aliases: Dict[str, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rql.nodes.ColumnAlias&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] = {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;stub-files&quot;&gt;Stub files?&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to keep your source code free of type annotations, but still want to use type annotations, you can write &lt;a href=&quot;https:&#x2F;&#x2F;www.python.org&#x2F;dev&#x2F;peps&#x2F;pep-0484&#x2F;#stub-files&quot;&gt;stub files&lt;&#x2F;a&gt;. A stub file is just a file that will contain all your variables, function signatures, &lt;em&gt;annotated&lt;&#x2F;em&gt;. &lt;strong&gt;Function bodies in stub files are just a single ellipsis.&lt;&#x2F;strong&gt; Another really short example:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# foo.py
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr):
&lt;&#x2F;span&gt;&lt;span&gt;        foo = self.get_foo()
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;foo != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;tr(foo)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Bar&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# foo.pyi &amp;lt;--- notice the extension used for stub files
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_description(self, tr: rt.TranslationFunction) -&amp;gt; Optional[str]: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h2 id=&quot;i-want-type-annotations-what-s-next&quot;&gt;I want type annotations, what&#x27;s next?&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;introduction.html#introduction&quot;&gt;Mypy&lt;&#x2F;a&gt; is a static type checker for Python. Let&#x27;s see what Mypy can to for us.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;1-generating-type-annotations&quot;&gt;1. Generating type annotations:&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s suppose you want to add type annotations to your code base. How do you proceed?&lt;&#x2F;p&gt;
&lt;p&gt;Mypy includes the &lt;a href=&quot;https:&#x2F;&#x2F;mypy.readthedocs.io&#x2F;en&#x2F;stable&#x2F;stubgen.html&quot;&gt;stubgen&lt;&#x2F;a&gt; tool that can automatically generate stub files. For example, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LeMeteore&#x2F;typeshed&#x2F;blob&#x2F;b2e1083560e223ec415fcb4dd155366e2984b2a5&#x2F;stubs&#x2F;dateparser&#x2F;dateparser&#x2F;__init__.pyi&quot;&gt;here&lt;&#x2F;a&gt; is an example of a &lt;code&gt;.pyi&lt;&#x2F;code&gt; file generated by the stubgen tool for the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scrapinghub&#x2F;dateparser&quot;&gt;dateparser&lt;&#x2F;a&gt; package.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Any, Optional
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;parse(
&lt;&#x2F;span&gt;&lt;span&gt;    date_string: Any, 
&lt;&#x2F;span&gt;&lt;span&gt;    date_formats: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    languages: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    locales: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    region: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;, 
&lt;&#x2F;span&gt;&lt;span&gt;    settings: Optional[Any] = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;): &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Keep in mind, most types annotations will default to &lt;code&gt;Any&lt;&#x2F;code&gt;. You&#x27;ll need to update &lt;code&gt;pyi&lt;&#x2F;code&gt; files and write more precise types (We agree that &lt;code&gt;Any&lt;&#x2F;code&gt; everywhere is not really useful). &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hoefling&#x2F;typeshed&#x2F;blob&#x2F;855acb4da416375b0d4791be51bf0934b0ee9e29&#x2F;stubs&#x2F;dateparser&#x2F;dateparser&#x2F;__init__.pyi&quot;&gt;Here&lt;&#x2F;a&gt; is an example of the same stub file with more precise type annotations:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;datetime
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Set, Tuple
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;dateparser.date &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;DateDataParser
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;sys.version_info &amp;gt;= (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Literal, TypedDict
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;typing_extensions &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Literal, TypedDict
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;__version__: str
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_default_parser: DateDataParser
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;_Part = Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;day&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;month&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;year&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;_ParserKind = Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;timestamp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;relative-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;custom-formats&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;absolute-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;no-spaces-time&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;_Settings(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;TypedDict&lt;&#x2F;span&gt;&lt;span&gt;, total=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;False&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    DATE_ORDER: str
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_LOCALE_DATE_ORDER: bool
&lt;&#x2F;span&gt;&lt;span&gt;    TIMEZONE: str
&lt;&#x2F;span&gt;&lt;span&gt;    TO_TIMEZONE: str
&lt;&#x2F;span&gt;&lt;span&gt;    RETURN_AS_TIMEZONE_AWARE: bool
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_DAY_OF_MONTH: Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;current&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;first&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;last&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    PREFER_DATES_FROM: Literal[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;current_period&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;future&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;past&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    RELATIVE_BASE: datetime.datetime
&lt;&#x2F;span&gt;&lt;span&gt;    STRICT_PARSING: bool
&lt;&#x2F;span&gt;&lt;span&gt;    REQUIRE_PARTS: list[_Part]
&lt;&#x2F;span&gt;&lt;span&gt;    SKIP_TOKENS: list[str]
&lt;&#x2F;span&gt;&lt;span&gt;    NORMALIZE: bool
&lt;&#x2F;span&gt;&lt;span&gt;    RETURN_TIME_AS_PERIOD: bool
&lt;&#x2F;span&gt;&lt;span&gt;    PARSERS: list[_ParserKind]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;parse(
&lt;&#x2F;span&gt;&lt;span&gt;    date_string: str,
&lt;&#x2F;span&gt;&lt;span&gt;    date_formats: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    languages: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    locales: list[str] | Tuple[str] | Set[str] | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    region: str | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    settings: _Settings | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;) -&amp;gt; datetime.datetime | &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do we agree that the :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;parse function parameters are more precise.&lt;&#x2F;li&gt;
&lt;li&gt;settings parameter is annotated with a more detailed type.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;li&gt;
&lt;li&gt;returned value is more precise.&lt;&#x2F;li&gt;
&lt;li&gt;refactoring of this function will be easier.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;2-type-checking&quot;&gt;2. Type checking:&lt;&#x2F;h3&gt;
&lt;p&gt;Before running your tests, before running your program, Mypy can detect &lt;em&gt;some types&lt;&#x2F;em&gt; of bugs:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;what2.png&quot; alt=&quot;&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I pretend &lt;code&gt;foo&lt;&#x2F;code&gt; should return a &lt;code&gt;string&lt;&#x2F;code&gt;, yet, there are cases where foo does return &lt;code&gt;None&lt;&#x2F;code&gt;. That should be fixed. Notice how, the program is running fine. Mypy will type check the program and tell you what&#x27;s wrong. Mypy won&#x27;t stop you from running the program.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion:&lt;&#x2F;h2&gt;
&lt;p&gt;Most people, including myself, don&#x27;t work on projects of this size (&lt;a href=&quot;https:&#x2F;&#x2F;dropbox.tech&#x2F;application&#x2F;our-journey-to-type-checking-4-million-lines-of-python&quot;&gt;4 million lines of Python code&lt;&#x2F;a&gt;), and hence have not to deal with the constraints of such a big code base.&lt;&#x2F;p&gt;
&lt;p&gt;Most people can perfectly write their Python programs without using type annotations. Mypy is just another tool inside your toolbox. I just want you to try, that will certainly make you a better software developer.&lt;&#x2F;p&gt;
&lt;p&gt;In the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;stcmp2&#x2F;&quot;&gt;next article&lt;&#x2F;a&gt;, I will talk a little bit more about the actual process I&#x27;ve followed for adding type annotations to the RQL package.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;to-learn-more-about-this-topic&quot;&gt;To learn more about this topic:&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;typing.html&quot;&gt;Python typing&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;tube.incognet.io&#x2F;watch?v=pJOmlFf5Je4&quot;&gt;What Python can learn from Haskell&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hTrjTAPnA_k&quot;&gt;Type hinting (and mypy)&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Which, by the way, is where you&#x27;ll find more interesting answers than what&#x27;s inside the documentation, imho.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Yes. I won&#x27;t deny, there is suddenly more lines to &lt;strong&gt;read&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Elephant in the room (part 1)</title>
        <published>2021-05-25T03:40:17+00:00</published>
        <updated>2021-05-25T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/eitr/"/>
        <id>https://nskm.xyz/posts/eitr/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/eitr/">&lt;p&gt;I&#x27;m living in a Continent where (&lt;em&gt;it sounds like&lt;&#x2F;em&gt;) nobody really cares about software freedom, data privacy, surveillance. I guess, people here are simply too busy trying to stay &lt;a href=&quot;https:&#x2F;&#x2F;www.africanews.com&#x2F;2021&#x2F;05&#x2F;29&#x2F;second-volcano-erupts-in-eastern-democratic-republic-of-congo&#x2F;&quot;&gt;alive&lt;&#x2F;a&gt;, not enough time to think about FOSS. Or maybe they&#x27;re simply confused, maybe they simply don&#x27;t know.&lt;&#x2F;p&gt;
&lt;p&gt;The topic is wide, it&#x27;s easy to digress, and I&#x27;m not sure about the best way to tackle it (&lt;em&gt;consider this to be a first draft, updates will come&lt;&#x2F;em&gt;). Let&#x27;s say it&#x27;s just an attempt, an effort, to &lt;em&gt;at least&lt;&#x2F;em&gt; address the issue.&lt;&#x2F;p&gt;
&lt;br&gt;
Okay. Let me put you in the context...
&lt;br&gt;
&lt;h1 id=&quot;will-you-be-okay-with-anybody-trying-to&quot;&gt;&lt;em&gt;Will you be okay with anybody trying to:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Fix any of your furnitures.&lt;&#x2F;li&gt;
&lt;li&gt;Take you anywhere you want.&lt;&#x2F;li&gt;
&lt;li&gt;Offer you any food you want.&lt;&#x2F;li&gt;
&lt;li&gt;Pay for all your phone, sms, mail bills.&lt;&#x2F;li&gt;
&lt;li&gt;Let you watch any movie, any film, any show.&lt;&#x2F;li&gt;
&lt;li&gt;Alert you about something every 5mn.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;and-in-exchange-the-same-person&quot;&gt;&lt;em&gt;And in exchange the same person:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Won&#x27;t ask you for any money, nothing, he&#x27;ll just keep a tiny tiny list of all:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the furnitures in your house?&lt;&#x2F;li&gt;
&lt;li&gt;the places you visit?&lt;&#x2F;li&gt;
&lt;li&gt;the foods you eat?&lt;&#x2F;li&gt;
&lt;li&gt;the conversations you had?&lt;&#x2F;li&gt;
&lt;li&gt;the movies you watched?&lt;&#x2F;li&gt;
&lt;li&gt;the time he notified you? The reason he notified you?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-we-agree-that-you-won-t-be-okay&quot;&gt;&lt;em&gt;Do we agree that you won&#x27;t be okay?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;In standard conditions for temperature and pressure&lt;&#x2F;em&gt;, you won&#x27;t be okay with anybody offering you the deal above because (&lt;em&gt;among many other reasons&lt;&#x2F;em&gt;):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;you don&#x27;t want anybody to access your &lt;strong&gt;private space&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;li&gt;you want to keep a certain level of &lt;strong&gt;autonomy&lt;&#x2F;strong&gt;, &lt;strong&gt;independance&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;you want to preserve your physical &lt;strong&gt;integrity&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;interestingly&quot;&gt;&lt;em&gt;Interestingly:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;It sounds like, nobody want me to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;put a webcam and a microphone in their house.&lt;&#x2F;li&gt;
&lt;li&gt;have the key to their house.&lt;&#x2F;li&gt;
&lt;li&gt;follow them.&lt;&#x2F;li&gt;
&lt;li&gt;take picture of them or recording them.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Yet, most of the same people are using all kinds of &lt;em&gt;&quot;privacy invading&quot;&lt;&#x2F;em&gt; technologies on a daily basis:  &lt;a href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;kateoflahertyuk&#x2F;2019&#x2F;07&#x2F;28&#x2F;apple-siri-eavesdropping-puts-millions-of-users-at-risk&quot;&gt;Siri&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.cnet.com&#x2F;home&#x2F;smart-home&#x2F;alexa-and-google-voice-assistants-app-exploits-left-it-vulnerable-to-eavesdropping&#x2F;&quot;&gt;Alexa&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;www.vrt.be&#x2F;vrtnws&#x2F;en&#x2F;2019&#x2F;07&#x2F;10&#x2F;google-employees-are-eavesdropping-even-in-flemish-living-rooms&#x2F;&quot;&gt;Google&lt;&#x2F;a&gt;. I won&#x27;t even talk about &lt;a href=&quot;https:&#x2F;&#x2F;www.dw.com&#x2F;en&#x2F;samsung-admits-smart-tv-may-be-eavesdropping&#x2F;a-18246372&quot;&gt;smart TVs&lt;&#x2F;a&gt;, nor &lt;a href=&quot;https:&#x2F;&#x2F;www.reuters.com&#x2F;article&#x2F;us-eu-facebook-dataprotection-idUSKCN1UO1B4&quot;&gt;Facebook&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;any-reasons-that-let-us-give-our-datas-to-the-tech-giants&quot;&gt;&lt;em&gt;Any reasons that let us give our datas to the Tech Giants?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;People use privacy invading software for maaaaany reasons that can be understood.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There is the &quot;I need to figure out what to eat today&quot; reason. Present all over the world, especially for the poorer people. Even more true in the Black continent.&lt;&#x2F;p&gt;
&lt;p&gt;There is the fact that &lt;strong&gt;implications&lt;&#x2F;strong&gt; (of using privacy invading software) &lt;strong&gt;are invisible&lt;&#x2F;strong&gt;, not obvious. While the benefits are immediate, concrete, observable.&lt;&#x2F;p&gt;
&lt;p&gt;Terms of Service are, &lt;em&gt;most of the time&lt;&#x2F;em&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;en&#x2F;service&#x2F;182&quot;&gt;confusing&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;fr&#x2F;service&#x2F;217&quot;&gt;difficult&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;tosdr.org&#x2F;fr&#x2F;service&#x2F;198&quot;&gt;blurry&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is also the &quot;I use it because people around me are using it&quot; reason. People are moved by &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Network_effect&quot;&gt;those around&lt;&#x2F;a&gt; them and wish to fit in as quickly as possible, as simply as possible.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Henrik_Ibsen&quot;&gt;Henrik Ibsen&lt;&#x2F;a&gt; said &lt;em&gt;&quot;A thousand words leave not the same deep impression as does a single deed&quot;&lt;&#x2F;em&gt;. And I definitely agree with him:&lt;&#x2F;p&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;vicious-cycle.42e644fb1aedfddb.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;theconversation.com&#x2F;heres-how-tech-giants-profit-from-invading-our-privacy-and-how-we-can-start-taking-it-back-120078&quot;&gt;Source&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-you-know-that&quot;&gt;&lt;em&gt;Do you know that:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ol&gt;
&lt;li&gt;Your right to physical integrity was &lt;em&gt;already&lt;&#x2F;em&gt; affirmed in 1222, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Kouroukan_Fouga#Contents&quot;&gt;inside the Manden Charter&lt;&#x2F;a&gt;, article 5:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Everybody has a right to life and to the &lt;strong&gt;preservation of physical integrity&lt;&#x2F;strong&gt;. [...]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Your right to privacy was affirmed in 1948 by the &lt;a href=&quot;https:&#x2F;&#x2F;www.un.org&#x2F;en&#x2F;about-us&#x2F;universal-declaration-of-human-rights&quot;&gt;Universal Declaration of Human Rights&lt;&#x2F;a&gt;, article 12:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;No one shall be subjected to &lt;strong&gt;arbitrary interference&lt;&#x2F;strong&gt; with his privacy, family, home or correspondence, nor to attacks upon his honour and reputation. Everyone has the right to the protection of the law against such interference or attacks.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;Within the &lt;a href=&quot;https:&#x2F;&#x2F;www.echr.coe.int&#x2F;documents&#x2F;convention_eng.pdf&quot;&gt;European Convention on Human Rights&lt;&#x2F;a&gt;, in the article 8, we can read:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Right to respect for private and family life.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Everyone has the right to respect for his private and family life, his home and his correspondence.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;There shall be &lt;strong&gt;no interference by a public authority&lt;&#x2F;strong&gt; with the exercise of this right except such as is in accordance with the law and is necessary in a democratic society in the interests of national security, public safety or the economic well-being of the country, for the prevention of disorder or crime, for the protection of health or morals, or for the protection of the rights and freedoms of others.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.law.cornell.edu&#x2F;constitution&quot;&gt;U.S. constitution&lt;&#x2F;a&gt; &lt;a href=&quot;https:&#x2F;&#x2F;constitution.congress.gov&#x2F;constitution&#x2F;amendment-4&#x2F;&quot;&gt;Fourth Amendment&lt;&#x2F;a&gt; states that:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The right of the people to be secure in their persons, houses, papers, and effects, &lt;strong&gt;against unreasonable searches and seizures&lt;&#x2F;strong&gt;, shall not be violated, and no Warrants shall issue, but upon probable cause, supported by Oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;The point seems to be: &lt;strong&gt;Every human being has a right to privacy, and this right should not be violated.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;what-is-privacy&quot;&gt;&lt;em&gt;What is privacy?&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I was not able to find a fixed, simple, perfect, static definition of &lt;a href=&quot;https:&#x2F;&#x2F;www.nolo.com&#x2F;dictionary&#x2F;right-to-privacy-term.html&quot;&gt;privacy&lt;&#x2F;a&gt;. The definition may vary from one country to another, from one constitution to another, from one period of time to another.&lt;&#x2F;p&gt;
&lt;p&gt;But I guess we can agree that privacy is any information that intrudes into the intimacy of the individual. &lt;em&gt;Right&lt;&#x2F;em&gt;? Privacy is that thing which is essential to the protection of our dignity as Human Being. &lt;em&gt;Right&lt;&#x2F;em&gt;?  Anything that is directly related to :&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;your personal space, your house, your image,&lt;&#x2F;li&gt;
&lt;li&gt;your financial status, your medical status,&lt;&#x2F;li&gt;
&lt;li&gt;your religious, political, &lt;em&gt;or even sexual&lt;&#x2F;em&gt; orientations,&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Privacy is the fundamental way to protect yourself&lt;&#x2F;em&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;some-of-the-solutions-we-can-explore&quot;&gt;&lt;em&gt;Some of the solutions we can explore:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;How do we defend ourselves and our friends from privacy invading technologies? What can we do to safeguard our personal privacy. What are the ways we can use to better protect ourselves when going online? What are the alternatives to the privacy invading software? I&#x27;ll talk about the solutions in the next &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;wmdop&#x2F;&quot;&gt;article&lt;&#x2F;a&gt; (&lt;em&gt;coming soon&lt;&#x2F;em&gt;).&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;no-i-m-not&quot;&gt;&lt;em&gt;No, I&#x27;m not:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;Saying that I&#x27;ve all the answers.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that you should do as I say.&lt;&#x2F;li&gt;
&lt;li&gt;Asking you to close all your accounts.&lt;&#x2F;li&gt;
&lt;li&gt;Asking you to go back to the stone age.&lt;&#x2F;li&gt;
&lt;li&gt;Trying to make you affraid of technology.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that I&#x27;ve found all the alternatives.&lt;&#x2F;li&gt;
&lt;li&gt;Saying that migrating from privacy invading software will be an easy task.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;what-i-m-asking-you&quot;&gt;&lt;em&gt;What I&#x27;m asking you:&lt;&#x2F;em&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Completely shuting down all the Tech Giants won&#x27;t be an easy task. It cannot be done within the snap of a finger &lt;em&gt;(I wish it &lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=TWB31WFomz4&quot;&gt;could&lt;&#x2F;a&gt;)&lt;&#x2F;em&gt;. Let&#x27;s stay optimistic, there is still some actionable steps we can take to help:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Ask yourself :
&lt;ul&gt;
&lt;li&gt;Why are you using those platforms?&lt;&#x2F;li&gt;
&lt;li&gt;What are the services you really need?&lt;&#x2F;li&gt;
&lt;li&gt;Is there any alternatives? (Respecting your privacy).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Be aware:
&lt;ul&gt;
&lt;li&gt;of the risks, of the pros &amp;amp; cons.&lt;&#x2F;li&gt;
&lt;li&gt;that if it&#x27;s free, you&#x27;re probably the &lt;a href=&quot;https:&#x2F;&#x2F;ethannonsequitur.com&#x2F;wp-content&#x2F;uploads&#x2F;2011&#x2F;09&#x2F;facebook-and-you-pigs.jpg&quot;&gt;product&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Ask for more:
&lt;ul&gt;
&lt;li&gt;Transparency to all those platforms.&lt;&#x2F;li&gt;
&lt;li&gt;Regulation &amp;amp; protection to your leaders, your governments.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Spark conversation, everywhere.&lt;&#x2F;strong&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h1 id=&quot;interesting-links&quot;&gt;Interesting links:&lt;&#x2F;h1&gt;
&lt;p&gt;This topic is too wide to be covered entirely in this tiny article. I really hope you&#x27;re learned something. I strongly recommend the following links for a better exploration and understanding of the topic.&lt;&#x2F;p&gt;
&lt;p&gt;The following is a list of resources you should &lt;em&gt;download, browse &amp;amp; share&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Enemy of the State&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.killswitchthefilm.com&#x2F;&quot;&gt;Killswitch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;yewtu.be&#x2F;watch?v=ZHl0WI32XkY&quot;&gt;We are legion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Terms and conditions may apply&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;citizenfourfilm.com&#x2F;&quot;&gt;Citizenfour&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.thesocialdilemma.com&#x2F;&quot;&gt;Social dilemma&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.thegreathack.com&#x2F;&quot;&gt;The great hack&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;snowdenfilm.com&#x2F;&quot;&gt;Snowden&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yewtu.be&#x2F;watch?v=YXmMtbgdces&quot;&gt;Nos données personnelles valent de l&#x27;or&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;activism.net&#x2F;cypherpunk&#x2F;manifesto.html&quot;&gt;A Cypherpunk&#x27;s Manifesto&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yewtu.be&#x2F;watch?v=IWzmYE60_dc&quot;&gt;Macron trahit la « start-up nation », les gafam raflent la mise&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thanks&quot;&gt;Thanks:&lt;&#x2F;h1&gt;
&lt;p&gt;Special &lt;a href=&quot;https:&#x2F;&#x2F;www.meme-arsenal.com&#x2F;memes&#x2F;379eb2a9776a3bbaac72286e3d857cbf.jpg&quot;&gt;thanks&lt;&#x2F;a&gt; to Orbifx, &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.scot&#x2F;@orbifx&quot;&gt;the Nature&#x27;s emissary&lt;&#x2F;a&gt;, and  &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@travis_kalanick&quot;&gt;Travis Kalanick&lt;&#x2F;a&gt;. They both gave me interesting ideas to help me finish this article.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h1 id=&quot;do-not-forget&quot;&gt;Do not forget:&lt;&#x2F;h1&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;real-power-is-people.815a6f16ec1b60fc.jpg&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Django single file project. Again</title>
        <published>2020-07-10T01:09:16+00:00</published>
        <updated>2020-07-10T01:09:16+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/dsfpa/"/>
        <id>https://nskm.xyz/posts/dsfpa/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/dsfpa/">&lt;p&gt;This article is a follow up on the &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;dsfp&#x2F;&quot;&gt;one&lt;&#x2F;a&gt; I&#x27;ve written few years
ago. Special shoutout and thanks and hugs and kudos to &lt;a href=&quot;http:&#x2F;&#x2F;buzzi.me&#x2F;&quot;&gt;Javier
Buzzi&lt;&#x2F;a&gt; for taking the time to &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;kingbuzzman&#x2F;d7859d9734b590e52fad787d19c34b52&quot;&gt;improve&lt;&#x2F;a&gt; the original script.&lt;&#x2F;p&gt;
&lt;p&gt;TL;DR: &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;ee784daff75aae62&quot;&gt;download old version&lt;&#x2F;a&gt; &amp;amp; &lt;a href=&quot;https:&#x2F;&#x2F;bin.nskm.xyz&#x2F;pastes&#x2F;c4434741122bec0f&quot;&gt;download new version&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;br &#x2F;&gt;
&lt;h2 id=&quot;very-important-disclaimer&quot;&gt;VERY IMPORTANT DISCLAIMER&lt;&#x2F;h2&gt;
&lt;p&gt;The content associated with mlvin.xyz may be very offensive to some people. I&#x27;ve lost the ownership of mlvin.xyz a very long time ago, sad situation. I&#x27;m not anymore linked to this domain name, nor to the content hosted on this website. &lt;em&gt;By the way F*** OVH&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-are-those-improvements&quot;&gt;What are those improvements?&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;application-label&quot;&gt;Application label?&lt;&#x2F;h3&gt;
&lt;p&gt;Our models are not defined as in a classical Django application. So,
each model should declare which app it belongs to. You can read more
about app_label Meta option &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;3.0&#x2F;ref&#x2F;models&#x2F;options&#x2F;#django.db.models.Options.app%5Flabel&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The problem with the first script was duplication:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Author(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Book(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    author = models.ForeignKey(Author, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;books&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;400&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want to define app_label once and for all our models:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# The current name of the file, which will be the name of our app
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL, _ = os.path.splitext(os.path.basename(os.path.abspath(__file__)))
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, we need to overwrite the Django function in charge of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;looking for an application configuration&lt;&#x2F;li&gt;
&lt;li&gt;attach the model to the found&#x2F;correct application configuration.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This function is named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;django&#x2F;apps&#x2F;registry.py#L243&quot;&gt;get_containing_app_config&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;get_containing_app_config(module):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;module == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__main__&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# if inside single file project,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# retrieve the application configuration using APP_LABEL variable
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;apps.get_app_config(APP_LABEL)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# otherwise, do as you always do
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;apps._get_containing_app_config(module)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# save the original function
&lt;&#x2F;span&gt;&lt;span&gt;apps._get_containing_app_config = apps.get_containing_app_config
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# ask Django to use our custom function
&lt;&#x2F;span&gt;&lt;span&gt;apps.get_containing_app_config = get_containing_app_config
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;migrations-folder&quot;&gt;Migrations folder?&lt;&#x2F;h3&gt;
&lt;p&gt;There is a Django settings named &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;django&#x2F;conf&#x2F;global_settings.py#L616&quot;&gt;MIGRATION_MODULE&lt;&#x2F;a&gt;. According to the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;django&#x2F;django&#x2F;blob&#x2F;stable&#x2F;3.0.x&#x2F;docs&#x2F;ref&#x2F;settings.txt#L2021&quot;&gt;documentation&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A dictionary specifying the package where migration modules can be found on a per-app basis. The  default value of this setting is an empty dictionary, but the default package name for migration modules is ``migrations``.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;In the first version of the script, all the migrations were put in a folder named &lt;code&gt;migrations&lt;&#x2F;code&gt;. With the following configuration, we can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;name the migration folder how we want.&lt;&#x2F;li&gt;
&lt;li&gt;make sure that we have one migration folder per application.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Where migrations folder need to be created
&lt;&#x2F;span&gt;&lt;span&gt;APP_MIGRATION_MODULE = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;_migrations&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;APP_MIGRATION_PATH = os.path.join(BASE_DIR, APP_MIGRATION_MODULE)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create the migration folder
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# and a __init__.py file if necessary:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if not &lt;&#x2F;span&gt;&lt;span&gt;os.path.exists(APP_MIGRATION_PATH):
&lt;&#x2F;span&gt;&lt;span&gt;    os.makedirs(APP_MIGRATION_PATH)
&lt;&#x2F;span&gt;&lt;span&gt;    open(os.path.join(APP_MIGRATION_PATH, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__init__.py&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;w&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).close()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We also took the time to update the Django settings, somewhere inside the call to &lt;code&gt;settings.configure function&lt;&#x2F;code&gt;, you&#x27;ll find:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Django needs to be told where is the migration module
&lt;&#x2F;span&gt;&lt;span&gt;MIGRATION_MODULES={APP_LABEL: APP_MIGRATION_MODULE},
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;fake-modules&quot;&gt;Not so fake modules?&lt;&#x2F;h3&gt;
&lt;p&gt;A correctly configured Django application should normally have a &lt;code&gt;model modules&lt;&#x2F;code&gt;, a &lt;code&gt;urls modules&lt;&#x2F;code&gt; and a &lt;code&gt;tests module&lt;&#x2F;code&gt;. Python provides us with an interesting  &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;types.html#types.ModuleType&quot;&gt;class&lt;&#x2F;a&gt;: &lt;code&gt;types.ModuleType&lt;&#x2F;code&gt;, that will help us create a module, &lt;em&gt;you guessed it&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Used so you can do &amp;#39;from &amp;lt;name of file&amp;gt;.models import *&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;models_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.models&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;tests_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.tests&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;urls_module = ModuleType(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;.urls&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;% (APP_LABEL))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# we created the urlpatterns list earlier,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s attach this variable to the urls_module:
&lt;&#x2F;span&gt;&lt;span&gt;urls_module.urlpatterns = urlpatterns
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# A model module needs to have classes that inherits from models.Model
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# let&amp;#39;s correctly add all our models we defined earlier
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# as attributes to the models_module:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;variable_name, value &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;list(locals().items()):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# We are only interested in models
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;inspect.isclass(value) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;and &lt;&#x2F;span&gt;&lt;span&gt;issubclass(value, models.Model):
&lt;&#x2F;span&gt;&lt;span&gt;        setattr(models_module, variable_name, value)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Setup the fake modules
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[models_module.__name__] = models_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[urls_module.__name__] = urls_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[APP_LABEL].models = models_module
&lt;&#x2F;span&gt;&lt;span&gt;sys.modules[APP_LABEL].urls = urls_module
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;going-further&quot;&gt;Going further?&lt;&#x2F;h3&gt;
&lt;p&gt;I really hope you&#x27;ve learned something, I did \o&#x2F;. You may want to browse some of the gists kept by &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;search?q=mlvin&quot;&gt;Javier Buzzi&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;
You may also be really interested by the work done for  &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zenwalker&#x2F;django-micro&quot;&gt;django-micro&lt;&#x2F;a&gt; a lightweight wrapper around Django that turns it into a microframework.
&lt;br&gt;&lt;br&gt;
If you have any kind of interesting improvements, advices, suggestions, please send me an email, or post a comment on &lt;a href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@lemeteore&#x2F;104489090816400323&quot;&gt;Mastodon&lt;&#x2F;a&gt;. &lt;em&gt;Still not took the time to install a comment system, shame on me&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;o&#x2F;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Free and Open Source Software</title>
        <published>2017-04-04T00:00:00+00:00</published>
        <updated>2017-04-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/foss/"/>
        <id>https://nskm.xyz/posts/foss/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/foss/">&lt;p&gt;I&#x27;m often asked why do I prefer to use free software in places (Dakar, Libreville, Kinshasa, ...), where basically every human being is using closed source and proprietary software? Here are some of the reasons.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;not-being-able-to-pay-for-a-license&quot;&gt;&lt;strong&gt;Not being able to pay for a license&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Learning informatics was equivalent to installing a bunch of software requiring me to pay for a license. And coming from a very modest family, paying for a license was not an option. I&#x27;ve never really been able to explain to my parent that&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I need to pay, via internet, using a credit card&lt;&#x2F;li&gt;
&lt;li&gt;a company located somewhere in the world, I don&#x27;t even know where&lt;&#x2F;li&gt;
&lt;li&gt;to get the permission to use such an abstract thing like a software&lt;&#x2F;li&gt;
&lt;li&gt;for some time, then I&#x27;ll have to pay again, to renew the permission&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;tired-of-looking-for-the-crack&quot;&gt;&lt;strong&gt;Tired of looking for the crack&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Not being able to pay for the license, the remaining choice was to look for the crack. that was the most easy way to get the software you want to use. But in the mean time, That was a very difficult task, always browsing the internet, looking for the product keys, the key generator, the patch, the full activator, etc... It was time consuming, and boring as editors are always trying to make it more and more difficult.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;trying-to-be-a-good-citizen&quot;&gt;&lt;strong&gt;Trying to be a good citizen&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Even if they should, most people often do not feel bad about using cracked software. After all, there were no physical harm, no shoplifting, no unlawful entry into a building, no indiscriminate taking of goods. Why feeling bad about it?&lt;&#x2F;p&gt;
&lt;p&gt;Theft, from &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Theft&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;In common usage, a theft is the illegal taking of another person&#x27;s property or services without that person&#x27;s permission or consent with the intent to deprive the rightful owner of it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Property, from &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Property#Types_of_property&quot;&gt;Wikepedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Important widely recognized types of property include real property (the combination of land and any improvements to or on the land), personal property (physical possessions belonging to a person), private property (property owned by legal persons, business entities or individual natural persons), public property (state owned or publicly owned and available possessions) and intellectual property (exclusive rights over artistic creations, inventions, etc.), although the last is not always as widely recognized or enforced.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
Above are the main reasons why I chose free and open source software. You can actually close this page, and go back to your awesome life, **thanks for reading**. But there is more.
&lt;br&gt;
&lt;h3 id=&quot;the-free-and-open-source-software-philosophy-promotes-values-that-go-beyond-software&quot;&gt;&lt;strong&gt;The free and open source software philosophy promotes values that go beyond software&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;own&lt;&#x2F;em&gt; an item, &lt;em&gt;to use it for any purpose&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;study&lt;&#x2F;em&gt; how this item is made&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;customize&lt;&#x2F;em&gt; this item&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s about the right to &lt;em&gt;share&lt;&#x2F;em&gt; the item modified or not, with whoever you want&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;h3 id=&quot;fine-can-we-have-some-real-life-examples-please&quot;&gt;&lt;strong&gt;Fine, can we have some real life examples please?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;From &lt;a href=&quot;https:&#x2F;&#x2F;www.softwareheritage.org&#x2F;mission&#x2F;heritage&#x2F;&quot;&gt;Software Heritage&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Software controls the electronic equipment embedded in the machines we use to travel, communicate, trade and exchange. Software is just crucial for the proper operation of every large organizations. Software has enabled the emergence of new forms of social and political organizations. Software is essential to understand our society.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Maybe it&#x27;s not perceptible enough, but free and open source software is already &lt;a href=&quot;http:&#x2F;&#x2F;embedded-computing.com&#x2F;articles&#x2F;open-source-software-everywhere&#x2F;&quot;&gt;everywhere&lt;&#x2F;a&gt;. Here you are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Aerospace: Open Source Software projects from &lt;a href=&quot;https:&#x2F;&#x2F;code.nasa.gov&#x2F;&quot;&gt;NASA&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Automotive: &lt;a href=&quot;https:&#x2F;&#x2F;www.automotivelinux.org&quot;&gt;AGL&lt;&#x2F;a&gt; group, including lots of &lt;a href=&quot;https:&#x2F;&#x2F;www.automotivelinux.org&#x2F;about&#x2F;members&quot;&gt;automakers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Robotics: &lt;a href=&quot;https:&#x2F;&#x2F;www.osrfoundation.org&#x2F;osrf-projects&#x2F;&quot;&gt;Open Source Robotics Foundation&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Healthcare: &lt;a href=&quot;http:&#x2F;&#x2F;www.open-emr.org&#x2F;&quot;&gt;Open-EMR&lt;&#x2F;a&gt;, &lt;a href=&quot;http:&#x2F;&#x2F;openmrs.org&#x2F;&quot;&gt;OpenMRS&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Education: &lt;a href=&quot;http:&#x2F;&#x2F;open-sankore.org&#x2F;en&quot;&gt;Open Sankoré&lt;&#x2F;a&gt;, an interactive whiteboard software.&lt;&#x2F;li&gt;
&lt;li&gt;Films: &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=eRsGyueVLvQ&quot;&gt;Sintel&lt;&#x2F;a&gt;, and many other open movies by &lt;a href=&quot;https:&#x2F;&#x2F;www.blender.org&#x2F;features&#x2F;projects&#x2F;&quot;&gt;Blender Foundation&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
It is no more about software, it is about **openess and freedom**.
&lt;br&gt;
The topic is actually very huge and deep, I&#x27;ve not even mentioned privacy, nor surveillance. I obviously won&#x27;t be able to cover the whole thing. 
&lt;h3 id=&quot;for-those-who-want-to-go-further-i-strongly-recommands-the-following-links&quot;&gt;&lt;strong&gt;For those who want to go further, I strongly recommands the following links:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=xKsR5jWl1Tk&quot;&gt;Threats of data mining&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=8vOF8VsUwbA&quot;&gt;Freedom in the cloud&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;modernfarmer.com&#x2F;2016&#x2F;07&#x2F;right-to-repair&#x2F;&quot;&gt;Right to fix their own dang tractors&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;opensource.com&#x2F;article&#x2F;17&#x2F;4&#x2F;become-open-source-sustainer&quot;&gt;Why you should become an open source sustainer&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;anybox.fr&#x2F;blog&#x2F;pourquoi-l-open-source&quot;&gt;Pourquoi l&#x27;open source&lt;&#x2F;a&gt; (French)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Threads</title>
        <published>2017-03-08T04:30:25+00:00</published>
        <updated>2017-03-08T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/an-overwiew-on-threads/"/>
        <id>https://nskm.xyz/posts/an-overwiew-on-threads/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/an-overwiew-on-threads/">&lt;p&gt;I&#x27;ve written something about &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;processes&lt;&#x2F;a&gt; Let&#x27;s write some notes about threads. This is not really an introduction to threads. It&#x27;s more like a little bit of introspection, so we can have an interesting perspective of what are threads.&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;what-s-really-a-thread&quot;&gt;&lt;strong&gt;What&#x27;s really a thread?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Processes each have their own address space. Threads exist as subsets of a process. Threads are just multiple workers in the same &lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;virtual address space&lt;&#x2F;a&gt; all threads in a process share the same memory. They can also share open files and other resources. Within that VAS, each thread has its own ID, its own stack, its own program counter, its own independent flow of control, its own registers set. A thread is just a &lt;strong&gt;context of execution&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;threads-example.gif&quot; alt=&quot;Threads&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;em&gt;Image from &lt;a href=&quot;http:&#x2F;&#x2F;mooneegee.blogspot.sn&#x2F;2015&#x2F;01&#x2F;os-thread.html&quot;&gt;mooneegee.blogspot.sn&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Next is a c script spawning two &lt;em&gt;posix&lt;&#x2F;em&gt; threads:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#define _GNU_SOURCE
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;pthread.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; sleep
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;syscall.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void * &lt;&#x2F;span&gt;&lt;span&gt;say_hello(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void* &lt;&#x2F;span&gt;&lt;span&gt;data){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;str = (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char*&lt;&#x2F;span&gt;&lt;span&gt;)data;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; howmany = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; r = (rand() % &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pid_t thread_id = syscall(__NR_gettid);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while&lt;&#x2F;span&gt;&lt;span&gt;(howmany &amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    sleep(r);
&lt;&#x2F;span&gt;&lt;span&gt;    howmany = howmany - &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;, &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,str);
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;from thread &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; and process &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%u&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;           thread_id, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return NULL&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_t t1,t2;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(getpid() &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;unable to get pid&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The main process id is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_create(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,say_hello,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;howdy&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_create(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;,say_hello,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_join(t1,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  pthread_join(t2,&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;If we &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;strace&lt;&#x2F;a&gt; the execution of our c script:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ strace -f .&#x2F;bin&#x2F;how_to_thread
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output will display lots of informations. And for what we are doing, the most interesting lines will look like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;clone(child_stack=0x7f30fa9b8ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f30fa9b99d0, tls=0x7f30fa9b9700, child_tidptr=0x7f30fa9b99d0) = 7450
&lt;&#x2F;span&gt;&lt;span&gt;Process 7450 attached
&lt;&#x2F;span&gt;&lt;span&gt;[pid  7449] clone(child_stack=0x7f30fa1b7ff0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f30fa1b89d0, tls=0x7f30fa1b8700, child_tidptr=0x7f30fa1b89d0) = 7451
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;the-clone-system-call&quot;&gt;&lt;strong&gt;The clone() system call:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;processes-introduction&#x2F;&quot;&gt;Processes&lt;&#x2F;a&gt; are created with the &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;fork()&lt;&#x2F;a&gt; system call. However, there is a separate system call, named &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;clone()&lt;&#x2F;a&gt; which is used for creating threads. It works like fork(), but it accepts a number of flags for adjusting its behavior so the child can share some parts of the parent&#x27;s execution context. Our c script made a call to clone() twice. And looking at &lt;em&gt;some&lt;&#x2F;em&gt; of the flags that have been passed, we can see that:&lt;&#x2F;p&gt;
&lt;p&gt;the caller and the child process:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CLONE_VM: run in the &lt;strong&gt;same memory space&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_FS: share the &lt;strong&gt;same filesystem information&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_FILES: share the &lt;strong&gt;same file descriptor table&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;CLONE_THREAD: are placed in the &lt;strong&gt;same thread group&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;p&gt;Another interesting arguments passed to clone system call are &lt;code&gt;child_stack&lt;&#x2F;code&gt; and &lt;code&gt;tls&lt;&#x2F;code&gt;. From the man page, we can read &lt;a href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;somewhere&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The child_stack argument specifies the location of the stack used by the child process.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And in &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;set_thread_area.2.html&quot;&gt;another part&lt;&#x2F;a&gt; of the man page:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;set a thread local storage (TLS) area&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Basically, we&#x27;re allocating a &lt;em&gt;personal stack&lt;&#x2F;em&gt; to each of our threads. But, we also give each thread, an access to a region of memory which is &lt;em&gt;not shared&lt;&#x2F;em&gt; with all other threads. Like one may do with Python using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;threading.html#thread-local-data&quot;&gt;threading.local&lt;&#x2F;a&gt; class.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;gdb-to-the-rescue&quot;&gt;&lt;strong&gt;GDB to the rescue&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Let&#x27;s have a confirmation using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GDB&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ gdb .&#x2F;bin&#x2F;how_to_thread
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;First, we set two breakpoints, one at the start of the main function, another one at the start of the say_hello function:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;insert-breakpoints.png&quot; alt=&quot;insert breakpoints&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Then we start the debugged program: &lt;code&gt;r&lt;&#x2F;code&gt;, and list the mapped memory regions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;info-proc-map1.png&quot; alt=&quot;info proc mappings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So far, we see only one stack segment, the one used by the main process, that is because our threads are not yet created. Let&#x27;s continue a little bit (twice) with &lt;code&gt;c&lt;&#x2F;code&gt;, and you should be able to see something like this:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;info-proc-map2.png&quot; alt=&quot;info proc mappings&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This time, we can see three stacks in the same virtual address space. The ones used by our threads are &lt;code&gt;[stack:15074]&lt;&#x2F;code&gt; and &lt;code&gt;[stack:15075]&lt;&#x2F;code&gt;. GDB to inspect each thread&#x27;s stack:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;stacks.png&quot; alt=&quot;thread&amp;#39;s stack&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;LWP is an acronym and stands for Light Weight Process. Next to LWP is the thread ID assigned by the kernel to this thread. We see that each thread has its own stack, and inside each stack, the progress is different, while thread 3 is entering the say_hello function, thread 2 is in &lt;em&gt;nanosleep&lt;&#x2F;em&gt;. By the way nanosleep is also a &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;nanosleep.2.html&quot;&gt;system call&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Here we are, a thread is indeed just a &lt;strong&gt;context of execution&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t be able to cover the whole topic as it&#x27;s not an easy and small one. So you may find &lt;em&gt;really&lt;&#x2F;em&gt; interesting the following links:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man7&#x2F;pthreads.7.html&quot;&gt;Pthreads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;7577&#x2F;&quot;&gt;Making Linux safe for pthreads&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.linfo.org&#x2F;context_switch.html&quot;&gt;Context switch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;0xax.gitbooks.io&#x2F;linux-insides&#x2F;content&#x2F;SyncPrim&#x2F;sync-3.html&quot;&gt;Semaphores&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;turnoff.us&#x2F;geek&#x2F;dont-share-mutable-state&#x2F;&quot;&gt;The real reason not to share a mutable state&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Django single file project</title>
        <published>2017-01-12T17:17:17+00:00</published>
        <updated>2017-01-12T17:17:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/dsfp/"/>
        <id>https://nskm.xyz/posts/dsfp/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/dsfp/">&lt;h4 id=&quot;disclaimer&quot;&gt;&lt;strong&gt;Disclaimer?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;The main purpose of this post is learning. Like any tool we should explore and find ways to bend it until it breaks. You should &lt;em&gt;normally&lt;&#x2F;em&gt; not use those techniques in real life projects &lt;em&gt;right&lt;&#x2F;em&gt;? For this post, I&#x27;m assuming you&#x27;re using Django 1.10.4, and Python3.6.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;single-file&quot;&gt;&lt;strong&gt;Single file?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Before reading &lt;a href=&quot;http:&#x2F;&#x2F;shop.oreilly.com&#x2F;product&#x2F;0636920032502.do&quot;&gt;Lightweight Django&lt;&#x2F;a&gt;, I never tought it was possible to build a Django project in a single python file. For that kind of stuff, I usually think, &lt;a href=&quot;http:&#x2F;&#x2F;flask.pocoo.org&#x2F;&quot;&gt;Flask&lt;&#x2F;a&gt;, or &lt;a href=&quot;http:&#x2F;&#x2F;bottlepy.org&#x2F;docs&#x2F;dev&#x2F;&quot;&gt;Bottle&lt;&#x2F;a&gt;. And in fact, there are many &lt;a href=&quot;http:&#x2F;&#x2F;codecondo.com&#x2F;14-minimal-web-frameworks-for-python&#x2F;&quot;&gt;others&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After reading the first chapter, I was a little bit disappointed. There were no Django &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;topics&#x2F;db&#x2F;models&#x2F;&quot;&gt;models&lt;&#x2F;a&gt; involved in the shown example. So, I try to find out if it was possible: &lt;strong&gt;a single file Django project with at least one application containing one model&lt;&#x2F;strong&gt;. I found some interesting links on the topic. But either it was for a very old version of Django, either I was obliged to install another package besides Django. After few days reading others people code, this is what I&#x27;ve done:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;sys
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.conf &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;settings
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;sys.path[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = os.path.dirname(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# the current folder name will also be our app
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL = os.path.basename(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;settings.configure(
&lt;&#x2F;span&gt;&lt;span&gt;    DEBUG=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DEBUG&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;on&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;on&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    SECRET_KEY=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;SECRET_KEY&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, os.urandom(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;)),
&lt;&#x2F;span&gt;&lt;span&gt;    ALLOWED_HOSTS=os.environ.get(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ALLOWED_HOSTS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;localhost&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;,&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    ROOT_URLCONF=__name__,
&lt;&#x2F;span&gt;&lt;span&gt;    MIDDLEWARE=[
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.security.SecurityMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions.middleware.SessionMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.common.CommonMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.csrf.CsrfViewMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth.middleware.AuthenticationMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages.middleware.MessageMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.clickjacking.XFrameOptionsMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.middleware.locale.LocaleMiddleware&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    INSTALLED_APPS=[
&lt;&#x2F;span&gt;&lt;span&gt;        APP_LABEL,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.admin&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.contenttypes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.staticfiles&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    STATIC_URL=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;static&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    STATICFILES_DIRS=[
&lt;&#x2F;span&gt;&lt;span&gt;        os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;static&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    ],
&lt;&#x2F;span&gt;&lt;span&gt;    STATIC_ROOT=os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;static_root&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    MEDIA_ROOT=os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;media&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    MEDIA_URL=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;media&#x2F;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;    TEMPLATES=[
&lt;&#x2F;span&gt;&lt;span&gt;        {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;BACKEND&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.backends.django.DjangoTemplates&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DIRS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;templates&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;),],
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;APP_DIRS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;OPTIONS&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;context_processors&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.debug&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.i18n&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.request&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth.context_processors.auth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.template.context_processors.tz&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages.context_processors.messages&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                ],
&lt;&#x2F;span&gt;&lt;span&gt;            },
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;    DATABASES={
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;default&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: {
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ENGINE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.db.backends.sqlite3&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;NAME&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: os.path.join(BASE_DIR, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;db.sqlite3&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;            }
&lt;&#x2F;span&gt;&lt;span&gt;        },
&lt;&#x2F;span&gt;&lt;span&gt;    REST_FRAMEWORK={
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DEFAULT_PERMISSION_CLASSES&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework.permissions.IsAdminUser&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;PAGE_SIZE&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;django
&lt;&#x2F;span&gt;&lt;span&gt;django.setup()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.contrib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;admin
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.db &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;models
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Create your models here.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Author(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    name = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;200&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Book(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;models.Model&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    author = models.ForeignKey(Author, related_name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;books&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    title = models.CharField(max_length=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;400&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        app_label = APP_LABEL
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;admin.site.register(Book)
&lt;&#x2F;span&gt;&lt;span&gt;admin.site.register(Author)
&lt;&#x2F;span&gt;&lt;span&gt;admin.autodiscover()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;serializers
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;BookSerializer(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;serializers.ModelSerializer&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;Meta:
&lt;&#x2F;span&gt;&lt;span&gt;        model = Book
&lt;&#x2F;span&gt;&lt;span&gt;        fields = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;__all__&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;viewsets
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;class &lt;&#x2F;span&gt;&lt;span&gt;BooksViewSet(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#4ec9b0;&quot;&gt;viewsets.ReadOnlyModelViewSet&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    queryset = Book.objects.all()
&lt;&#x2F;span&gt;&lt;span&gt;    serializer_class = BookSerializer
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.conf.urls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;url, include
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;rest_framework &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;routers
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.http &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;HttpResponse
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.contrib &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;admin
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;router = routers.DefaultRouter()
&lt;&#x2F;span&gt;&lt;span&gt;router.register(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;books&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, BooksViewSet)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;index(request):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;HttpResponse(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Hello&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;urlpatterns = [
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;admin&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, admin.site.urls),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, index, name=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;homepage&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;api&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(router.urls)),
&lt;&#x2F;span&gt;&lt;span&gt;    url(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;^&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;api-auth&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, include(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework.urls&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,\
&lt;&#x2F;span&gt;&lt;span&gt;                                   namespace=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.core.wsgi &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;get_wsgi_application
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;__name__ == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;__main__&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.core.management &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;execute_from_command_line
&lt;&#x2F;span&gt;&lt;span&gt;    execute_from_command_line(sys.argv)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    get_wsgi_application()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Everything related to &lt;a href=&quot;http:&#x2F;&#x2F;www.django-rest-framework.org&#x2F;&quot;&gt;Django REST Framework&lt;&#x2F;a&gt; is not mandatory. I was looking for &lt;a href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;979&#x2F;&quot;&gt;interesting links&lt;&#x2F;a&gt; over the internet, and I found this question on &lt;a href=&quot;http:&#x2F;&#x2F;stackoverflow.com&#x2F;q&#x2F;32866578&#x2F;4055832&quot;&gt;StackOverflow&lt;&#x2F;a&gt;. I saw this as an opportunity to kill two birds with one stone.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The above script was saved in a file named &lt;code&gt;single.py&lt;&#x2F;code&gt; in a folder named &lt;code&gt;lwdj&lt;&#x2F;code&gt;. But you can do as you feel, as soon as you respect the name of the file and the name of the current folder. The rest is known story:&lt;&#x2F;p&gt;
&lt;p&gt;Make the migrations for our application:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py makemigrations lwdj
&lt;&#x2F;span&gt;&lt;span&gt;Migrations for &amp;#39;lwdj&amp;#39;:
&lt;&#x2F;span&gt;&lt;span&gt;  migrations&#x2F;0001_initial.py:
&lt;&#x2F;span&gt;&lt;span&gt;    - Create model Author
&lt;&#x2F;span&gt;&lt;span&gt;    - Create model Book
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%) ⤷
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Run the migrations:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py migrate
&lt;&#x2F;span&gt;&lt;span&gt;Operations to perform:
&lt;&#x2F;span&gt;&lt;span&gt;  Apply all migrations: admin, auth, contenttypes, lwdj, sessions
&lt;&#x2F;span&gt;&lt;span&gt;Running migrations:
&lt;&#x2F;span&gt;&lt;span&gt;  Applying contenttypes.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying admin.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying admin.0002_logentry_remove_auto_add... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying contenttypes.0002_remove_content_type_name... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0002_alter_permission_name_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0003_alter_user_email_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0004_alter_user_username_opts... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0005_alter_user_last_login_null... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0006_require_contenttypes_0002... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0007_alter_validators_add_error_messages... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying auth.0008_alter_user_username_max_length... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying lwdj.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;  Applying sessions.0001_initial... OK
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Create a super user and run the server:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py createsuperuser
&lt;&#x2F;span&gt;&lt;span&gt;Username (leave blank to use &amp;#39;nsukami&amp;#39;):
&lt;&#x2F;span&gt;&lt;span&gt;Email address: nsukami@gmail.com
&lt;&#x2F;span&gt;&lt;span&gt;Password:
&lt;&#x2F;span&gt;&lt;span&gt;Password (again):
&lt;&#x2F;span&gt;&lt;span&gt;Superuser created successfully.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py runserver
&lt;&#x2F;span&gt;&lt;span&gt;Performing system checks...
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;System check identified no issues (0 silenced).
&lt;&#x2F;span&gt;&lt;span&gt;January 12, 2017 - 18:52:57
&lt;&#x2F;span&gt;&lt;span&gt;Django version 1.10.4, using settings None
&lt;&#x2F;span&gt;&lt;span&gt;Starting development server at http:&#x2F;&#x2F;127.0.0.1:8000&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;Quit the server with CONTROL-C.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;so-what-have-we-learned-here&quot;&gt;&lt;strong&gt;So, what have we learned here?&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Yes, that is not how you are supposed to use Django. But we were able to learn few things.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;projects-and-applications&quot;&gt;&lt;strong&gt;Projects and applications&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Somewhere in the Django documentation related to &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;ref&#x2F;applications&#x2F;#projects-and-applications&quot;&gt;projects and applications&lt;&#x2F;a&gt;, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;There&#x27;s no restriction that a project package can&#x27;t also be considered an application and have models, etc. (which would require adding it to INSTALLED_APPS).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We can double check using the &lt;code&gt;tree&lt;&#x2F;code&gt; command:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ tree
&lt;&#x2F;span&gt;&lt;span&gt;.
&lt;&#x2F;span&gt;&lt;span&gt;├── activate -&amp;gt; &#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;bin&#x2F;activate
&lt;&#x2F;span&gt;&lt;span&gt;├── db.sqlite3
&lt;&#x2F;span&gt;&lt;span&gt;├── Makefile
&lt;&#x2F;span&gt;&lt;span&gt;├── media
&lt;&#x2F;span&gt;&lt;span&gt;├── migrations
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── 0001_initial.py
&lt;&#x2F;span&gt;&lt;span&gt;│   ├── __init__.py
&lt;&#x2F;span&gt;&lt;span&gt;│   └── __pycache__
&lt;&#x2F;span&gt;&lt;span&gt;│       └── __init__.cpython-36.pyc
&lt;&#x2F;span&gt;&lt;span&gt;├── single.py
&lt;&#x2F;span&gt;&lt;span&gt;├── static
&lt;&#x2F;span&gt;&lt;span&gt;│   └── site.css
&lt;&#x2F;span&gt;&lt;span&gt;├── static_root
&lt;&#x2F;span&gt;&lt;span&gt;└── templates
&lt;&#x2F;span&gt;&lt;span&gt;    └── home.html
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;the-django-setup-method&quot;&gt;&lt;strong&gt;The django.setup() method&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;Reading The Fabulous &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;ref&#x2F;applications&#x2F;#how-applications-are-loaded&quot;&gt;Manual&lt;&#x2F;a&gt;, we learn that, this method configures Django by loading the settings, but also:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When Django starts, django.setup() is responsible for populating the application registry.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let&#x27;s start a shell using the command &lt;code&gt;python single.py shell&lt;&#x2F;code&gt;, and let&#x27;s check the application registry:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;django.apps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;apps
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; apps.ready
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; apps.get_app_configs()
&lt;&#x2F;span&gt;&lt;span&gt;odict_values([&amp;lt;AppConfig: lwdj&amp;gt;, &amp;lt;AdminConfig: admin&amp;gt;, &amp;lt;AuthConfig: auth&amp;gt;, &amp;lt;ContentTypesConfig: contenttypes&amp;gt;, &amp;lt;SessionsConfig: sessions&amp;gt;, &amp;lt;MessagesConfig: messages&amp;gt;, &amp;lt;StaticFilesConfig: staticfiles&amp;gt;, &amp;lt;AppConfig: rest_framework&amp;gt;])
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c = apps.get_app_config(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.module
&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;module &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;(namespace)&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.path
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;GITHUB&#x2F;how_tos&#x2F;how_to_django&#x2F;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.verbose_name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;Lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; c.label
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lwdj&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;m &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;c.models: print(m)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;author
&lt;&#x2F;span&gt;&lt;span&gt;book
&lt;&#x2F;span&gt;&lt;span&gt;(dj) &amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Neat!
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We also &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;dev&#x2F;ref&#x2F;applications&#x2F;#how-applications-are-loaded&quot;&gt;read&lt;&#x2F;a&gt; that:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;At this stage, your code shouldn&#x27;t import any models!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This is exactly why our models, and everything related to them, do not appear before those 2 lines of code.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;django
&lt;&#x2F;span&gt;&lt;span&gt;django.setup()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Doing otherwise, raises the &lt;code&gt;AppRegistryNotReady&lt;&#x2F;code&gt; exception:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;span&gt;⤷ python single.py runserver
&lt;&#x2F;span&gt;&lt;span&gt;Traceback (most recent call last):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;single.py&amp;quot;, line 90, in &amp;lt;module&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;    class Author(models.Model):
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;db&#x2F;models&#x2F;base.py&amp;quot;, line 105, in __new__
&lt;&#x2F;span&gt;&lt;span&gt;    app_config = apps.get_containing_app_config(module)
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;apps&#x2F;registry.py&amp;quot;, line 237, in get_containing_app_config
&lt;&#x2F;span&gt;&lt;span&gt;    self.check_apps_ready()
&lt;&#x2F;span&gt;&lt;span&gt;  File &amp;quot;&#x2F;home&#x2F;nsukami&#x2F;envs&#x2F;dj&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;django&#x2F;apps&#x2F;registry.py&amp;quot;, line 124, in check_apps_ready
&lt;&#x2F;span&gt;&lt;span&gt;    raise AppRegistryNotReady(&amp;quot;Apps aren&amp;#39;t loaded yet.&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;django.core.exceptions.AppRegistryNotReady: Apps aren&amp;#39;t loaded yet.
&lt;&#x2F;span&gt;&lt;span&gt;(dj) ~&#x2F;...&#x2F;how_to_django&#x2F;lwdj  (master *%)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;installed-applications&quot;&gt;&lt;strong&gt;Installed applications&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;I have not yet fully understood this part. &lt;code&gt;APP_LABEL&lt;&#x2F;code&gt; is actually containing the name of the current directory. By putting &lt;code&gt;APP_LABEL&lt;&#x2F;code&gt; inside &lt;code&gt;INSTALLED_APPS&lt;&#x2F;code&gt;, Django was able to find all the Django models existing inside the current directory:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;sys.path[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;] = os.path.dirname(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;APP_LABEL = os.path.basename(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;{{&amp;lt; &#x2F;highlight &amp;gt;}}
&lt;&#x2F;span&gt;&lt;span&gt;{{&amp;lt; highlight python &amp;gt;}}
&lt;&#x2F;span&gt;&lt;span&gt;    INSTALLED_APPS=[
&lt;&#x2F;span&gt;&lt;span&gt;        APP_LABEL,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.admin&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.auth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.contenttypes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.sessions&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.messages&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;django.contrib.staticfiles&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;rest_framework&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        ],
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;app-label&quot;&gt;&lt;strong&gt;App label&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;All our models were created outside of a &lt;code&gt;models.py&lt;&#x2F;code&gt; file. They&#x27;re not even in a &lt;em&gt;real&lt;&#x2F;em&gt; Django application. So we were obliged to tell them which application they belongs to. This is done using the &lt;a href=&quot;https:&#x2F;&#x2F;docs.djangoproject.com&#x2F;en&#x2F;1.10&#x2F;ref&#x2F;models&#x2F;options&#x2F;#app-label&quot;&gt;app_label&lt;&#x2F;a&gt; attribute of the internal &lt;code&gt;class Meta&lt;&#x2F;code&gt; of Django models.
{{&amp;lt; highlight python &amp;gt;}}
class Author(models.Model):
name = models.CharField(max_length=200)
class Meta:
app_label = APP_LABEL&lt;&#x2F;p&gt;
&lt;p&gt;class Book(models.Model):
author = models.ForeignKey(Author, related_name=&#x27;books&#x27;)
title = models.CharField(max_length=400)
class Meta:
app_label = APP_LABEL
{{&amp;lt; &#x2F;highlight &amp;gt;}}
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Really hope you learnt something. Also, I would not be able to write this post, without following the &lt;em&gt;StackTrace&lt;&#x2F;em&gt; leaved by the people who were there before me. A huge thanks to them:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;dotmobo.github.io&#x2F;django-minimaliste.html&quot;&gt;Créer une application django minimaliste&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;blog.fahhem.com&#x2F;2011&#x2F;10&#x2F;django-models-without-apps-or-everything-django-truly-in-a-single-file&#x2F;&quot;&gt;Django Models without Apps OR Everything Django Truly in a Single File&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zenwalker&#x2F;django-micro&quot;&gt;Django as microframework&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Make</title>
        <published>2016-11-25T00:00:00+00:00</published>
        <updated>2016-11-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/mk/"/>
        <id>https://nskm.xyz/posts/mk/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/mk/">&lt;p&gt;if you have some &lt;strong&gt;complex and esoteric shell commands&lt;&#x2F;strong&gt; that you have to run on a regular basis, it can be convenient to just package them up &lt;em&gt;somewhere&lt;&#x2F;em&gt;, so you don&#x27;t have to &lt;strong&gt;remember them&lt;&#x2F;strong&gt; or &lt;strong&gt;type them out every time&lt;&#x2F;strong&gt;. &lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Why, I don&#x27;t use Makefiles more often? Even though I know I should. One of the reason may be because, as an Emacs user, automating simple tasks is &lt;em&gt;funny&lt;&#x2F;em&gt; using &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;manual&#x2F;html_node&#x2F;elisp&#x2F;&quot;&gt;Emacs Lisp&lt;&#x2F;a&gt;. Following are simple elisp functions I use to compile a C file, nothing extraordinary:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;lisp&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-lisp &quot;&gt;&lt;code class=&quot;language-lisp&quot; data-lang=&quot;lisp&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defun &lt;&#x2F;span&gt;&lt;span&gt;my-c-save-compile ()
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Save, and compile c file.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  (interactive)
&lt;&#x2F;span&gt;&lt;span&gt;  (save-buffer)
&lt;&#x2F;span&gt;&lt;span&gt;  (compile
&lt;&#x2F;span&gt;&lt;span&gt;   (format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;cc -Wall -Wextra -pedantic -std=c11 -g %s -o .&#x2F;bin&#x2F;%s&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;           (buffer-file-name)
&lt;&#x2F;span&gt;&lt;span&gt;           (file-name-base (buffer-file-name)))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;defun &lt;&#x2F;span&gt;&lt;span&gt;my-c-run ()
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Run c code.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  (interactive)
&lt;&#x2F;span&gt;&lt;span&gt;  (compile (format &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;bin&#x2F;%s&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;                   (file-name-base (buffer-file-name)))))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Another reason I don&#x27;t use Makefiles more often could be, the &lt;a href=&quot;http:&#x2F;&#x2F;www.tldp.org&#x2F;LDP&#x2F;Bash-Beginners-Guide&#x2F;html&#x2F;Bash-Beginners-Guide.html&quot;&gt;Bourne Again Shell&lt;&#x2F;a&gt;. I find it easier to quickly write shell aliases for repetitive tasks. The following is some aliases I &lt;em&gt;sometimes&lt;&#x2F;em&gt; use whenever I&#x27;m doing &lt;a href=&quot;https:&#x2F;&#x2F;www.djangoproject.com&#x2F;&quot;&gt;Django&lt;&#x2F;a&gt; development:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;bin&#x2F;sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# my weird aliases
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_runserver=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py runserver&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_shell=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py shell&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_shellp=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py shell_plus&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_make=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py makemigrations&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_mig=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py migrate&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_csu=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python manage.py createsuperuser&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;alias djo_smtpd=&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&amp;quot;python -m smtpd -n -c DebuggingServer localhost:1025&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Make do have a reputation for being complex. Indeed, it can be very &lt;a href=&quot;http:&#x2F;&#x2F;okmij.org&#x2F;ftp&#x2F;Computation&#x2F;#Makefile-functional&quot;&gt;esoteric&lt;&#x2F;a&gt;. The full &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;manual&lt;&#x2F;a&gt; is a 183 pages. Fortunately, you can ignore most of this, Make can be used in a very simple and incredibly useful way. &lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The following, is a Makefile I sometimes use in replacement of the shell aliases above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;make&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-make &quot;&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Makefile for (the project)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Nsukami
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# November 2016
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;SHELL := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;tas&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PYTHON_BIN := &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;VIRTUAL_ENV&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;&#x2F;bin&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEV_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.dev&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROD_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.prod&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROJECT&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;.settings.test&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;shell dirname &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;realpath &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;lastword &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;MAKEFILE_LIST&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;))))&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PMP = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;python manage.py&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# if not on prod server, use dev settings
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;ifneq &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;shell uname -n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,phobos)
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;DEV_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#dcdcdc;&quot;&gt;PROD_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;endif
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: all - Default target. Does nothing.
&lt;&#x2F;span&gt;&lt;span&gt;all:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;Nothing to do by default. Try &amp;#39;make help&amp;#39;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: help - Show list of targets + description
&lt;&#x2F;span&gt;&lt;span&gt;help:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;@&lt;&#x2F;span&gt;&lt;span&gt;egrep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;^# target:&amp;quot; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Mm&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;akefile
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: init - Install that a dev needs to get up and running.
&lt;&#x2F;span&gt;&lt;span&gt;init: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;bootstrap.sh&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &amp;amp;&amp;amp; &lt;&#x2F;span&gt;&lt;span&gt;sudo .&#x2F;bootstrap.sh
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean - remove all useless files
&lt;&#x2F;span&gt;&lt;span&gt;clean: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;clean-pyc clean-build&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean-pyc - remove all auto generated files
&lt;&#x2F;span&gt;&lt;span&gt;clean-pyc:
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.pyc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force {} +
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*.pyo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force {} +
&lt;&#x2F;span&gt;&lt;span&gt;    find . -name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;*~&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; -exec rm --force  {} +
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: clean-build - remove all auto generated folders
&lt;&#x2F;span&gt;&lt;span&gt;clean-build:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive build&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive dist&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive htmlcov
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive .coverage
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;rm --force --recursive &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.egg-info
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: translate - calls the &amp;quot;makemessages&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;translate:
&lt;&#x2F;span&gt;&lt;span&gt;    cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &amp;amp;&amp;amp; $(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;makemessages --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; -a
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: test - calls the &amp;quot;test&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;test:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;test --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: run - calls the &amp;quot;runserver&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;run:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;runserver --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: update - install (and update) pip requirements
&lt;&#x2F;span&gt;&lt;span&gt;update:
&lt;&#x2F;span&gt;&lt;span&gt;    pip install -U -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;requirements&#x2F;dev.txt
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: collect - calls the &amp;quot;collectstatic&amp;quot; django command
&lt;&#x2F;span&gt;&lt;span&gt;collect:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;collectstatic --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; --noinput
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: rebuild - rebuild tables from models
&lt;&#x2F;span&gt;&lt;span&gt;rebuild:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;makemigrations --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;PMP&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;) &lt;&#x2F;span&gt;&lt;span&gt;migrate --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;$(&lt;&#x2F;span&gt;&lt;span&gt;SETTINGS&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# target: deploy - let make take care of deployment
&lt;&#x2F;span&gt;&lt;span&gt;deploy:
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Should I call fabric here?
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;.ONESHELL:
&lt;&#x2F;span&gt;&lt;span&gt;.PHONY: &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#282828;color:#d69d85;&quot;&gt;all help translate test clean update collect rebuild run clean-pyc clean-build clean init&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;Finally, the other reason, and probably the main reason I don&#x27;t use Makefiles more often, it&#x27;s because of &lt;a href=&quot;http:&#x2F;&#x2F;www.fabfile.org&#x2F;&quot;&gt;Fabric&lt;&#x2F;a&gt;. Following is a fabfile more or less doing the same thing as the Makefile above:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;#!&#x2F;usr&#x2F;bin&#x2F;env python
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# -*- coding: utf-8 -*- #
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; fabric commands &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;fabric.api &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;env, sudo, cd, local, task, run
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;fabric.contrib.project &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;project
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;os
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# Local path configuration (can be absolute or relative to fabfile)
&lt;&#x2F;span&gt;&lt;span&gt;env.hosts = [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;localhost&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;env.use_ssh_config = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;True
&lt;&#x2F;span&gt;&lt;span&gt;env.ssh_config_path = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&#x2F;home&#x2F;nsukami&#x2F;.ssh&#x2F;config&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;env.owner = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;nsukami&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;PROJECT = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;tas&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;DEV_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.dev&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;PROD_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.prod&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;TEST_SETTINGS = PROJECT + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.settings.test&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;BASE_DIR = os.path.dirname(os.path.abspath(__file__))
&lt;&#x2F;span&gt;&lt;span&gt;PMP = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;python manage.py &amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;uname():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Prints information about the host. &amp;quot;&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;uname -n&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;uname() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;is not &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;phobos&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = DEV_SETTINGS
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;    SETTINGS = PROD_SETTINGS
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;init():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;init - Install that a dev needs to get up and running.&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;cd(BASE_DIR):
&lt;&#x2F;span&gt;&lt;span&gt;        sudo(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;.&#x2F;bootstrap.sh&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clean - remove all useless files&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    clean_pyc()
&lt;&#x2F;span&gt;&lt;span&gt;    clean_build()
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean_pyc():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;# clean-pyc - remove all auto generated files&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*.pyc&amp;#39; -exec rm --force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*.pyo&amp;#39; -exec rm --force &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;find . -name &amp;#39;*~&amp;#39; -exec rm --force  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; +&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;clean_build():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;clean-build - remove all auto generated folders&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive build&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive dist&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive htmlcov&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive .coverage&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    local(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;rm --force --recursive *.egg-info&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;translate():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;translate - calls the &amp;#39;makemessages&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;cd(BASE_DIR):
&lt;&#x2F;span&gt;&lt;span&gt;        cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;makemessages --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt; -a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;        local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;test():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;test - calls the &amp;#39;test&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;test --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;runserver():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;run - calls the &amp;#39;runserver&amp;#39; django command&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = PMP + &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;runserver --settings=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(SETTINGS)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;@task
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span&gt;update():
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;update - install (and update) pip requirements&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    cmd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;pip install -U -r &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&#x2F;requirements&#x2F;dev.txt&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.format(BASE_DIR)
&lt;&#x2F;span&gt;&lt;span&gt;    local(cmd)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We see that Fabric &lt;em&gt;can&lt;&#x2F;em&gt; be used as a build tool even though it isn&#x27;t one. It is easy to read and write, especially for a Python developer. The drawback may be, it does require Python to run. &lt;em&gt;Seriously, who cares?&lt;&#x2F;em&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;New year resolution: &lt;strong&gt;using Makefiles more often.&lt;&#x2F;strong&gt;
&lt;br&gt;&lt;br&gt;
More on the topic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;make&#x2F;manual&#x2F;make.html&quot;&gt;Make&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=5276339&quot;&gt;Make alternatives&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_build_automation_software&quot;&gt;List of build automation software&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How to create processes</title>
        <published>2016-08-22T03:40:17+00:00</published>
        <updated>2016-08-22T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/process-creation/"/>
        <id>https://nskm.xyz/posts/process-creation/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/process-creation/">&lt;p&gt;We&#x27;ve seen &lt;a href=&quot;&#x2F;on-processes.md&quot;&gt;processes&lt;&#x2F;a&gt;, We&#x27;ve said lots of things about processes, but we did not talk about process creation. Let&#x27;s see how to create a process in C, in &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;&quot;&gt;Golang&lt;&#x2F;a&gt;, and in &lt;a href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;en-US&#x2F;&quot;&gt;Rustlang&lt;&#x2F;a&gt; &lt;em&gt;&lt;strong&gt;Disclaimer:&lt;&#x2F;strong&gt; I&#x27;m not doing a comparison to find out which one is better than the other. I just want to explore how the same task can be done using different approaches.&lt;br&gt;&lt;br&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;fork-and-exec&quot;&gt;&lt;strong&gt;Fork and Exec:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;UNIX processes are created using the fork() &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;System_call&quot;&gt;system call&lt;&#x2F;a&gt;. Fork is the primary method of process creation on Unix-like operating systems.  Fork is the system call that the parent process uses to &quot;divide&quot; itself, to &quot;fork&quot; into two identical processes. The child process will be the exact copy of the parent except for the return value.&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Exec_(system_call)&quot;&gt;exec()&lt;&#x2F;a&gt; system call and its family of functions are almost always used with fork(). The exec() syscall and the like overwrite the current [stackframe]({{&amp;lt; ref on-processes &amp;gt;}})with the name of the application passed to it.&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;h4 id=&quot;c&quot;&gt;&lt;strong&gt;C:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In C, there is nothing special to do, contrary to Golang and Rustlang. You just really call fork(), then exec(), simple and direct. The following, is an example written in C:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;wait.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;fork_and_execute();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  fork_and_execute();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;fork_and_execute() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid, status;
&lt;&#x2F;span&gt;&lt;span&gt;  pid = fork();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; if pid equals 0,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(pid == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; we&amp;#39;re dealing with the child process
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;I am the child process, my pid is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, getpid());
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the program we want to execute
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;cmd[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; execvp will search for ls on $PATH
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(execvp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd, cmd) &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; catch any error that may occur during execution
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: exec failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd);
&lt;&#x2F;span&gt;&lt;span&gt;      exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; returned pid is -1, fork operation failed
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;(pid &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: forking child process failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;fork&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; The wait system-call blocks the parent process
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; and waits for the child-process to end.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(wait(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;status) != pid){}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;go&quot;&gt;&lt;strong&gt;Go:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In Go, it is recommended to use the &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;os&#x2F;exec&#x2F;&quot;&gt;exec&lt;&#x2F;a&gt; package. It runs external commands, and wraps &lt;a href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;pkg&#x2F;os&#x2F;#StartProcess&quot;&gt;os.StartProcess&lt;&#x2F;a&gt; function for you. Following, is the previous example, this time written in Golang:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;go&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-go &quot;&gt;&lt;code class=&quot;language-go&quot; data-lang=&quot;go&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;package &lt;&#x2F;span&gt;&lt;span&gt;main
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;syscall&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;os&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;os&#x2F;exec&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;func &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; check if ls command exists in the PATH
&lt;&#x2F;span&gt;&lt;span&gt;    binary, lookErr := exec.LookPath(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;lookErr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;!= nil &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic(lookErr)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; the program we want to execute
&lt;&#x2F;span&gt;&lt;span&gt;    args := []string{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; fork new process and execute our program
&lt;&#x2F;span&gt;&lt;span&gt;    execErr := syscall.Exec(binary, args, os.Environ())
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F; catch error if any
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;execErr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;!= nil &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;        panic(execErr)
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h4 id=&quot;rust&quot;&gt;&lt;strong&gt;Rust:&lt;&#x2F;strong&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;In Rust, we have &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;struct.Command.html&quot;&gt;std::process::Command&lt;&#x2F;a&gt;. It is is a type that acts as a process builder and provides fine-grained control over how the new process should be spawned. If we browse the &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;std&#x2F;process.rs.html#521&quot;&gt;source code&lt;&#x2F;a&gt;, we can read beginning line 521:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Constructs a new &lt;code&gt;Command&lt;&#x2F;code&gt; for launching the program at&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;path &lt;code&gt;program&lt;&#x2F;code&gt;, with the following default configuration:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;No arguments to the program&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit the current process&#x27;s environment&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit the current process&#x27;s working directory&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Inherit stdin&#x2F;stdout&#x2F;stderr for &lt;code&gt;spawn&lt;&#x2F;code&gt; or &lt;code&gt;status&lt;&#x2F;code&gt;, but create pipes for &lt;code&gt;output&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;br&gt;
&lt;p&gt;Basically, it behave a little bit like a call to fork(), followed by a call to exec(). Let&#x27;s rewrite the previous example in Rust:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;use &lt;&#x2F;span&gt;&lt;span&gt;std::process::Command;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span&gt; output = Command::new(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .arg(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;                     .output()
&lt;&#x2F;span&gt;&lt;span&gt;                     .expect(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls command failed to start&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;stdout: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, String::from_utf8_lossy(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;output.stdout));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;process&#x2F;struct.Command.html#method.output&quot;&gt;output&lt;&#x2F;a&gt; function executes the command as a child process, waiting for it to finish and collecting all of its output. By default, stdin, stdout and stderr are captured (and used to provide the resulting output).&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;option&#x2F;enum.Option.html#method.expect&quot;&gt;expect&lt;&#x2F;a&gt; function is used for quick and dirty error handling.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;strace-trace-system-calls-and-signals&quot;&gt;&lt;strong&gt;Strace, trace system calls and signals:&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Somewhere in the strace&#x27;s manual page, we can read:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Trace child processes as they are created by currently traced processes as a result of the fork(2), vfork(2) and clone(2) system calls.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If everything went normally during the execution of our scripts, we should see, in the strace&#x27;s output, lots of system calls, the most important ones being a call to &lt;strong&gt;clone()&lt;&#x2F;strong&gt;, followed by a call to &lt;strong&gt;exec()&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;4714  clone(child_stack=0, flags=CLONE_CHILD_CLEARTID&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;CLONE_CHILD_SETTID&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;SIGCHLD, child_tidptr=0x7fac5d28da90) = 4715
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;7564  execve(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&#x2F;bin&#x2F;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; 74 vars &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;unfinished ...&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;fork() was the original UNIX system call. Only used to create new processes, not threads. Also, it is portable.&lt;&#x2F;p&gt;
&lt;p&gt;clone() is a new, versatile system call which can be used to create, depending on the passed option, a UNIX process, or a POSIX thread, or something in between, or something completely different. I invite you to &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;Read The Fabulous Manual&lt;&#x2F;a&gt; about clone().&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t really know if there is something else you can read to learn more on this topic:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;fork.2.html&quot;&gt;Fork&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man3&#x2F;exec.3.html&quot;&gt;Exec&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man2&#x2F;clone.2.html&quot;&gt;Clone&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man1&#x2F;strace.1.html&quot;&gt;Strace&lt;&#x2F;a&gt; manual page.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Processes</title>
        <published>2016-08-09T03:40:17+00:00</published>
        <updated>2016-08-09T03:40:17+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/processes-introduction/"/>
        <id>https://nskm.xyz/posts/processes-introduction/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/processes-introduction/">&lt;p&gt;As a Debian user, I often want to see the active processes, sometimes, I want to kill them. I know how to launch a new process, inside my Python scripts. But what is a process?&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;A process is the execution context of a running program. When an executable program is read into memory by the kernel and executed, it becomes a process. Processes are dynamic entities, they are constantly changing as their machine code instructions are executed by the CPU.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;With the exception of the &lt;code&gt;init process&lt;&#x2F;code&gt;, every process is the child of another process. And every process has the potential to be the parent of another process. The following is a small C program that will print the current process ID and the corresponding parent process ID:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main (){
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span&gt; ch;
&lt;&#x2F;span&gt;&lt;span&gt;  printf (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The process ID is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) getpid ());
&lt;&#x2F;span&gt;&lt;span&gt;  printf (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;The parent process ID is &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b4cea8;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;) getppid ());
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;( ch != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\r&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&amp;amp; ch != &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    ch = getchar();
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After execution, you should see something like:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span&gt;~
&lt;&#x2F;span&gt;&lt;span&gt;+-&amp;gt; .&#x2F;bin&#x2F;ex1
&lt;&#x2F;span&gt;&lt;span&gt;The process ID is 11147
&lt;&#x2F;span&gt;&lt;span&gt;The parent process ID is 9552
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a name=&quot;vas&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;virtual-address-space&quot;&gt;&lt;strong&gt;Virtual address space?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A virtual address space, &lt;code&gt;VAS&lt;&#x2F;code&gt;, is the set of ranges of virtual addresses available to a process. The virtual address space is what a process sees when it executes. A process works with and only sees VAS. The operating system handles mapping VAS to real storage so that this is invisible to the running program.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;We need VAS to prevent process A and process B from writing&#x2F;reading in the same memory addresses. VAS is a way to achieve &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Process_isolation&quot;&gt;process isolation&lt;&#x2F;a&gt;. With VAS, several programs could write to memory location at the same address without stepping over each others results.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;center&gt;

&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;nskm.xyz&amp;#x2F;processed_images&amp;#x2F;vas-schema.9c317ee408a2f21e.png&quot; &#x2F;&gt;
&lt;&#x2F;center&gt;
&lt;p&gt;&lt;em&gt;Image from &lt;a href=&quot;http:&#x2F;&#x2F;www.tenouk.com&#x2F;ModuleW_files&#x2F;ccompilerlinker007.png&quot;&gt;tenouk.com&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;h3 id=&quot;what-s-inside-vas&quot;&gt;&lt;strong&gt;What&#x27;s inside VAS?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;VAS&lt;&#x2F;code&gt;, is the set of ranges of virtual addresses available to a process, so what is inside a VAS? A typical memory representation of process consists of following sections:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stack:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section that is used for several related purposes, the main one being to keep track of the point to which each active subroutine should return control when it finishes executing. The return address is pushed onto the stack by the caller. When it finishes, the called subroutine, pops the return address off the stack and transfers control to that address. &lt;br&gt;&lt;br&gt;That section also stores temporary variables created by each function inside the program. The stack is a LIFO data structure, managed and optimized by the CPU quite closely. Every time a function declares a new variable, it is &quot;pushed&quot; onto the stack, you don&#x27;t have to allocate the needed memory by hand. Then every time a function exits, all of the variables pushed onto the stack by that function, are freed for you. Once a stack variable is freed, that region of memory becomes available for other stack variables.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Heap:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section where dynamic memory allocation usually takes place. Unlike the Stack, this part of the VAS is not managed automatically for you, and is not as tightly managed by the CPU. You are in charge of allocating memory on the heap. You are also responsible for deallocating that memory once you don&#x27;t need it any more. If you fail to do this, your program will have what is known as a memory leak.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Initialized Data Segment:&lt;&#x2F;strong&gt;&lt;br&gt;
Or simply, Data Segment. VAS section, which contains the global and static variables that are initialized by the programmer. The size of this segment is determined by the size of the values in the program&#x27;s source code, and does not change at run time.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Uninitialized (bss) Data Segment:&lt;&#x2F;strong&gt; &lt;br&gt;
VAS section that contains all global and static variables that are initialized to zero or do not have explicit initialization in the programer&#x27;s source code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Text (code) Segment:&lt;&#x2F;strong&gt;&lt;br&gt;
VAS section that contains machine instructions of the program. Those machine instructions can be thought of as the text of a novel: It tells the story of what the program does.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;h3 id=&quot;how-to-do-some-introspection&quot;&gt;&lt;strong&gt;How to do some introspection?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;How do we learn about the memory layout of a running process? How do we look at how program are laid out in memory?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Directly from &#x2F;proc&#x2F;PID&#x2F;maps:&lt;br&gt;&lt;&#x2F;strong&gt;
You can directly ask to the process information pseudo-filesystem: &lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man5&#x2F;proc.5.html&quot;&gt;proc&lt;&#x2F;a&gt;. Let&#x27;s see the output of &lt;code&gt;cat &#x2F;proc&#x2F;6026&#x2F;maps&lt;&#x2F;code&gt;. Here &lt;code&gt;6026&lt;&#x2F;code&gt; is the PID of a running process on my Debian:&lt;br&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;00400000-00401000 r-xp 00000000 08:05 3181468            &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;00600000-00601000 rw-p 00000000 08:05 3181468            &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;01698000-016b9000 rw-p 00000000 00:00 0                  [heap]
&lt;&#x2F;span&gt;&lt;span&gt;7f747118a000-7f747132c000 r-xp 00000000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747132c000-7f747152b000 ---p 001a2000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747152b000-7f747152f000 r--p 001a1000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f747152f000-7f7471531000 rw-p 001a5000 08:01 131521     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471531000-7f7471535000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471535000-7f7471555000 r-xp 00000000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471734000-7f7471737000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471752000-7f7471755000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7f7471755000-7f7471756000 r--p 00020000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471756000-7f7471757000 rw-p 00021000 08:01 130924     &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;7f7471757000-7f7471758000 rw-p 00000000 00:00 0
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d89b000-7ffc4d8bc000 rw-p 00000000 00:00 0          [stack]
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d99b000-7ffc4d99d000 r-xp 00000000 00:00 0          [vdso]
&lt;&#x2F;span&gt;&lt;span&gt;7ffc4d99d000-7ffc4d99f000 r--p 00000000 00:00 0          [vvar]
&lt;&#x2F;span&gt;&lt;span&gt;ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0  [vsyscall]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
The Heap segment and the Stack segment are labelled, easy. The addresses are displayed from the lowest `00400000`, to the highest `ffffffffff601000`. The first segment, `00400000-00401000`, is read-only and executable, so, this is the Code segment. We know that between the Code segment, and the Heap segment, there is the Data segment. If you don&#x27;t want to browse the `&#x2F;proc` directory, there is also the [pmap](http:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;pmap) command you can use to report the memory map of a process.
&lt;br&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Using the GNU debugger:&lt;&#x2F;strong&gt;
GDB, the &lt;em&gt;awesome&lt;&#x2F;em&gt; &lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GNU Project debugger&lt;&#x2F;a&gt;, allows you, among others things, to see what is going on &lt;code&gt;inside&lt;&#x2F;code&gt; a running process. For example, from the gdb prompt, you can type &lt;code&gt;info proc mappings&lt;&#x2F;code&gt; to see the current address mapping:&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;process 8460
&lt;&#x2F;span&gt;&lt;span&gt;Mapped address spaces:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        Start Addr           End Addr     Size   Offset objfile
&lt;&#x2F;span&gt;&lt;span&gt;          0x400000           0x401000   0x1000      0x0 &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;          0x600000           0x601000   0x1000      0x0 &#x2F;home&#x2F;nsukami&#x2F;bin&#x2F;how_to_vms
&lt;&#x2F;span&gt;&lt;span&gt;          0x601000           0x622000  0x21000      0x0 [heap]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7a31000     0x7ffff7bd3000 0x1a2000      0x0 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7bd3000     0x7ffff7dd2000 0x1ff000 0x1a2000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd2000     0x7ffff7dd6000   0x4000 0x1a1000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd6000     0x7ffff7dd8000   0x2000 0x1a5000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;libc-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7dd8000     0x7ffff7ddc000   0x4000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ddc000     0x7ffff7dfc000  0x20000      0x0 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7fd7000     0x7ffff7fda000   0x3000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ff5000     0x7ffff7ff8000   0x3000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ff8000     0x7ffff7ffa000   0x2000      0x0 [vdso]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffa000     0x7ffff7ffc000   0x2000      0x0 [vvar]
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffc000     0x7ffff7ffd000   0x1000  0x20000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffd000     0x7ffff7ffe000   0x1000  0x21000 &#x2F;lib&#x2F;x86_64-linux-gnu&#x2F;ld-2.19.so
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffff7ffe000     0x7ffff7fff000   0x1000      0x0
&lt;&#x2F;span&gt;&lt;span&gt;    0x7ffffffde000     0x7ffffffff000  0x21000      0x0 [stack]
&lt;&#x2F;span&gt;&lt;span&gt;0xffffffffff600000 0xffffffffff601000   0x1000      0x0 [vsyscall]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;And there is more to explore:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;(gdb) help info proc
&lt;&#x2F;span&gt;&lt;span&gt;Show &#x2F;proc process information about any running process.
&lt;&#x2F;span&gt;&lt;span&gt;Specify any process id, or use the program being debugged by default.
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;List of info proc subcommands:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;info proc all -- List all available &#x2F;proc info
&lt;&#x2F;span&gt;&lt;span&gt;info proc cmdline -- List command line arguments of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc cwd -- List current working directory of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc exe -- List absolute filename for executable of the process
&lt;&#x2F;span&gt;&lt;span&gt;info proc mappings -- List of mapped memory regions
&lt;&#x2F;span&gt;&lt;span&gt;info proc stat -- List process info from &#x2F;proc&#x2F;PID&#x2F;stat
&lt;&#x2F;span&gt;&lt;span&gt;info proc status -- List process info from &#x2F;proc&#x2F;PID&#x2F;status
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Type &amp;quot;help info proc&amp;quot; followed by info proc subcommand name for full documentation.
&lt;&#x2F;span&gt;&lt;span&gt;Type &amp;quot;apropos word&amp;quot; to search for commands related to &amp;quot;word&amp;quot;.
&lt;&#x2F;span&gt;&lt;span&gt;Command name abbreviations are allowed if unambiguous.
&lt;&#x2F;span&gt;&lt;span&gt;(gdb)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;h3 id=&quot;how-to-create-a-process&quot;&gt;&lt;strong&gt;How to create a process?&lt;&#x2F;strong&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;1.&lt;strong&gt;fork():&lt;&#x2F;strong&gt;
The fork() system call is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;c&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-c &quot;&gt;&lt;code class=&quot;language-c&quot; data-lang=&quot;c&quot;&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdio.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;types.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;unistd.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;stdlib.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;sys&#x2F;wait.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;lt;string.h&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;execute();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span&gt;main() {
&lt;&#x2F;span&gt;&lt;span&gt;  execute();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span&gt;execute() {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; pid, status;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt;((pid = fork()) == &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;char *&lt;&#x2F;span&gt;&lt;span&gt;cmd[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;] = {&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;ls&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-l&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;-h&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\0&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(execvp(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd, cmd) &amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;){
&lt;&#x2F;span&gt;&lt;span&gt;      printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: exec failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;      perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;cmd);
&lt;&#x2F;span&gt;&lt;span&gt;      exit(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    printf(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;*** ERROR: forking child process failed&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    perror(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;quot;fork&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;    exit(EXIT_FAILURE);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;&#x2F;&#x2F;The parent executes the wait.
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(wait(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;status) != pid){}
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I really would like to write more on this topic. Maybe in another post, otherwise the article will be too long, &lt;em&gt;and I have the dishes to do&lt;&#x2F;em&gt;. At least, we&#x27;ve seen that there is an interesting amount of informations behind what is called a process.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-hope-you-ve-learned-something-and-if-you-want-to-know-more&quot;&gt;I hope you&#x27;ve learned something, and if you want to know more:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;www.tldp.org&#x2F;LDP&#x2F;tlk&#x2F;kernel&#x2F;processes.html&quot;&gt;Processes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.kernel.org&#x2F;doc&#x2F;Documentation&#x2F;filesystems&#x2F;proc.txt&quot;&gt;Proc&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man5&#x2F;proc.5.html&quot;&gt;Proc man pages&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;446528&#x2F;&quot;&gt;The &quot;vsyscall&quot; and &quot;vDSO&quot; segments&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;gdb&#x2F;&quot;&gt;GDB&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;turnoff.us&#x2F;geek&#x2F;the-jealous-process&#x2F;&quot;&gt;The jealous process&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Network namespaces</title>
        <published>2016-07-08T00:00:00+00:00</published>
        <updated>2016-07-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/onn/"/>
        <id>https://nskm.xyz/posts/onn/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/onn/">&lt;p&gt;I use LXC containers mainly as isolated environments when I&#x27;m writing code, but also when I just want to try the last version of a package without being obliged to break something on my current configuration. This is the first part of a serie about LXC containers. In this post, I&#x27;ll share with you what I&#x27;ve learned about network namespaces. Everything here will be done under Debian Jessie, as root, I&#x27;m using Python 3.5 and I&#x27;ve pip installed pyroute2.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To keep the schemas as simple as possible, I won&#x27;t mention the interface &lt;code&gt;lo&lt;&#x2F;code&gt; actually available inside the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. The &lt;code&gt;root namespace&lt;&#x2F;code&gt; is the namespace available to you after a fresh boot of your Operating System. This is a small schema of my configuration showing you where we&#x27;ll start: &lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;root_ns.png&quot; alt=&quot;Root namespace&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;What we will do:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#namespace-creation&quot;&gt;Create a namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#veth-pair-creation&quot;&gt;Create a virtual ethernet device pair&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#assign-on-side-to-namespace&quot;&gt;Assign one side of the veth pair to the namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#ip-addresses&quot;&gt;Assign IP addresses to each side of the veth pair&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#default-route-for-namespace&quot;&gt;Set the default route for our namespace&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;#attach-veth-to-bridge&quot;&gt;Attach the other side of the veth pair to a bridge&lt;&#x2F;a&gt;.
&lt;br&gt;&lt;br&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;network-namespaces&quot;&gt;Network namespaces&lt;&#x2F;h4&gt;
&lt;p&gt;A &lt;strong&gt;namespace&lt;&#x2F;strong&gt; is a way of scoping a particular set of identifiers. You can use the same identifier multiple times in different namespaces. Most importantly, you can also restrict an identifier set visible to particular processes.
&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fact: the set of network interfaces and routing tables are shared across your entire Operating System. &lt;a href=&quot;https:&#x2F;&#x2F;lwn.net&#x2F;Articles&#x2F;580893&#x2F;&quot;&gt;Network namespaces&lt;&#x2F;a&gt; change that fundamental assumption. With network namespaces, you can have different and separate instances of network interfaces and routing tables that operate independent of each other. Let&#x27;s see how it works, using the Python package &lt;a href=&quot;https:&#x2F;&#x2F;pypi.python.org&#x2F;pypi&#x2F;pyroute2&quot;&gt;Pyroute2&lt;&#x2F;a&gt;:
&lt;a name=&quot;namespace-creation&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;pyroute2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;IPDB, IPRoute, NetNS, netns, NSPopen
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;subprocess &lt;&#x2F;span&gt;&lt;span style=&quot;color:#9b9b9b;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;Popen, PIPE
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_namespace1 = IPDB(nl=NetNS(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;))
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; nsp = NSPopen(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ip&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;addr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;], stdout=PIPE)
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;l &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;nsp.communicate()[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;].split(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e3bbab;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;print(l)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;1: lo: &amp;lt;LOOPBACK&amp;gt; mtu 65536 qdisc noop state DOWN group default &amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We&#x27;ve just created a network namespace named &lt;code&gt;namespace1&lt;&#x2F;code&gt;. The &lt;code&gt;ip addr&lt;&#x2F;code&gt; command launched inside the namespace &lt;code&gt;namespace1&lt;&#x2F;code&gt; tells us that there is only one interface, &lt;code&gt;lo&lt;&#x2F;code&gt;.
&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;ns_created.png&quot; alt=&quot;Namespace1 created&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, we need a way to link our newly created namespace, to the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. To do that, virtual ethernet devices, &lt;code&gt;veth pair&lt;&#x2F;code&gt;, need to be created and configured. A &lt;code&gt;veth pair&lt;&#x2F;code&gt; works like a patch cable, connecting two sides. It consists of two virtual interfaces, one of them is assigned to the root network namespace, while the other lives within the network namespace, &lt;code&gt;namespace1&lt;&#x2F;code&gt;:
&lt;a name=&quot;veth-pair-creation&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_root = IPDB() &lt;&#x2F;span&gt;&lt;span style=&quot;color:#608b4e;&quot;&gt;# root namespace
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; ipdb_root.create(ifname=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, kind=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, peer=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;).commit()
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ca:a0:d7:39:57:22&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;peer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;veth_created.png&quot; alt=&quot;Veth pair device created&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Veth pair device created. Both sides of the veth pair device are actually in the &lt;code&gt;root namespace&lt;&#x2F;code&gt;. To link the &lt;code&gt;root namespace&lt;&#x2F;code&gt; to our newly created namespace &lt;code&gt;namespace1&lt;&#x2F;code&gt;, one side of the veth pair device, the peer, should be assigned to &lt;code&gt;namespace1&lt;&#x2F;code&gt;:
&lt;a name=&quot;assign-on-side-to-namespace&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_root.interfaces.vp01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;v:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;v.net_ns_fd = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;namespace1&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;veth_peer_moved.png&quot; alt=&quot;Veth peer moved&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Now, let&#x27;s give IP addresses to all of our interfaces, and set everybody up:
&lt;a name=&quot;ip-addresses&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_root.interfaces.v01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;veth:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.add_ip(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;192.168.1.36&#x2F;24&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;peer&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;f2:2d:aa:9d:16:da&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;v01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_namespace1.interfaces.vp01 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;veth:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.add_ip(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;192.168.1.37&#x2F;24&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...     &lt;&#x2F;span&gt;&lt;span&gt;veth.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;kind&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;veth&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;26:29:f4:06:8a:ea&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1500&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vp01&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ff:ff:ff:ff:ff:ff&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;4098&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span&gt;ipdb_namespace1.interfaces.lo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;i:
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...   &lt;&#x2F;span&gt;&lt;span&gt;i.up()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#569cd6;&quot;&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre data-lang=&quot;python&quot; style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot; class=&quot;language-python &quot;&gt;&lt;code class=&quot;language-python&quot; data-lang=&quot;python&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;flags&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;promiscuity&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;group&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_scope&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;system&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifi_type&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;772&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;linkmode&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipdb_priority&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier_changes&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;address&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;00:00:00:00:00:00&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;mtu&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;65536&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;carrier&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ifname&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;lo&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_tx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;index&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ports&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;vlans&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;ipaddr&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;qdisc&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;noop&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;neighbours&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: [], &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;txqlen&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;broadcast&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;00:00:00:00:00:00&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;operstate&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;DOWN&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;num_rx_queues&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d69d85;&quot;&gt;&amp;#39;family&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#b5cea8;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;At this point, we can open a shell and directly check the configuration for &lt;code&gt;v01&lt;&#x2F;code&gt; interface:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip addr show v01
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;6: v01: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether f2:2d:aa:9d:16:da brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.36&#x2F;24 scope global v01
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::f02d:aaff:fe9d:16da&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;We can also, still from the shell, check the available interfaces inside &lt;code&gt;namespace1&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip netns exec namespace1 ip addr show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 65536 qdisc noqueue state UNKNOWN group default
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
&lt;&#x2F;span&gt;&lt;span&gt;    inet 127.0.0.1&#x2F;8 scope host lo
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 ::1&#x2F;128 scope host
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;5: vp01: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 26:29:f4:06:8a:ea brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.37&#x2F;24 scope global vpeer01
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::2429:f4ff:fe06:8aea&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;A system uses its routing table to determine which network interface to use when sending packets to remote systems. Let&#x27;s make all traffic leaving &lt;code&gt;namespace1&lt;&#x2F;code&gt; to go through &lt;code&gt;v01&lt;&#x2F;code&gt;:
&lt;a name=&quot;default-route-for-namespace&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip netns exec namespace1 ip route add default via 192.168.1.36
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;nskm.xyz&#x2F;posts&#x2F;onn&#x2F;%7Bfilename%7D&#x2F;images&#x2F;default-route-added.png&quot; alt=&quot;Default route added&quot; &#x2F;&gt;
&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I told you I often use LXC containers when I&#x27;m working. For that reason, I always have a bridge configured and up. Then, all the containers are connected to the internet, via the bridge, as &lt;code&gt;ports&lt;&#x2F;code&gt;. Let me show you:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# ip addr show br0
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;4: br0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc noqueue state UP group default
&lt;&#x2F;span&gt;&lt;span&gt;    link&#x2F;ether 3c:97:0e:65:c0:27 brd ff:ff:ff:ff:ff:ff
&lt;&#x2F;span&gt;&lt;span&gt;    inet 192.168.1.34&#x2F;24 brd 192.168.1.255 scope global br0
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;span&gt;    inet6 fe80::3e97:eff:fe65:c027&#x2F;64 scope link
&lt;&#x2F;span&gt;&lt;span&gt;       valid_lft forever preferred_lft forever
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# brctl show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;bridge name     bridge id               STP enabled     interfaces
&lt;&#x2F;span&gt;&lt;span&gt;br0             8000.3c970e65c027       no              eth0
&lt;&#x2F;span&gt;&lt;span&gt;                                                        vethLMRO1N
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
&lt;p&gt;The &lt;code&gt;br0&lt;&#x2F;code&gt; interface is the interface I use for going outside. In fact, &lt;code&gt;br0&lt;&#x2F;code&gt; is a bridge. &lt;code&gt;eth0&lt;&#x2F;code&gt; and &lt;code&gt;vethLMRON&lt;&#x2F;code&gt; are interfaces, &lt;code&gt;ports&lt;&#x2F;code&gt;, attached to that &lt;a href=&quot;http:&#x2F;&#x2F;www.linuxfoundation.org&#x2F;collaborate&#x2F;workgroups&#x2F;networking&#x2F;bridge&quot;&gt;bridge&lt;&#x2F;a&gt;. &lt;code&gt;v01&lt;&#x2F;code&gt; should be attached to the &lt;code&gt;br0&lt;&#x2F;code&gt; bridge, otherwise, &lt;code&gt;v01&lt;&#x2F;code&gt; won&#x27;t be able to send packets to the outside world:
&lt;a name=&quot;attach-veth-to-bridge&quot;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;kintanu:~# brctl addif br0 v01
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~# brctl show
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;pre style=&quot;background-color:#1e1e1e;color:#dcdcdc;&quot;&gt;&lt;code&gt;&lt;span&gt;bridge name     bridge id               STP enabled     interfaces
&lt;&#x2F;span&gt;&lt;span&gt;br0             8000.3c970e65c027       no              eth0
&lt;&#x2F;span&gt;&lt;span&gt;                                                        vethLMRO1N
&lt;&#x2F;span&gt;&lt;span&gt;                                                        v01
&lt;&#x2F;span&gt;&lt;span&gt;kintanu:~#
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;br&gt;
![Veth pair device added to bridge]({filename}&#x2F;images&#x2F;ns.png)
&lt;br&gt;&lt;br&gt;
If everything went fine, you should be able to ping an external host from `namespace1`:
```
kintanu:~# ip netns exec namespace1 ping 8.8.8.8
```
```
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 192.168.1.34: icmp_seq=1 Redirect Host(New nexthop: 192.168.1.1)
64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=104 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=54 time=105 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=54 time=105 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=54 time=104 ms
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min&#x2F;avg&#x2F;max&#x2F;mdev = 104.190&#x2F;104.859&#x2F;105.375&#x2F;0.595 ms
kintanu:~#
```
&lt;br&gt;
&lt;p&gt;We&#x27;ve just seen how to create a network namespace, and link that network namespace to the outside world. When playing with LXC containers, you will also heard about &lt;code&gt;control groups&lt;&#x2F;code&gt;, a kernel mechanism that will allow you to allocate resources among user-defined groups of tasks (processes) running on a system. That will be the topic of the next chapter.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;&#x2F;p&gt;
&lt;p style=&quot;text-align: right;&quot;&gt;All the diagrams were made using [Asciiflow](http:&#x2F;&#x2F;asciiflow.com&#x2F;)&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Introduction</title>
        <published>2015-07-24T00:00:00+00:00</published>
        <updated>2015-07-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://nskm.xyz/posts/intro/"/>
        <id>https://nskm.xyz/posts/intro/</id>
        
        <content type="html" xml:base="https://nskm.xyz/posts/intro/">&lt;p&gt;Hello, I&#x27;m Patrick Di Kiesse, born and raised in central &lt;a href=&quot;#&quot;&gt;Africa&lt;&#x2F;a&gt;, currently based in West Africa, &lt;a href=&quot;#&quot;&gt;Dakar Senegal&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I am an experienced software engineer, passionate about &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt;. I have a strong background in developing backend solutions. With almost 10 years of hands-on experience in the field, I have successfully contributed to &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt; and I have successfully developed and deployed &lt;a href=&quot;#&quot;&gt;numerous&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;software&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;projects&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;across&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;various&lt;&#x2F;a&gt; &lt;a href=&quot;#&quot;&gt;industries&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My expertise lies in &lt;a href=&quot;#&quot;&gt;free software&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;Python programming&lt;&#x2F;a&gt;, &lt;a href=&quot;#&quot;&gt;databases&lt;&#x2F;a&gt;; enabling me to tackle complex challenges and deliver high-quality, scalable software solutions. I thrive in dynamic and collaborative environments, working closely with cross-functional teams to understand requirements, design architectures, and implement robust solutions.&lt;&#x2F;p&gt;
&lt;p&gt;Throughout my career, I have demonstrated a proven track record of delivering projects on time and within budget, while ensuring adherence to best practices and industry standards. I am adept at analyzing existing systems, identifying areas for improvement, and implementing enhancements that optimize performance and user experience.&lt;&#x2F;p&gt;
&lt;p&gt;Over the course of my professional journey, I have had the privilege of &lt;a href=&quot;#&quot;&gt;working as a programming instructor&lt;&#x2F;a&gt; for diverse groups of learners, ranging from beginners to experienced professionals. My &lt;a href=&quot;#&quot;&gt;teaching&lt;&#x2F;a&gt; approach is centered around creating an engaging and supportive &lt;a href=&quot;#&quot;&gt;learning environment&lt;&#x2F;a&gt;, where students can grasp complex concepts with ease and apply them effectively.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond technical skills, I am a team player, strong communicator and effective problem solver. I excel at sharing knowledge, at translating complex technical concepts into clear &amp;amp; non-technical language, fostering effective communication between stakeholders, clients, and development teams.&lt;&#x2F;p&gt;
&lt;p&gt;I am constantly exploring emerging technologies and &lt;a href=&quot;#&quot;&gt;staying up-to-date&lt;&#x2F;a&gt; with industry trends, as I believe in continuous learning and professional growth. I am eager to leverage my skills and expertise to contribute to a dynamic organization, driving innovation and delivering exceptional software solutions.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
