<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Aaqa Ishtyaq</title>
      <link>https://aaqa.dev/</link>
      <description>Aaqa Ishtyaq — Infrastructure engineer exploring ML systems, inference engineering, and distributed computing.</description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://aaqa.dev/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sun, 12 Apr 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>What AI Infrastructure Actually Needs from MicroVMs</title>
          <pubDate>Sun, 12 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/what-ai-infrastructure-needs-from-microvms/</link>
          <guid>https://aaqa.dev/notes/what-ai-infrastructure-needs-from-microvms/</guid>
          <description xml:base="https://aaqa.dev/notes/what-ai-infrastructure-needs-from-microvms/">&lt;p&gt;I have been thinking about AI infrastructure from the compute side more than the model side.&lt;&#x2F;p&gt;
&lt;p&gt;There is a lot of noise around AI infrastructure right now.&lt;&#x2F;p&gt;
&lt;p&gt;Most of it is about models.&lt;&#x2F;p&gt;
&lt;p&gt;The part I care about is everything around the model: where work runs, how fast sandboxes start, how isolated they are, how they reach private tools, how you measure usage, and how you keep the whole thing understandable.&lt;&#x2F;p&gt;
&lt;p&gt;That is where microVMs get interesting.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I want to keep the discussion grounded in the kind of systems work that actually shows up when you build these platforms.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ai-workloads-are-not-just-training-jobs&quot;&gt;AI workloads are not just training jobs&lt;&#x2F;h2&gt;
&lt;p&gt;When people say &quot;AI infra,&quot; they often picture giant GPU clusters.&lt;&#x2F;p&gt;
&lt;p&gt;That is real, but it is only one slice.&lt;&#x2F;p&gt;
&lt;p&gt;A lot of useful AI work looks more like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;short-lived agent sandboxes&lt;&#x2F;li&gt;
&lt;li&gt;code execution environments&lt;&#x2F;li&gt;
&lt;li&gt;retrieval or tool-calling workers&lt;&#x2F;li&gt;
&lt;li&gt;notebook-like interactive sessions&lt;&#x2F;li&gt;
&lt;li&gt;batch jobs that need strong isolation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those workloads want a different set of platform traits.&lt;&#x2F;p&gt;
&lt;p&gt;A simple example is a code interpreter sandbox. It needs to boot fast, run untrusted code in isolation, reach a few internal tools, then disappear cleanly when the task is done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-these-workloads-need&quot;&gt;What these workloads need&lt;&#x2F;h2&gt;
&lt;p&gt;In plain terms, they need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;strong isolation&lt;&#x2F;li&gt;
&lt;li&gt;fast startup&lt;&#x2F;li&gt;
&lt;li&gt;reproducible environments&lt;&#x2F;li&gt;
&lt;li&gt;private networking&lt;&#x2F;li&gt;
&lt;li&gt;simple ingress when needed&lt;&#x2F;li&gt;
&lt;li&gt;usage metering&lt;&#x2F;li&gt;
&lt;li&gt;enough observability to explain cost and latency&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is a pretty good match for microVM-based compute.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-containers-are-not-always-enough&quot;&gt;Why containers are not always enough&lt;&#x2F;h2&gt;
&lt;p&gt;Containers are great. I use them a lot.&lt;&#x2F;p&gt;
&lt;p&gt;But there are cases where a stronger boundary is worth the extra machinery:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;running untrusted user code&lt;&#x2F;li&gt;
&lt;li&gt;isolating agent tasks from each other&lt;&#x2F;li&gt;
&lt;li&gt;giving each workload a cleaner kernel boundary&lt;&#x2F;li&gt;
&lt;li&gt;making network identity and lifecycle more explicit&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;MicroVMs sit in a useful middle space. They are lighter than full traditional VMs and stronger than &quot;just another container on the host.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That middle space is attractive for AI products that need speed and isolation at the same time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fast-startup-matters-more-than-people-admit&quot;&gt;Fast startup matters more than people admit&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of AI workloads are bursty.&lt;&#x2F;p&gt;
&lt;p&gt;An agent wakes up, does work, calls tools, maybe spins up a second task, then disappears. A user opens an interactive environment and expects it to feel ready now, not after a long cold boot. A background job fans out for a few minutes and then goes quiet.&lt;&#x2F;p&gt;
&lt;p&gt;That means startup time is not a side metric.&lt;&#x2F;p&gt;
&lt;p&gt;If you want microVMs to fit these products, you need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;image preparation off the hot path&lt;&#x2F;li&gt;
&lt;li&gt;clone or snapshot paths&lt;&#x2F;li&gt;
&lt;li&gt;warm slots for common environments&lt;&#x2F;li&gt;
&lt;li&gt;scheduling that knows which nodes can activate fast&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is not AI magic. That is platform discipline.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-is-different-from-classic-web-workloads&quot;&gt;Why this is different from classic web workloads&lt;&#x2F;h2&gt;
&lt;p&gt;These workloads are often:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;burstier&lt;&#x2F;li&gt;
&lt;li&gt;more isolated&lt;&#x2F;li&gt;
&lt;li&gt;more expensive when they go wrong&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That changes what you care about. Startup, teardown, and usage accounting all matter more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;private-networking-is-the-sleeper-requirement&quot;&gt;Private networking is the sleeper requirement&lt;&#x2F;h2&gt;
&lt;p&gt;AI workloads often need to reach private things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;internal APIs&lt;&#x2F;li&gt;
&lt;li&gt;databases&lt;&#x2F;li&gt;
&lt;li&gt;vector stores&lt;&#x2F;li&gt;
&lt;li&gt;queues&lt;&#x2F;li&gt;
&lt;li&gt;company tools&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That means the compute environment cannot just be isolated. It has to be connected in a controlled way.&lt;&#x2F;p&gt;
&lt;p&gt;This is where a microVM platform needs a real private network story, not just egress to the public internet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;metering-matters-because-ai-costs-move-fast&quot;&gt;Metering matters because AI costs move fast&lt;&#x2F;h2&gt;
&lt;p&gt;One weak spot in a lot of AI platforms is cost visibility.&lt;&#x2F;p&gt;
&lt;p&gt;A request fans out into a few workers, maybe a browser sandbox, maybe a code executor, maybe a retrieval task, and suddenly nobody is sure what the real billable footprint was.&lt;&#x2F;p&gt;
&lt;p&gt;A microVM platform can help here if it tracks usage cleanly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;how long the machine lived&lt;&#x2F;li&gt;
&lt;li&gt;what shape it had&lt;&#x2F;li&gt;
&lt;li&gt;what resources it consumed&lt;&#x2F;li&gt;
&lt;li&gt;what path it took through the platform&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That does not solve all billing problems, but it gives you a real foundation.&lt;&#x2F;p&gt;
&lt;p&gt;Teardown matters too. If these workloads start fast but linger forever after the useful work is done, the bill still gets ugly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-shape-i-find-compelling&quot;&gt;The shape I find compelling&lt;&#x2F;h2&gt;
&lt;p&gt;This is the platform picture I keep coming back to:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;user request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;control plane&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    +--&amp;gt; warm microVM sandbox&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    +--&amp;gt; private tools &#x2F; data over internal network&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    +--&amp;gt; usage, logs, traces, cleanup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The machine is isolated.
The startup is fast.
The network is private.
The lifecycle is visible.&lt;&#x2F;p&gt;
&lt;p&gt;That is a strong base for AI workloads.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-real-point&quot;&gt;The real point&lt;&#x2F;h2&gt;
&lt;p&gt;I do not think &quot;AI infrastructure&quot; needs a totally separate class of systems.&lt;&#x2F;p&gt;
&lt;p&gt;I think it needs better compute primitives.&lt;&#x2F;p&gt;
&lt;p&gt;MicroVMs become interesting when they stop being a novelty and start acting like those primitives:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;reliable&lt;&#x2F;li&gt;
&lt;li&gt;quick to activate&lt;&#x2F;li&gt;
&lt;li&gt;easy to meter&lt;&#x2F;li&gt;
&lt;li&gt;easy to reason about&lt;&#x2F;li&gt;
&lt;li&gt;safe enough for hostile or messy code&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you can give people that, a lot of AI product shapes get easier to build.&lt;&#x2F;p&gt;
&lt;p&gt;That is why I find this work interesting. The model gets the headlines. The compute platform decides whether the product feels real. That part deserves more attention than it gets. AI products do not just need models. They need fast, isolated, measurable compute.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Scheduling Dense Compute Without Lying to Yourself</title>
          <pubDate>Sat, 11 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/scheduling-dense-compute-without-lying-to-yourself/</link>
          <guid>https://aaqa.dev/notes/scheduling-dense-compute-without-lying-to-yourself/</guid>
          <description xml:base="https://aaqa.dev/notes/scheduling-dense-compute-without-lying-to-yourself/">&lt;p&gt;I have been thinking a lot about scheduling lately, especially once warm starts and reservations enter the picture.&lt;&#x2F;p&gt;
&lt;p&gt;Schedulers are easy to make impressive in a slide deck.&lt;&#x2F;p&gt;
&lt;p&gt;They are much harder to make honest.&lt;&#x2F;p&gt;
&lt;p&gt;You can pack nodes aggressively, overcommit a little, and brag about utilization. Then a few bad placement calls land on the wrong hosts and the whole thing feels brittle.&lt;&#x2F;p&gt;
&lt;p&gt;That is why I care less about flashy scheduling algorithms and more about honest inputs.&lt;&#x2F;p&gt;
&lt;p&gt;In this article, I want to focus on that part.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-first-rule&quot;&gt;The first rule&lt;&#x2F;h2&gt;
&lt;p&gt;Do not schedule from fantasy.&lt;&#x2F;p&gt;
&lt;p&gt;That means your scheduler needs real inputs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;current capacity&lt;&#x2F;li&gt;
&lt;li&gt;reserved capacity&lt;&#x2F;li&gt;
&lt;li&gt;ready slots&lt;&#x2F;li&gt;
&lt;li&gt;machine shape&lt;&#x2F;li&gt;
&lt;li&gt;node health&lt;&#x2F;li&gt;
&lt;li&gt;whether the node should take work&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If any of those are stale or vague, &quot;smart&quot; placement becomes random placement with extra steps.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-free-cpu-is-not-enough&quot;&gt;Why free CPU is not enough&lt;&#x2F;h2&gt;
&lt;p&gt;A node can have free CPU and still be a bad target.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe it is unhealthy.
Maybe it is still recovering.
Maybe it has capacity on paper but not the right prepared images.
Maybe it is already holding reservations for requests that have not committed yet.&lt;&#x2F;p&gt;
&lt;p&gt;This is why a better scheduler tracks more than free resources.&lt;&#x2F;p&gt;
&lt;p&gt;It needs to know the difference between:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;cold capacity&lt;&#x2F;li&gt;
&lt;li&gt;reserved capacity&lt;&#x2F;li&gt;
&lt;li&gt;hot capacity&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those are not the same thing.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a very simple example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;node A has more free CPU, but only cold create capacity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;node B has less free CPU, but already has a matching ready slot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;for latency, node B is the better answer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is why raw free capacity is not enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-reservation-model-fixes-a-lot&quot;&gt;The reservation model fixes a lot&lt;&#x2F;h2&gt;
&lt;p&gt;One thing I like about reservation-based placement is that it forces the scheduler to act with discipline.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of firing real create requests at multiple nodes, it can:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;rank candidates&lt;&#x2F;li&gt;
&lt;li&gt;reserve one&lt;&#x2F;li&gt;
&lt;li&gt;commit to one&lt;&#x2F;li&gt;
&lt;li&gt;activate a ready slot when available&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;That cuts wasted work and keeps placement cleaner.&lt;&#x2F;p&gt;
&lt;p&gt;It also gives the system a way to talk honestly about partial ownership of resources before the machine fully exists.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bad-scheduler-inputs&quot;&gt;Bad scheduler inputs&lt;&#x2F;h2&gt;
&lt;p&gt;The scheduler gets weird quickly if any of these are stale:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;node health&lt;&#x2F;li&gt;
&lt;li&gt;reservations&lt;&#x2F;li&gt;
&lt;li&gt;ready-slot counts&lt;&#x2F;li&gt;
&lt;li&gt;image availability&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At that point, even a clever ranking function starts making dumb choices.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dense-packing-needs-guardrails&quot;&gt;Dense packing needs guardrails&lt;&#x2F;h2&gt;
&lt;p&gt;I am not against dense packing or measured overcommit.&lt;&#x2F;p&gt;
&lt;p&gt;I am against pretending they are free.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to pack nodes tightly, you need:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;clear machine classes&lt;&#x2F;li&gt;
&lt;li&gt;known resource envelopes&lt;&#x2F;li&gt;
&lt;li&gt;health gating&lt;&#x2F;li&gt;
&lt;li&gt;fast rollback when activation fails&lt;&#x2F;li&gt;
&lt;li&gt;good observability around pressure&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Otherwise density turns into support load.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scheduling-is-a-product-decision-too&quot;&gt;Scheduling is a product decision too&lt;&#x2F;h2&gt;
&lt;p&gt;This part gets missed a lot.&lt;&#x2F;p&gt;
&lt;p&gt;The scheduler shapes the product.&lt;&#x2F;p&gt;
&lt;p&gt;If placement is sloppy:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;starts get slower&lt;&#x2F;li&gt;
&lt;li&gt;noisy nodes get noisier&lt;&#x2F;li&gt;
&lt;li&gt;users hit surprise failures&lt;&#x2F;li&gt;
&lt;li&gt;ready slots get wasted&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If placement is sharp:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;fast paths stay fast&lt;&#x2F;li&gt;
&lt;li&gt;node failures are easier to contain&lt;&#x2F;li&gt;
&lt;li&gt;prepared capacity gets used well&lt;&#x2F;li&gt;
&lt;li&gt;the product feels responsive&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why I treat scheduler inputs like user-facing behavior, not background math.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-want-from-a-scheduler&quot;&gt;What I want from a scheduler&lt;&#x2F;h2&gt;
&lt;p&gt;I want the system to answer a few simple questions well:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;which nodes are healthy enough to take work?&lt;&#x2F;li&gt;
&lt;li&gt;which nodes can do a cold create?&lt;&#x2F;li&gt;
&lt;li&gt;which nodes can do a warm activation right now?&lt;&#x2F;li&gt;
&lt;li&gt;which node is already close to the needed image and shape?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is enough to get good results without pretending the platform has perfect foresight.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-lie-to-avoid&quot;&gt;The lie to avoid&lt;&#x2F;h2&gt;
&lt;p&gt;The lie is telling yourself the scheduler is smart because it has a ranking function.&lt;&#x2F;p&gt;
&lt;p&gt;A ranking function over stale or incomplete state is not smart. It is decorative.&lt;&#x2F;p&gt;
&lt;p&gt;Good scheduling starts with good state.&lt;&#x2F;p&gt;
&lt;p&gt;That is why so many &quot;scheduler&quot; problems are really state-distribution problems, health-model problems, or lifecycle-model problems in disguise.&lt;&#x2F;p&gt;
&lt;p&gt;Fix those first.&lt;&#x2F;p&gt;
&lt;p&gt;Then the placement code gets a lot better, even if the algorithm itself stays pretty simple. A scheduler is only as good as the state it believes.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Observability for a MicroVM Platform</title>
          <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/observability-for-a-microvm-platform/</link>
          <guid>https://aaqa.dev/notes/observability-for-a-microvm-platform/</guid>
          <description xml:base="https://aaqa.dev/notes/observability-for-a-microvm-platform/">&lt;p&gt;I love logs, but logs alone have not been enough for the kind of machine lifecycle work I have been doing.&lt;&#x2F;p&gt;
&lt;p&gt;You do not really know a platform until something slow or broken happens.&lt;&#x2F;p&gt;
&lt;p&gt;That is when the nice diagrams stop helping.&lt;&#x2F;p&gt;
&lt;p&gt;A request takes five seconds instead of two hundred milliseconds. A machine gets stuck during startup. A route exists, but traffic still fails. A node looks healthy until you ask one slightly better question.&lt;&#x2F;p&gt;
&lt;p&gt;That is when observability earns its keep.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I want to talk about the kind of visibility I actually want from a microVM platform.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;logs-alone-are-not-enough&quot;&gt;Logs alone are not enough&lt;&#x2F;h2&gt;
&lt;p&gt;Logs matter. I want them. I want structured logs, and I want machine IDs in them.&lt;&#x2F;p&gt;
&lt;p&gt;But logs alone are a rough way to understand a distributed machine lifecycle.&lt;&#x2F;p&gt;
&lt;p&gt;You still end up asking:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;which service started the action?&lt;&#x2F;li&gt;
&lt;li&gt;which node handled it?&lt;&#x2F;li&gt;
&lt;li&gt;which transition was slow?&lt;&#x2F;li&gt;
&lt;li&gt;how long did rootfs prep take?&lt;&#x2F;li&gt;
&lt;li&gt;did networking finish before the guest timed out?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why traces and metrics matter too.&lt;&#x2F;p&gt;
&lt;p&gt;Different signals answer different questions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-want-to-see&quot;&gt;What I want to see&lt;&#x2F;h2&gt;
&lt;p&gt;For a microVM platform, I want visibility at a few levels:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;request level: what API call came in?&lt;&#x2F;li&gt;
&lt;li&gt;machine level: what happened to this machine over time?&lt;&#x2F;li&gt;
&lt;li&gt;node level: is the host healthy and under pressure?&lt;&#x2F;li&gt;
&lt;li&gt;service level: which component is slow or failing?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If those layers do not connect, debugging turns into archaeology.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-fields-i-never-want-to-miss&quot;&gt;The fields I never want to miss&lt;&#x2F;h2&gt;
&lt;p&gt;There are a few fields I always want available when I look at a request or a machine:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;machine id&lt;&#x2F;li&gt;
&lt;li&gt;node id&lt;&#x2F;li&gt;
&lt;li&gt;request id&lt;&#x2F;li&gt;
&lt;li&gt;transition name&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Without those, even good logs and traces start to blur together.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-machine-is-the-unit-that-matters&quot;&gt;The machine is the unit that matters&lt;&#x2F;h2&gt;
&lt;p&gt;The cleanest organizing idea is to treat the machine as the thread through the system.&lt;&#x2F;p&gt;
&lt;p&gt;Every log, metric, and span that can reasonably attach to a machine should do it.&lt;&#x2F;p&gt;
&lt;p&gt;That way you can follow one path:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;API request&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   -&amp;gt; placement&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   -&amp;gt; worker FSM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   -&amp;gt; rootfs prep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   -&amp;gt; network setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   -&amp;gt; guest boot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   -&amp;gt; proxy exposure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Without that thread, you get disconnected facts. With it, you get a story.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-spans-help-so-much&quot;&gt;Why spans help so much&lt;&#x2F;h2&gt;
&lt;p&gt;A machine FSM is a perfect place for spans.&lt;&#x2F;p&gt;
&lt;p&gt;Each transition already has a name and timing boundary. That means the system can show you not just that startup was slow, but where it was slow.&lt;&#x2F;p&gt;
&lt;p&gt;For example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;reserve_node: 8ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;prepare_rootfs: 420ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;setup_network: 95ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wait_for_guest_agent: 1.8s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you have something real to act on.&lt;&#x2F;p&gt;
&lt;p&gt;Without that, &quot;create was slow&quot; is just a complaint.&lt;&#x2F;p&gt;
&lt;p&gt;That also gives you a real debugging loop:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create request looks slow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;trace shows rootfs prep is normal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guest readiness wait is huge&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;look inside guest startup path next&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is a much better place to be than guessing between five different services.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;local-collection-matters&quot;&gt;Local collection matters&lt;&#x2F;h2&gt;
&lt;p&gt;I prefer a node-local collector for a simple reason: it keeps the system robust.&lt;&#x2F;p&gt;
&lt;p&gt;Each host can emit:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;OTLP logs&lt;&#x2F;li&gt;
&lt;li&gt;metrics&lt;&#x2F;li&gt;
&lt;li&gt;traces&lt;&#x2F;li&gt;
&lt;li&gt;machine boot logs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Then a local collector ships them onward.&lt;&#x2F;p&gt;
&lt;p&gt;That makes instrumentation simpler and keeps the service code cleaner.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;good-observability-changes-behavior&quot;&gt;Good observability changes behavior&lt;&#x2F;h2&gt;
&lt;p&gt;Once the signals are strong, the engineering work changes.&lt;&#x2F;p&gt;
&lt;p&gt;You stop guessing.&lt;&#x2F;p&gt;
&lt;p&gt;You stop saying things like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;it might be networking&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;maybe the guest was slow&quot;&lt;&#x2F;li&gt;
&lt;li&gt;&quot;could be the proxy&quot;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You can actually see:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;retry storms&lt;&#x2F;li&gt;
&lt;li&gt;stuck transitions&lt;&#x2F;li&gt;
&lt;li&gt;noisy health probes&lt;&#x2F;li&gt;
&lt;li&gt;node-specific hot spots&lt;&#x2F;li&gt;
&lt;li&gt;slow image paths&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That makes the platform better because the fixes get sharper.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-trap-to-avoid&quot;&gt;The trap to avoid&lt;&#x2F;h2&gt;
&lt;p&gt;The trap is collecting everything and understanding nothing.&lt;&#x2F;p&gt;
&lt;p&gt;A microVM platform already has enough moving parts. If the telemetry model is sloppy, the data turns into clutter.&lt;&#x2F;p&gt;
&lt;p&gt;I would rather have:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;good machine identifiers&lt;&#x2F;li&gt;
&lt;li&gt;a few honest spans&lt;&#x2F;li&gt;
&lt;li&gt;useful node metrics&lt;&#x2F;li&gt;
&lt;li&gt;clean request logs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;than a giant bucket of unlabeled noise.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-boring-outcome-i-want&quot;&gt;The boring outcome I want&lt;&#x2F;h2&gt;
&lt;p&gt;When a user says, &quot;machine create was slow,&quot; I want the answer within minutes.&lt;&#x2F;p&gt;
&lt;p&gt;Not because someone remembered a host by instinct.&lt;&#x2F;p&gt;
&lt;p&gt;Because the system can show:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;where the request went&lt;&#x2F;li&gt;
&lt;li&gt;how placement behaved&lt;&#x2F;li&gt;
&lt;li&gt;which machine transition stalled&lt;&#x2F;li&gt;
&lt;li&gt;what the host looked like at the time&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is what observability is for. Not dashboards for their own sake. Explanations. That is the bar. Good observability does not just collect data. It shortens the path to the right fix.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Host Reconciliation with a Host Agent</title>
          <pubDate>Thu, 09 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/host-reconciliation-with-a-host-agent/</link>
          <guid>https://aaqa.dev/notes/host-reconciliation-with-a-host-agent/</guid>
          <description xml:base="https://aaqa.dev/notes/host-reconciliation-with-a-host-agent/">&lt;p&gt;I actually like SSH. It is useful, fast, and hard to avoid when you are building infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;Still, there is a point in every infrastructure project where SSH becomes a bad habit.&lt;&#x2F;p&gt;
&lt;p&gt;At first it feels fast.&lt;&#x2F;p&gt;
&lt;p&gt;Jump into a box. Edit a file. Restart a service. Fix the thing.&lt;&#x2F;p&gt;
&lt;p&gt;Then the fleet grows, and you realize your operating model is just &quot;hope the last person remembers what changed.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That is not a platform. That is group memory with root access.&lt;&#x2F;p&gt;
&lt;p&gt;This is the thinking behind having a host agent in the first place.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-hosts-need-their-own-owner&quot;&gt;Why hosts need their own owner&lt;&#x2F;h2&gt;
&lt;p&gt;A host running a worker daemon, WireGuard, Corrosion, DNS, and proxy services has real state outside the guest workload.&lt;&#x2F;p&gt;
&lt;p&gt;That state needs ownership.&lt;&#x2F;p&gt;
&lt;p&gt;You need one place that can answer:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;what should be running here?&lt;&#x2F;li&gt;
&lt;li&gt;what revision is applied?&lt;&#x2F;li&gt;
&lt;li&gt;are configs rendered correctly?&lt;&#x2F;li&gt;
&lt;li&gt;is the node healthy enough for placement?&lt;&#x2F;li&gt;
&lt;li&gt;what should happen if the mesh drifts or a service crashes?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is the job I want a host agent to do.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-a-host-agent-should-own&quot;&gt;What a host agent should own&lt;&#x2F;h2&gt;
&lt;p&gt;For me, the host agent should own the boring but important things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;config rendering&lt;&#x2F;li&gt;
&lt;li&gt;service state&lt;&#x2F;li&gt;
&lt;li&gt;revision tracking&lt;&#x2F;li&gt;
&lt;li&gt;health reporting&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If those responsibilities are split across too many scripts and side channels, the host starts drifting faster than the team can keep up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-rule-i-like&quot;&gt;The rule I like&lt;&#x2F;h2&gt;
&lt;p&gt;The host agent should be the only live owner of host mutation.&lt;&#x2F;p&gt;
&lt;p&gt;That sounds strict. It should be.&lt;&#x2F;p&gt;
&lt;p&gt;If half your changes come from bootstrap scripts, a quarter come from direct SSH, and the rest come from local service side effects, you do not have clean recovery. You have overlapping authority.&lt;&#x2F;p&gt;
&lt;p&gt;That leads to drift.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;manifest-driven-hosts-are-calmer-hosts&quot;&gt;Manifest-driven hosts are calmer hosts&lt;&#x2F;h2&gt;
&lt;p&gt;The idea is simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;describe the node in a manifest&lt;&#x2F;li&gt;
&lt;li&gt;let the host agent reconcile toward that state&lt;&#x2F;li&gt;
&lt;li&gt;expose health and admin APIs from the same agent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That gives you a clear loop:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desired node manifest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   host agent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; services &#x2F; configs &#x2F; health state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the node stops being a snowflake and starts being something you can reason about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-matters-for-placement&quot;&gt;Why this matters for placement&lt;&#x2F;h2&gt;
&lt;p&gt;Host health is not just an ops concern. It affects scheduling.&lt;&#x2F;p&gt;
&lt;p&gt;If a node has enough free CPU but its mesh is broken, its config is stale, or its core services are unhealthy, it should not take new work.&lt;&#x2F;p&gt;
&lt;p&gt;That means the host agent should publish health that the control plane can trust:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;ready or not&lt;&#x2F;li&gt;
&lt;li&gt;schedulable or not&lt;&#x2F;li&gt;
&lt;li&gt;drained or not&lt;&#x2F;li&gt;
&lt;li&gt;last error&lt;&#x2F;li&gt;
&lt;li&gt;applied revision&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That turns host management into a real input to compute placement.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;self-healing-without-nonsense&quot;&gt;Self-healing without nonsense&lt;&#x2F;h2&gt;
&lt;p&gt;I like self-healing, but only when it is bounded.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Self-healing&quot; should not mean a daemon thrashing forever while making the node harder to debug.&lt;&#x2F;p&gt;
&lt;p&gt;It should mean a small set of safe actions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;rerun reconcile&lt;&#x2F;li&gt;
&lt;li&gt;restart one broken service&lt;&#x2F;li&gt;
&lt;li&gt;re-check health&lt;&#x2F;li&gt;
&lt;li&gt;cordon if still bad&lt;&#x2F;li&gt;
&lt;li&gt;escalate if retries are exhausted&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is enough.&lt;&#x2F;p&gt;
&lt;p&gt;The host agent should be able to help, not hide the problem.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the kind of drift case I worry about:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;service binary updated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mesh config not updated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;node looks half healthy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;node should report degraded and stop taking work&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is exactly the sort of thing I want a host agent to catch early.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-direct-ssh-should-become-the-exception&quot;&gt;Why direct SSH should become the exception&lt;&#x2F;h2&gt;
&lt;p&gt;SSH is still useful. You need it for deep debugging.&lt;&#x2F;p&gt;
&lt;p&gt;But it should not be the main operating path.&lt;&#x2F;p&gt;
&lt;p&gt;The more routine work you can move into a host agent, the better:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;service restarts&lt;&#x2F;li&gt;
&lt;li&gt;drain and uncordon&lt;&#x2F;li&gt;
&lt;li&gt;health checks&lt;&#x2F;li&gt;
&lt;li&gt;config rendering&lt;&#x2F;li&gt;
&lt;li&gt;support bundle collection&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is how you make the fleet operable by design instead of by folklore.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-matters-even-more-for-small-teams&quot;&gt;This matters even more for small teams&lt;&#x2F;h2&gt;
&lt;p&gt;Big teams can sometimes absorb messy host practices with process and staffing.&lt;&#x2F;p&gt;
&lt;p&gt;Small teams cannot.&lt;&#x2F;p&gt;
&lt;p&gt;If a small team wants to run real infrastructure, it needs systems that reduce memory load. You do not want every fix to require remembering which host has which hand-edited file and which bootstrap flag was last used there.&lt;&#x2F;p&gt;
&lt;p&gt;You want one path.&lt;&#x2F;p&gt;
&lt;p&gt;That is why I think host reconciliation is a first-class platform feature, not just an operations convenience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-simple-bar&quot;&gt;The simple bar&lt;&#x2F;h2&gt;
&lt;p&gt;A healthy host management story should let you answer these questions quickly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;what should be on this node?&lt;&#x2F;li&gt;
&lt;li&gt;what is actually on this node?&lt;&#x2F;li&gt;
&lt;li&gt;is it healthy?&lt;&#x2F;li&gt;
&lt;li&gt;can it take more work?&lt;&#x2F;li&gt;
&lt;li&gt;if not, what is the next safe action?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If the answer still starts with &quot;SSH in and check around,&quot; I do not think the system is done. If hosts mutate from too many places, recovery turns into guesswork.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Why We Built Our Own Machine Proxy</title>
          <pubDate>Wed, 08 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/why-we-built-our-own-machine-proxy/</link>
          <guid>https://aaqa.dev/notes/why-we-built-our-own-machine-proxy/</guid>
          <description xml:base="https://aaqa.dev/notes/why-we-built-our-own-machine-proxy/">&lt;p&gt;When I started thinking about exposing services from machines, one plain question kept showing up:&lt;&#x2F;p&gt;
&lt;p&gt;How does traffic reach a machine?&lt;&#x2F;p&gt;
&lt;p&gt;That question sounds smaller than it is.&lt;&#x2F;p&gt;
&lt;p&gt;Public ingress is not just HTTP. It is TLS, SNI, raw TCP, SSH, WebSSH, machine ownership, and route cleanup when the guest disappears in the middle of the day.&lt;&#x2F;p&gt;
&lt;p&gt;That is a lot of stuff to hand-wave.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I want to explain why I think a machine platform often wants a proxy layer that is tightly tied to the machine lifecycle.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-normal-answer&quot;&gt;The normal answer&lt;&#x2F;h2&gt;
&lt;p&gt;The normal answer is to reach for a big proxy.&lt;&#x2F;p&gt;
&lt;p&gt;That is often reasonable. Envoy, HAProxy, Nginx, Caddy, and friends exist for a reason. You should not rebuild them out of ego.&lt;&#x2F;p&gt;
&lt;p&gt;But sometimes the fit is bad.&lt;&#x2F;p&gt;
&lt;p&gt;In a microVM platform, the proxy has to care about things that general-purpose ingress does not naturally care about:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;per-machine route ownership&lt;&#x2F;li&gt;
&lt;li&gt;fast route add and delete&lt;&#x2F;li&gt;
&lt;li&gt;namespace-aware connections&lt;&#x2F;li&gt;
&lt;li&gt;SSH and WebSSH alongside HTTP&lt;&#x2F;li&gt;
&lt;li&gt;tight integration with machine lifecycle&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When that friction grows, a custom proxy stops sounding like vanity and starts sounding like less glue code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-wanted-from-the-proxy&quot;&gt;What I wanted from the proxy&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted the host-level proxy to do a few things well:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;terminate TLS&lt;&#x2F;li&gt;
&lt;li&gt;expose stable public endpoints&lt;&#x2F;li&gt;
&lt;li&gt;route traffic to the right machine&lt;&#x2F;li&gt;
&lt;li&gt;support HTTP, raw TCP, and SSH flows&lt;&#x2F;li&gt;
&lt;li&gt;clean up routes when machines die&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is not a generic public ingress problem. That is a machine platform problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-lifecycle-integration-matters&quot;&gt;Why lifecycle integration matters&lt;&#x2F;h2&gt;
&lt;p&gt;A machine proxy should not feel like a detached box on the side.&lt;&#x2F;p&gt;
&lt;p&gt;It needs to move with the lifecycle:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;machine starts&lt;&#x2F;li&gt;
&lt;li&gt;route gets registered&lt;&#x2F;li&gt;
&lt;li&gt;DNS gets updated&lt;&#x2F;li&gt;
&lt;li&gt;traffic flows&lt;&#x2F;li&gt;
&lt;li&gt;machine stops&lt;&#x2F;li&gt;
&lt;li&gt;route disappears&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If the route layer lags behind machine truth, you get bad failure modes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;traffic to dead machines&lt;&#x2F;li&gt;
&lt;li&gt;ghost routes&lt;&#x2F;li&gt;
&lt;li&gt;wrong backend after a restart&lt;&#x2F;li&gt;
&lt;li&gt;delayed exposure after machine readiness&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The proxy has to speak the same language as the machine system.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-shape-of-the-design&quot;&gt;The shape of the design&lt;&#x2F;h2&gt;
&lt;p&gt;This is the rough picture:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;internet&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+---------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| proxy   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| TLS     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| SSH     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| routes  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----+----+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| machine  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| netns or |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| backend  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The important part is not the box. It is the ownership.&lt;&#x2F;p&gt;
&lt;p&gt;The proxy should know which machine owns which route and update that state as the machine lifecycle changes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-the-proxy-really-stores&quot;&gt;What the proxy really stores&lt;&#x2F;h2&gt;
&lt;p&gt;At a minimum, the proxy layer usually needs to know:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;hostname&lt;&#x2F;li&gt;
&lt;li&gt;target machine&lt;&#x2F;li&gt;
&lt;li&gt;protocol&lt;&#x2F;li&gt;
&lt;li&gt;port&lt;&#x2F;li&gt;
&lt;li&gt;route ownership&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is enough to make route updates explicit instead of magical.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-not-push-this-into-every-guest&quot;&gt;Why not push this into every guest&lt;&#x2F;h2&gt;
&lt;p&gt;You could make every machine solve its own public ingress.&lt;&#x2F;p&gt;
&lt;p&gt;That would be a mistake.&lt;&#x2F;p&gt;
&lt;p&gt;Now every guest needs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;TLS setup&lt;&#x2F;li&gt;
&lt;li&gt;cert management&lt;&#x2F;li&gt;
&lt;li&gt;public binding logic&lt;&#x2F;li&gt;
&lt;li&gt;exposure policy&lt;&#x2F;li&gt;
&lt;li&gt;maybe even SSH exposure logic&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is duplicated work and a bigger security surface.&lt;&#x2F;p&gt;
&lt;p&gt;A host-level proxy gives the platform one clean place to manage exposure.&lt;&#x2F;p&gt;
&lt;p&gt;That is simpler for operators and better for users.&lt;&#x2F;p&gt;
&lt;p&gt;There is also a very real cleanup race here:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;machine dies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;route still exists&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;next request arrives&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;request goes nowhere&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is why I keep treating ingress as part of the machine lifecycle instead of a detached networking concern.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-underrated-benefit-better-product-shape&quot;&gt;One underrated benefit: better product shape&lt;&#x2F;h2&gt;
&lt;p&gt;Once ingress is owned at the platform layer, you can do nicer things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;stable public hostnames per machine&lt;&#x2F;li&gt;
&lt;li&gt;platform-managed certs&lt;&#x2F;li&gt;
&lt;li&gt;clean SSH entry points&lt;&#x2F;li&gt;
&lt;li&gt;policy around what gets exposed&lt;&#x2F;li&gt;
&lt;li&gt;shared observability around requests and failures&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That turns raw compute into a product with doors and handles.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-your-own-does-not-mean-building-everything&quot;&gt;Building your own does not mean building everything&lt;&#x2F;h2&gt;
&lt;p&gt;There is a good way to do this and a bad way.&lt;&#x2F;p&gt;
&lt;p&gt;The good way is to build the narrow thing your platform actually needs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;route storage&lt;&#x2F;li&gt;
&lt;li&gt;lifecycle hooks&lt;&#x2F;li&gt;
&lt;li&gt;protocol support you really use&lt;&#x2F;li&gt;
&lt;li&gt;cert modes you can operate&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The bad way is to convince yourself you are now in the business of recreating every feature a major proxy has learned over a decade.&lt;&#x2F;p&gt;
&lt;p&gt;I have no interest in the second path.&lt;&#x2F;p&gt;
&lt;p&gt;The goal is not &quot;beat Envoy.&quot; The goal is &quot;remove enough mismatch that the system gets simpler.&quot;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-test-i-use&quot;&gt;The test I use&lt;&#x2F;h2&gt;
&lt;p&gt;If a machine starts, can the route appear quickly?&lt;&#x2F;p&gt;
&lt;p&gt;If a machine dies, can the route disappear cleanly?&lt;&#x2F;p&gt;
&lt;p&gt;If an operator asks who owns a route, is the answer obvious?&lt;&#x2F;p&gt;
&lt;p&gt;If the answer to those questions is yes, the proxy is doing its job.&lt;&#x2F;p&gt;
&lt;p&gt;That is the level I care about. Not theoretical flexibility. Real ownership. That is what I care about here. Ingress is a lifecycle problem as much as a networking problem.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Making Internal DNS Boring for Private Machines</title>
          <pubDate>Tue, 07 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/making-internal-dns-boring/</link>
          <guid>https://aaqa.dev/notes/making-internal-dns-boring/</guid>
          <description xml:base="https://aaqa.dev/notes/making-internal-dns-boring/">&lt;p&gt;Once private networking starts to work, DNS becomes the next obvious problem.&lt;&#x2F;p&gt;
&lt;p&gt;If private networking is the road system, DNS is the street sign.&lt;&#x2F;p&gt;
&lt;p&gt;And like street signs, you only notice it when it is wrong.&lt;&#x2F;p&gt;
&lt;p&gt;Nothing makes a platform feel flaky faster than this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the machine is up&lt;&#x2F;li&gt;
&lt;li&gt;the network path works&lt;&#x2F;li&gt;
&lt;li&gt;the name still does not resolve&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That gap is small on paper and painful in real use.&lt;&#x2F;p&gt;
&lt;p&gt;I have run into this enough times that I now care a lot about keeping internal DNS boring.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-want-from-internal-dns&quot;&gt;What I want from internal DNS&lt;&#x2F;h2&gt;
&lt;p&gt;I want internal DNS to be so boring people stop asking how it works.&lt;&#x2F;p&gt;
&lt;p&gt;That means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;every machine can resolve private names&lt;&#x2F;li&gt;
&lt;li&gt;the answer does not depend on which node happens to host the resolver&lt;&#x2F;li&gt;
&lt;li&gt;moving a machine should not change the model&lt;&#x2F;li&gt;
&lt;li&gt;stale node-local state should not quietly break resolution&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If DNS depends too much on local accidents, the whole private network feels less trustworthy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stable-identity-beats-node-local-cleverness&quot;&gt;Stable identity beats node-local cleverness&lt;&#x2F;h2&gt;
&lt;p&gt;One tempting design is to make the guest ask a node-specific resolver.&lt;&#x2F;p&gt;
&lt;p&gt;That sounds easy because the host is right there.&lt;&#x2F;p&gt;
&lt;p&gt;The problem is that it leaks host details into the guest model. Now the guest is coupled to where it landed. If the node changes, the path changes. If node-local state drifts, resolution changes. If the resolver is healthy on one node and stale on another, you get weird half-failures.&lt;&#x2F;p&gt;
&lt;p&gt;A better model is simple:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the guest uses one stable DNS service identity&lt;&#x2F;li&gt;
&lt;li&gt;the host makes that identity work locally&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That keeps the guest contract clean.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-matters-more-than-it-sounds&quot;&gt;Why this matters more than it sounds&lt;&#x2F;h2&gt;
&lt;p&gt;Service discovery is one of those things people treat as an accessory until they build real workloads.&lt;&#x2F;p&gt;
&lt;p&gt;The moment you have:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;app talking to database&lt;&#x2F;li&gt;
&lt;li&gt;app talking to cache&lt;&#x2F;li&gt;
&lt;li&gt;one machine calling another by name&lt;&#x2F;li&gt;
&lt;li&gt;a short-lived environment that should behave like a real network&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;you need names you can trust.&lt;&#x2F;p&gt;
&lt;p&gt;Something as simple as &lt;code&gt;db.internal&lt;&#x2F;code&gt; should just work. The user should not have to know which node hosts the database or which host is running the resolver.&lt;&#x2F;p&gt;
&lt;p&gt;IP addresses are fine for debugging. They are bad user experience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-shape-i-like&quot;&gt;The shape I like&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the guest-facing model:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guest:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  query .internal name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;stable DNS VIP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;worker-local dns service&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;answer from replicated machine&#x2F;network state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The guest always talks to the same destination.&lt;&#x2F;p&gt;
&lt;p&gt;The host does the local termination and lookup work.&lt;&#x2F;p&gt;
&lt;p&gt;That split is what makes the system feel stable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keep-lookup-data-close-to-the-truth&quot;&gt;Keep lookup data close to the truth&lt;&#x2F;h2&gt;
&lt;p&gt;The second part of the DNS problem is data freshness.&lt;&#x2F;p&gt;
&lt;p&gt;If name records are built from stale side tables or delayed repair logic, DNS becomes the first place you notice drift.&lt;&#x2F;p&gt;
&lt;p&gt;That is usually what bad DNS feels like in practice:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the machine is up&lt;&#x2F;li&gt;
&lt;li&gt;packets are flowing&lt;&#x2F;li&gt;
&lt;li&gt;the name still fails&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That kind of bug wastes a lot of time because it makes people question the whole network even when only one part is broken.&lt;&#x2F;p&gt;
&lt;p&gt;That is why the data feeding DNS should come from the same control-plane truth that placement and machine ownership use. Different products can wire that differently, but the principle stays the same:&lt;&#x2F;p&gt;
&lt;p&gt;Do not make DNS invent its own reality.&lt;&#x2F;p&gt;
&lt;p&gt;It should reflect the authoritative view of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;what machine exists&lt;&#x2F;li&gt;
&lt;li&gt;what network it belongs to&lt;&#x2F;li&gt;
&lt;li&gt;what private address it owns&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Freshness matters too. If DNS updates lag too much, users stop trusting names and start pasting IPs into config files.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-small-thing-that-changes-the-whole-product&quot;&gt;A small thing that changes the whole product&lt;&#x2F;h2&gt;
&lt;p&gt;When internal DNS is good, everything above it gets easier:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;config files get simpler&lt;&#x2F;li&gt;
&lt;li&gt;local dev feels closer to production&lt;&#x2F;li&gt;
&lt;li&gt;private services stop needing copy-pasted IPs&lt;&#x2F;li&gt;
&lt;li&gt;cross-machine workflows become natural&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When internal DNS is bad, users build shadow systems:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;hardcoded addresses&lt;&#x2F;li&gt;
&lt;li&gt;host file hacks&lt;&#x2F;li&gt;
&lt;li&gt;startup scripts that query the control plane directly&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is usually a sign the platform contract is weak.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;boring-is-the-win&quot;&gt;Boring is the win&lt;&#x2F;h2&gt;
&lt;p&gt;The best internal DNS story is not impressive.&lt;&#x2F;p&gt;
&lt;p&gt;It is just this:&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Every machine gets a private name, every other machine can resolve it, and nobody has to think about which worker host is involved.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That is the result I want. Not clever. Just reliable. If users keep reaching for IP addresses, the internal DNS contract is probably weak.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Private Networking for MicroVM Fleets with WireGuard and IPv6</title>
          <pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/private-networking-for-microvms-wireguard-ipv6/</link>
          <guid>https://aaqa.dev/notes/private-networking-for-microvms-wireguard-ipv6/</guid>
          <description xml:base="https://aaqa.dev/notes/private-networking-for-microvms-wireguard-ipv6/">&lt;p&gt;After getting machines to boot reliably, networking was the next thing that forced me to slow down and think properly.&lt;&#x2F;p&gt;
&lt;p&gt;Private networking sounds simple when you say it quickly.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Just let the machines talk to each other.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Then you try to do it across hosts, across regions, across reboots, without handing every guest a pile of custom firewall rules and mystery routing.&lt;&#x2F;p&gt;
&lt;p&gt;That is where the clean model matters.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I want to explain the network shape I find the most reasonable for a microVM fleet.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-wanted-from-the-network&quot;&gt;What I wanted from the network&lt;&#x2F;h2&gt;
&lt;p&gt;For a microVM platform, the private network should feel boring from inside the guest.&lt;&#x2F;p&gt;
&lt;p&gt;The guest should not care:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;which host it landed on&lt;&#x2F;li&gt;
&lt;li&gt;which physical node hosts its peer&lt;&#x2F;li&gt;
&lt;li&gt;whether a node got replaced&lt;&#x2F;li&gt;
&lt;li&gt;how the control plane exchanged peer state&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The guest should know one thing: it has a private address and packets to that private world work.&lt;&#x2F;p&gt;
&lt;p&gt;That is the standard.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-ipv6-helps&quot;&gt;Why IPv6 helps&lt;&#x2F;h2&gt;
&lt;p&gt;IPv4 can do this, but it starts fights you do not need.&lt;&#x2F;p&gt;
&lt;p&gt;With IPv6, you can give every machine a clean private identity without squeezing everything through tiny address space and heavy NAT habits. It makes the addressing model easier to reason about.&lt;&#x2F;p&gt;
&lt;p&gt;That matters because the address can carry meaning:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;node identity&lt;&#x2F;li&gt;
&lt;li&gt;machine identity&lt;&#x2F;li&gt;
&lt;li&gt;network membership&lt;&#x2F;li&gt;
&lt;li&gt;policy boundaries&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Not magical meaning. Useful meaning.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-wireguard-fits&quot;&gt;Why WireGuard fits&lt;&#x2F;h2&gt;
&lt;p&gt;Once you have more than one host, you need a private fabric between them.&lt;&#x2F;p&gt;
&lt;p&gt;WireGuard is a good fit because it is simple, fast, and kernel-native. It also gives you a clean identity model with keys instead of a giant pile of TLS setup for every internal hop.&lt;&#x2F;p&gt;
&lt;p&gt;At a high level:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guest VM --tap--&amp;gt; worker host --WireGuard--&amp;gt; remote worker host --tap--&amp;gt; guest VM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The worker hosts form the mesh. The guests ride on top of it.&lt;&#x2F;p&gt;
&lt;p&gt;That lets the platform keep a simple promise:&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Your machine has a private address, and that address works across the fleet.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;Here is the packet path I keep in my head:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&amp;gt; tap device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&amp;gt; local worker host&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&amp;gt; WireGuard mesh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&amp;gt; remote worker host&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&amp;gt; remote tap device&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&amp;gt; remote guest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;do-not-mix-guest-routing-and-dns-identity&quot;&gt;Do not mix guest routing and DNS identity&lt;&#x2F;h2&gt;
&lt;p&gt;One subtle mistake is to blur two separate ideas:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the next hop a guest should route through&lt;&#x2F;li&gt;
&lt;li&gt;the stable identity of the DNS service it should query&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those are not the same thing.&lt;&#x2F;p&gt;
&lt;p&gt;The next hop is local. It is about how a packet leaves the guest and reaches the host.&lt;&#x2F;p&gt;
&lt;p&gt;The DNS service identity should be stable. It should not change just because the guest moved or the node got replaced.&lt;&#x2F;p&gt;
&lt;p&gt;Once those concepts stay separate, the network gets less weird.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-control-plane-trap&quot;&gt;The control-plane trap&lt;&#x2F;h2&gt;
&lt;p&gt;There is a bigger design lesson here too.&lt;&#x2F;p&gt;
&lt;p&gt;Do not make your whole control plane depend on the same network it is still trying to heal.&lt;&#x2F;p&gt;
&lt;p&gt;That circular dependency creates awful failure modes.&lt;&#x2F;p&gt;
&lt;p&gt;If peer updates only arrive over the mesh, and the mesh is broken because peer updates are stale, you have built a trap for yourself.&lt;&#x2F;p&gt;
&lt;p&gt;The data plane and the control plane can talk to each other, but they should not hold each other hostage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;failure-modes-that-matter&quot;&gt;Failure modes that matter&lt;&#x2F;h2&gt;
&lt;p&gt;The failure modes here are not always dramatic. They are often annoying:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a stale peer endpoint means packets go to the wrong place&lt;&#x2F;li&gt;
&lt;li&gt;a bad route means the guest has an address but no path&lt;&#x2F;li&gt;
&lt;li&gt;the guest can reach the network, but DNS still fails&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those are the cases that make a platform feel flaky even when part of the design is working.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-good-looks-like&quot;&gt;What &quot;good&quot; looks like&lt;&#x2F;h2&gt;
&lt;p&gt;A good private network for microVMs has a few traits:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;every guest gets a stable private identity&lt;&#x2F;li&gt;
&lt;li&gt;east-west traffic works across hosts&lt;&#x2F;li&gt;
&lt;li&gt;guest routing is host-local and predictable&lt;&#x2F;li&gt;
&lt;li&gt;policy can be enforced without hand-crafted snowflake rules&lt;&#x2F;li&gt;
&lt;li&gt;DNS does not depend on the guest knowing host details&lt;&#x2F;li&gt;
&lt;li&gt;host replacement does not force the guest model to change&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is the shape I want:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            private fleet network&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   VM A            worker A           worker B            VM B&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  fdaa::10  &amp;lt;--&amp;gt;   mesh0    &amp;lt;====&amp;gt;    mesh0    &amp;lt;--&amp;gt;     fdaa::20&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     WG mesh          WG mesh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The guest sees a private world. The host does the ugly work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-matters-for-compute-products&quot;&gt;Why this matters for compute products&lt;&#x2F;h2&gt;
&lt;p&gt;Private networking is not a side quest.&lt;&#x2F;p&gt;
&lt;p&gt;It is what makes the platform useful for anything beyond isolated toy workloads.&lt;&#x2F;p&gt;
&lt;p&gt;You need it for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;service-to-service communication&lt;&#x2F;li&gt;
&lt;li&gt;private databases&lt;&#x2F;li&gt;
&lt;li&gt;multi-machine test environments&lt;&#x2F;li&gt;
&lt;li&gt;agent sandboxes that call internal tools&lt;&#x2F;li&gt;
&lt;li&gt;distributed jobs that should not be public on the internet&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Without a clean private network, everything gets forced through public exposure or weird host tunnels. That is not a platform. That is a workaround farm.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-real-win&quot;&gt;The real win&lt;&#x2F;h2&gt;
&lt;p&gt;The best network design is the one users forget.&lt;&#x2F;p&gt;
&lt;p&gt;They should not need to know which node owns the WireGuard peer, which route got reconciled, or which host-local device delivered the packet.&lt;&#x2F;p&gt;
&lt;p&gt;They should know their machine has a private address and the packet gets where it should go. That is boring. Boring is the goal. The guest should see one private network, even if the hosts underneath are messy.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Fast Starts: Snapshots, Clones, and Warm Slots for MicroVMs</title>
          <pubDate>Sun, 05 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/fast-starts-snapshots-clones-and-warm-slots/</link>
          <guid>https://aaqa.dev/notes/fast-starts-snapshots-clones-and-warm-slots/</guid>
          <description xml:base="https://aaqa.dev/notes/fast-starts-snapshots-clones-and-warm-slots/">&lt;p&gt;One of the things I care about most in a compute platform is startup time.&lt;&#x2F;p&gt;
&lt;p&gt;People say they want fast machine starts.&lt;&#x2F;p&gt;
&lt;p&gt;What they usually mean is they do not want to wait while your platform does cold work right in front of them.&lt;&#x2F;p&gt;
&lt;p&gt;That distinction matters a lot.&lt;&#x2F;p&gt;
&lt;p&gt;If you create a machine from scratch on demand, you are paying for a bunch of slow steps in public:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;prepare a root filesystem&lt;&#x2F;li&gt;
&lt;li&gt;create overlays&lt;&#x2F;li&gt;
&lt;li&gt;set up networking&lt;&#x2F;li&gt;
&lt;li&gt;boot or restore Firecracker&lt;&#x2F;li&gt;
&lt;li&gt;wait for the guest agent&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even when each step is pretty fast, the total is not.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a rough way to think about that budget:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rootfs prep: hundreds of ms to seconds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;network setup: tens to hundreds of ms&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;boot or restore: hundreds of ms to seconds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guest readiness: hundreds of ms to seconds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;None of those numbers are scary on their own.&lt;&#x2F;p&gt;
&lt;p&gt;Stack them together on the request path and they stop feeling cheap.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cold-create-is-not-the-enemy&quot;&gt;Cold create is not the enemy&lt;&#x2F;h2&gt;
&lt;p&gt;Cold create is fine. You need it. It is the fallback path and the general path.&lt;&#x2F;p&gt;
&lt;p&gt;The mistake is pretending cold create can also be your instant path.&lt;&#x2F;p&gt;
&lt;p&gt;If you care about interactive workloads, dev environments, agent sandboxes, or bursty compute, you need a different shape:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;prepare ahead of time&lt;&#x2F;li&gt;
&lt;li&gt;reserve capacity before doing expensive work&lt;&#x2F;li&gt;
&lt;li&gt;activate something already close to ready&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is where snapshots, clones, and warm slots come in.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I want to walk through how I think about those three paths.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;three-levels-of-speed&quot;&gt;Three levels of speed&lt;&#x2F;h2&gt;
&lt;p&gt;I like to think about machine startup in three buckets.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-fresh-boot&quot;&gt;1. Fresh boot&lt;&#x2F;h3&gt;
&lt;p&gt;This is the full path. Pull image. Build filesystem. Boot guest. Wait for readiness.&lt;&#x2F;p&gt;
&lt;p&gt;It is the most flexible and the slowest.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-clone-from-a-prepared-source&quot;&gt;2. Clone from a prepared source&lt;&#x2F;h3&gt;
&lt;p&gt;This path reuses a known-good base, often through snapshot or overlay tricks. It cuts a lot of setup time, but there is still work to do.&lt;&#x2F;p&gt;
&lt;p&gt;It is much better, but not instant.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;3-warm-activation&quot;&gt;3. Warm activation&lt;&#x2F;h3&gt;
&lt;p&gt;This path claims something already prepared and nearly ready.&lt;&#x2F;p&gt;
&lt;p&gt;That is the path that can feel snappy.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the rough picture:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fresh create:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  image pull -&amp;gt; rootfs prep -&amp;gt; network -&amp;gt; boot -&amp;gt; ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;clone:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  prepared base -&amp;gt; overlay&#x2F;snapshot -&amp;gt; network -&amp;gt; restore -&amp;gt; ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;warm activation:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  claim ready slot -&amp;gt; attach identity -&amp;gt; expose -&amp;gt; run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The third path is where good latency lives.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-reservation-matters&quot;&gt;Why reservation matters&lt;&#x2F;h2&gt;
&lt;p&gt;One easy mistake is to fan out real work to multiple nodes and let the fastest winner keep running.&lt;&#x2F;p&gt;
&lt;p&gt;That looks clever until you notice the waste.&lt;&#x2F;p&gt;
&lt;p&gt;Two or three nodes may do expensive rootfs and startup work for one user request. The losers then roll back after burning CPU, IO, and time.&lt;&#x2F;p&gt;
&lt;p&gt;That is not a fast path. It is a messy betting strategy.&lt;&#x2F;p&gt;
&lt;p&gt;A better model is:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;rank nodes&lt;&#x2F;li&gt;
&lt;li&gt;reserve one node&lt;&#x2F;li&gt;
&lt;li&gt;commit cold work to that node only&lt;&#x2F;li&gt;
&lt;li&gt;use warm activation when an exact match already exists&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This keeps the fast path honest.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-importance-of-exact-match&quot;&gt;The importance of exact match&lt;&#x2F;h2&gt;
&lt;p&gt;Warm pools sound great until you make them fuzzy.&lt;&#x2F;p&gt;
&lt;p&gt;If a warm slot is only &quot;kind of close&quot; to what the user asked for, activation turns into mutation, and mutation turns back into cold work.&lt;&#x2F;p&gt;
&lt;p&gt;So the identity of a warm slot needs to be strict:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;image digest&lt;&#x2F;li&gt;
&lt;li&gt;machine shape&lt;&#x2F;li&gt;
&lt;li&gt;restore capability&lt;&#x2F;li&gt;
&lt;li&gt;any other setup that changes startup cost or correctness&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That lets the scheduler ask a sharp question:&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Do I already have a prepared thing that exactly matches this request?&quot;&lt;&#x2F;p&gt;
&lt;p&gt;If yes, activate it.&lt;&#x2F;p&gt;
&lt;p&gt;If no, reserve a node for cold work and move on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-breaks-warm-starts&quot;&gt;What breaks warm starts&lt;&#x2F;h2&gt;
&lt;p&gt;Warm starts stop being warm pretty quickly when one of these shows up:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the image digest does not match&lt;&#x2F;li&gt;
&lt;li&gt;the machine shape does not match&lt;&#x2F;li&gt;
&lt;li&gt;the prepared state is stale&lt;&#x2F;li&gt;
&lt;li&gt;the guest still has expensive init work left to do&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why I do not like fuzzy warm capacity. Either it is a real ready slot for this request, or it is not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;speed-without-lying&quot;&gt;Speed without lying&lt;&#x2F;h2&gt;
&lt;p&gt;The biggest risk in performance work is cheating.&lt;&#x2F;p&gt;
&lt;p&gt;You call something fast because one internal benchmark looked nice, but the real path still hides slow work in the same request.&lt;&#x2F;p&gt;
&lt;p&gt;I do not want &quot;fast&quot; to mean:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;it was cached on one node once&lt;&#x2F;li&gt;
&lt;li&gt;the loser nodes cleaned up eventually&lt;&#x2F;li&gt;
&lt;li&gt;we skipped a correctness check&lt;&#x2F;li&gt;
&lt;li&gt;the guest was not actually ready yet&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I want it to mean the user asked for a machine and got a usable machine quickly, without hidden waste and without crossed fingers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-user-facing-payoff&quot;&gt;The user-facing payoff&lt;&#x2F;h2&gt;
&lt;p&gt;When this is done well, the platform feels different.&lt;&#x2F;p&gt;
&lt;p&gt;It stops feeling like &quot;please wait while we build your environment&quot; and starts feeling closer to &quot;your environment is here.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That opens the door for better product shapes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;on-demand dev machines&lt;&#x2F;li&gt;
&lt;li&gt;ephemeral test environments&lt;&#x2F;li&gt;
&lt;li&gt;short-lived AI sandboxes&lt;&#x2F;li&gt;
&lt;li&gt;burst compute for jobs that should start now&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those experiences depend less on the hypervisor and more on how smart the control plane is about prepared capacity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-real-challenge&quot;&gt;The real challenge&lt;&#x2F;h2&gt;
&lt;p&gt;The hard part is not building one fast restore path.&lt;&#x2F;p&gt;
&lt;p&gt;The hard part is managing the whole life around it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;how many warm slots to keep&lt;&#x2F;li&gt;
&lt;li&gt;which image digests deserve them&lt;&#x2F;li&gt;
&lt;li&gt;when to recycle them&lt;&#x2F;li&gt;
&lt;li&gt;how to avoid stale prepared state&lt;&#x2F;li&gt;
&lt;li&gt;how to represent ready slots to the scheduler&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why fast activation is a control-plane problem as much as a Firecracker problem.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-simple-summary&quot;&gt;The simple summary&lt;&#x2F;h2&gt;
&lt;p&gt;Cold create is necessary.&lt;&#x2F;p&gt;
&lt;p&gt;Clone paths are useful.&lt;&#x2F;p&gt;
&lt;p&gt;Warm activation is what changes the feel of the product.&lt;&#x2F;p&gt;
&lt;p&gt;And if you want warm activation to work well, you need more than a snapshot trick. You need clear reservation semantics, exact identity, and a scheduler that knows the difference between &quot;this node has free CPU&quot; and &quot;this node has a prepared machine I can claim right now.&quot; That difference is where a lot of the speed comes from. Fast start is mostly about moving slow work off the user path.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Stateless Regional Control Planes and Replicated State</title>
          <pubDate>Sat, 04 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/stateless-regional-control-plane-with-gossip-state/</link>
          <guid>https://aaqa.dev/notes/stateless-regional-control-plane-with-gossip-state/</guid>
          <description xml:base="https://aaqa.dev/notes/stateless-regional-control-plane-with-gossip-state/">&lt;p&gt;I like control planes that can die without drama.&lt;&#x2F;p&gt;
&lt;p&gt;If a regional API process restarts, I do not want a rescue mission. I want it to come back, rebuild what it needs, and keep serving traffic.&lt;&#x2F;p&gt;
&lt;p&gt;That pushes you toward a simple rule:&lt;&#x2F;p&gt;
&lt;p&gt;The control plane should not own more durable state than it has to.&lt;&#x2F;p&gt;
&lt;p&gt;I ran into this while thinking through the regional control plane. The more state I wanted to push into it, the less I liked the system.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-old-temptation&quot;&gt;The old temptation&lt;&#x2F;h2&gt;
&lt;p&gt;The easy design is familiar.&lt;&#x2F;p&gt;
&lt;p&gt;Workers report into a central database. The regional service reads and writes that database. Over time it becomes a big cache, a queue, and a graveyard of stale rows all at once.&lt;&#x2F;p&gt;
&lt;p&gt;That works until it does not.&lt;&#x2F;p&gt;
&lt;p&gt;The cracks show up in boring places:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a node reboots and stale machine records survive&lt;&#x2F;li&gt;
&lt;li&gt;capacity data lags behind reality&lt;&#x2F;li&gt;
&lt;li&gt;different regional instances read slightly different views&lt;&#x2F;li&gt;
&lt;li&gt;cleanup relies on rows that no longer mean what they used to&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The database becomes the place where old assumptions go to live forever.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-better-split&quot;&gt;A better split&lt;&#x2F;h2&gt;
&lt;p&gt;The worker already has the facts about its own machines. So let it publish enough of those facts for the control plane to read.&lt;&#x2F;p&gt;
&lt;p&gt;That changes the flow:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;before:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  worker -&amp;gt; central DB -&amp;gt; control plane&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;after:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  worker -&amp;gt; replicated cluster state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  control plane -&amp;gt; read local replica&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The second model has better failure behavior.&lt;&#x2F;p&gt;
&lt;p&gt;The control plane is now a reader, scheduler, and router. It is not the sole keeper of facts it did not create.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-the-control-plane-should-not-know&quot;&gt;What the control plane should not know&lt;&#x2F;h2&gt;
&lt;p&gt;There is also plenty the control plane does not need to know in detail:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;every host-side cleanup step&lt;&#x2F;li&gt;
&lt;li&gt;every boot log line&lt;&#x2F;li&gt;
&lt;li&gt;every process-level detail on the worker&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It needs enough shared state to decide and route well. It does not need to mirror the entire private life of every node.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-matters-in-practice&quot;&gt;Why this matters in practice&lt;&#x2F;h2&gt;
&lt;p&gt;Stateless does not mean dumb.&lt;&#x2F;p&gt;
&lt;p&gt;The regional control plane still does real work:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;auth&lt;&#x2F;li&gt;
&lt;li&gt;placement&lt;&#x2F;li&gt;
&lt;li&gt;network lifecycle&lt;&#x2F;li&gt;
&lt;li&gt;machine lookup&lt;&#x2F;li&gt;
&lt;li&gt;routing decisions&lt;&#x2F;li&gt;
&lt;li&gt;health-based placement&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The difference is that it does not need its own database to do that work well.&lt;&#x2F;p&gt;
&lt;p&gt;It can boot, connect to its local replica, warm an in-memory cache if needed, and start answering questions.&lt;&#x2F;p&gt;
&lt;p&gt;If it dies, no truth is lost.&lt;&#x2F;p&gt;
&lt;p&gt;That is a much healthier role.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-replicated-state-buys-you&quot;&gt;What replicated state buys you&lt;&#x2F;h2&gt;
&lt;p&gt;The control plane needs cluster facts, but not all facts.&lt;&#x2F;p&gt;
&lt;p&gt;It mostly needs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;node health&lt;&#x2F;li&gt;
&lt;li&gt;node capacity&lt;&#x2F;li&gt;
&lt;li&gt;machine placement&lt;&#x2F;li&gt;
&lt;li&gt;network allocation state&lt;&#x2F;li&gt;
&lt;li&gt;enough metadata to route and schedule safely&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Those are all good candidates for shared replicated state.&lt;&#x2F;p&gt;
&lt;p&gt;Corrosion became the interesting piece here. It shifts the cluster away from &quot;everything goes through one central writer&quot; and toward &quot;the writer is close to the machine activity it is reporting.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;That matches reality better.&lt;&#x2F;p&gt;
&lt;p&gt;Reading from a local replica helps too. It cuts the cost of always reaching back to one central place before the control plane can answer a simple question.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-hard-part-is-not-replication&quot;&gt;The hard part is not replication&lt;&#x2F;h2&gt;
&lt;p&gt;The hard part is deciding what deserves replication.&lt;&#x2F;p&gt;
&lt;p&gt;If you replicate too little, the control plane gets blind.&lt;&#x2F;p&gt;
&lt;p&gt;If you replicate too much, you turn shared state into a kitchen sink and make rollouts painful.&lt;&#x2F;p&gt;
&lt;p&gt;The trick is to replicate the facts needed for decisions, not every private detail of a node&#x27;s internal life.&lt;&#x2F;p&gt;
&lt;p&gt;I think about it like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;local only:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  step-by-step recovery detail&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  process-local cleanup bookkeeping&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  short-lived machine state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;replicated:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  node capacity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  machine ownership&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  placement-visible health&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  network membership&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  routeable identity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That boundary keeps the cluster readable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;stateless-makes-life-easier&quot;&gt;Stateless makes life easier&lt;&#x2F;h2&gt;
&lt;p&gt;There is a human reason to want this too.&lt;&#x2F;p&gt;
&lt;p&gt;A control plane with its own fragile state store becomes a thing you are scared to touch. You babysit migrations. You wonder if a failover will leak meaning. You start planning around the database instead of around the product.&lt;&#x2F;p&gt;
&lt;p&gt;A stateless regional service is easier to operate, easier to scale, and easier to trust.&lt;&#x2F;p&gt;
&lt;p&gt;Start a new one. Stop an old one. Move it. Replace it.&lt;&#x2F;p&gt;
&lt;p&gt;That should be routine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-more-benefit-the-architecture-gets-honest&quot;&gt;One more benefit: the architecture gets honest&lt;&#x2F;h2&gt;
&lt;p&gt;When the regional layer stops pretending to own everything, the system reads more clearly:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;workers report machine state&lt;&#x2F;li&gt;
&lt;li&gt;the cluster replicates scheduling truth&lt;&#x2F;li&gt;
&lt;li&gt;the regional service consumes that truth to make decisions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is a crisp model.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the simplest version of it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          write state                  read state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;worker -----------------&amp;gt; replicated state -----------------&amp;gt; regional control plane&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   ^                                                              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   |                                                              |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   +--------------------- commands back --------------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The loop is tight, and each side has a job. That is what I want from a control plane. Not magic. Just clean ownership. The control plane needs enough shared state to decide. It does not need every detail to operate.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>How a Worker Node Runs a MicroVM</title>
          <pubDate>Fri, 03 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/how-a-worker-node-runs-a-microvm/</link>
          <guid>https://aaqa.dev/notes/how-a-worker-node-runs-a-microvm/</guid>
          <description xml:base="https://aaqa.dev/notes/how-a-worker-node-runs-a-microvm/">&lt;p&gt;After removing the earlier draft for this slot, I still wanted a post here that explains one of the most important parts of the platform: what actually happens on the worker node when a machine gets created.&lt;&#x2F;p&gt;
&lt;p&gt;This part matters because a lot of the rest of the system only makes sense once you know what the worker is responsible for.&lt;&#x2F;p&gt;
&lt;p&gt;The control plane can pick a node. The proxy can expose traffic. DNS can hand out names. None of that means much until one worker host actually does the job of turning a request into a running microVM.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-worker-is-where-the-request-becomes-real&quot;&gt;The worker is where the request becomes real&lt;&#x2F;h2&gt;
&lt;p&gt;At a high level, the worker daemon is the part of the system that takes a machine request and does the host-side work needed to bring it to life.&lt;&#x2F;p&gt;
&lt;p&gt;That usually means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;validating the machine request&lt;&#x2F;li&gt;
&lt;li&gt;preparing the filesystem&lt;&#x2F;li&gt;
&lt;li&gt;setting up the network&lt;&#x2F;li&gt;
&lt;li&gt;starting Firecracker&lt;&#x2F;li&gt;
&lt;li&gt;waiting for the guest to come up&lt;&#x2F;li&gt;
&lt;li&gt;exposing the machine to the rest of the platform&lt;&#x2F;li&gt;
&lt;li&gt;cleaning up if something fails halfway through&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is a lot of responsibility for one service, but it is the right place for it. The worker host is where the machine actually lives, so it needs the code that knows how to deal with the messy details.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-flow-i-keep-in-my-head&quot;&gt;The flow I keep in my head&lt;&#x2F;h2&gt;
&lt;p&gt;This is the simplest version of the worker-side flow:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;create request arrives&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  validate + record intent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  prepare root filesystem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  setup network namespace, tap, routes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  write VM config + start Firecracker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  wait for guest agent to become ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  register machine with proxy &#x2F; DNS &#x2F; control plane&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Real life is messier than that, but if this mental model is clear, the rest of the platform gets easier to follow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-the-worker-leaves-behind-on-disk&quot;&gt;What the worker leaves behind on disk&lt;&#x2F;h2&gt;
&lt;p&gt;Even a short-lived machine usually leaves behind a few concrete things on the host while it is running:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a kernel image&lt;&#x2F;li&gt;
&lt;li&gt;a root filesystem or overlay&lt;&#x2F;li&gt;
&lt;li&gt;a VM config&lt;&#x2F;li&gt;
&lt;li&gt;logs&lt;&#x2F;li&gt;
&lt;li&gt;sockets or control files&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is another reason cleanup matters so much. These are not abstract objects. They are real files and real resources on a real box.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-1-take-the-request-seriously&quot;&gt;Step 1: take the request seriously&lt;&#x2F;h2&gt;
&lt;p&gt;The first part sounds boring, but it is important.&lt;&#x2F;p&gt;
&lt;p&gt;When the worker gets a create request, it cannot just charge ahead and hope for the best. It needs to make sure:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the shape of the machine makes sense&lt;&#x2F;li&gt;
&lt;li&gt;the node has enough room&lt;&#x2F;li&gt;
&lt;li&gt;the image or base is available&lt;&#x2F;li&gt;
&lt;li&gt;the request can be tracked if the host dies halfway through&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is one reason I like durable lifecycle logic so much. If the process crashes after step three out of seven, the worker still needs enough information to continue or clean up properly when it comes back.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-2-prepare-the-filesystem&quot;&gt;Step 2: prepare the filesystem&lt;&#x2F;h2&gt;
&lt;p&gt;Before the guest boots, the worker has to prepare the disk the machine will use.&lt;&#x2F;p&gt;
&lt;p&gt;Depending on the path, that can mean:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;pulling an image&lt;&#x2F;li&gt;
&lt;li&gt;unpacking a root filesystem&lt;&#x2F;li&gt;
&lt;li&gt;creating an overlay&lt;&#x2F;li&gt;
&lt;li&gt;cloning from a prepared base&lt;&#x2F;li&gt;
&lt;li&gt;restoring from a snapshot-backed setup&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This step has a huge effect on startup time.&lt;&#x2F;p&gt;
&lt;p&gt;It is also one of the places where wasted work hurts the most. If two nodes both prepare filesystems for one request and only one wins, that is real IO and real time thrown away.&lt;&#x2F;p&gt;
&lt;p&gt;That is why I care so much about reservations and prepared capacity in the later posts.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-slow-parts&quot;&gt;The slow parts&lt;&#x2F;h2&gt;
&lt;p&gt;If I had to point to the places that most often dominate startup time, it would usually be these:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;filesystem prep&lt;&#x2F;li&gt;
&lt;li&gt;network bring-up&lt;&#x2F;li&gt;
&lt;li&gt;waiting for the guest to be ready&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The worker does all three, which is why it ends up sitting right on the critical path.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-3-build-the-network-around-the-guest&quot;&gt;Step 3: build the network around the guest&lt;&#x2F;h2&gt;
&lt;p&gt;Once the filesystem is ready, the worker still has to build the network shape the machine expects.&lt;&#x2F;p&gt;
&lt;p&gt;That usually means creating or wiring up:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a network namespace&lt;&#x2F;li&gt;
&lt;li&gt;a tap device&lt;&#x2F;li&gt;
&lt;li&gt;routes&lt;&#x2F;li&gt;
&lt;li&gt;addressing&lt;&#x2F;li&gt;
&lt;li&gt;any host-side policy needed for isolation&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the part that makes a machine feel less like &quot;a Firecracker process&quot; and more like &quot;a guest that actually lives on a host and can talk to things.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;It is also the step that causes a lot of annoying bugs if you are sloppy. A machine can boot fine and still be useless because the host-side network was only half-configured.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-4-start-firecracker&quot;&gt;Step 4: start Firecracker&lt;&#x2F;h2&gt;
&lt;p&gt;Once the assets are in place, the worker can finally hand things over to Firecracker.&lt;&#x2F;p&gt;
&lt;p&gt;That means building the VM config, pointing Firecracker at the right kernel and drives, starting the process, and then watching closely.&lt;&#x2F;p&gt;
&lt;p&gt;This is the step people usually think is the whole problem.&lt;&#x2F;p&gt;
&lt;p&gt;It is not.&lt;&#x2F;p&gt;
&lt;p&gt;It is a very important step, but by the time you get here, the worker has already done a lot of heavy lifting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-5-wait-for-the-guest-to-be-usable&quot;&gt;Step 5: wait for the guest to be usable&lt;&#x2F;h2&gt;
&lt;p&gt;A VM process existing is not the same thing as a usable machine.&lt;&#x2F;p&gt;
&lt;p&gt;This is one of those details that matters a lot in practice.&lt;&#x2F;p&gt;
&lt;p&gt;If you return success too early, the rest of the system starts acting as if the machine is ready when it really is not. Then you get weird timing bugs:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the proxy points to a machine that is not listening yet&lt;&#x2F;li&gt;
&lt;li&gt;the control plane thinks startup succeeded&lt;&#x2F;li&gt;
&lt;li&gt;the user connects before the guest finished booting&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So the worker needs a clear readiness signal from inside the guest. Until that signal shows up, the machine is still starting.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-6-plug-the-machine-into-the-platform&quot;&gt;Step 6: plug the machine into the platform&lt;&#x2F;h2&gt;
&lt;p&gt;Once the guest is actually ready, the worker can expose it to the rest of the system.&lt;&#x2F;p&gt;
&lt;p&gt;That can include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;registering routes with the proxy&lt;&#x2F;li&gt;
&lt;li&gt;publishing private network identity&lt;&#x2F;li&gt;
&lt;li&gt;publishing DNS data&lt;&#x2F;li&gt;
&lt;li&gt;reporting machine state back to the control plane&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the point where the machine stops being &quot;something being built on one host&quot; and becomes &quot;something the platform can route to and reason about.&quot;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;step-7-clean-up-hard-when-things-go-wrong&quot;&gt;Step 7: clean up hard when things go wrong&lt;&#x2F;h2&gt;
&lt;p&gt;This part is easy to underestimate.&lt;&#x2F;p&gt;
&lt;p&gt;Machines do not only fail at clean points. They fail halfway through.&lt;&#x2F;p&gt;
&lt;p&gt;You can end up with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a prepared filesystem but no VM&lt;&#x2F;li&gt;
&lt;li&gt;a VM process but broken networking&lt;&#x2F;li&gt;
&lt;li&gt;a route registered for a machine that never became ready&lt;&#x2F;li&gt;
&lt;li&gt;a half-created overlay&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why the worker daemon cannot just know how to start machines. It has to know how to recover and how to clean up.&lt;&#x2F;p&gt;
&lt;p&gt;For me, that is one of the main differences between a demo and a platform.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-worker-is-the-heart-of-the-node&quot;&gt;The worker is the heart of the node&lt;&#x2F;h2&gt;
&lt;p&gt;Once I started looking at the system this way, a lot of other design choices made more sense.&lt;&#x2F;p&gt;
&lt;p&gt;The control plane should stay focused on placement and coordination.&lt;&#x2F;p&gt;
&lt;p&gt;The worker should own the machine lifecycle on the node.&lt;&#x2F;p&gt;
&lt;p&gt;The proxy should care about exposure.&lt;&#x2F;p&gt;
&lt;p&gt;DNS should care about names.&lt;&#x2F;p&gt;
&lt;p&gt;The host agent should care about host-level drift and health.&lt;&#x2F;p&gt;
&lt;p&gt;That split keeps the jobs clear.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-i-wanted-this-post-in-the-series&quot;&gt;Why I wanted this post in the series&lt;&#x2F;h2&gt;
&lt;p&gt;I wanted one post early in the series that answers a simple question:&lt;&#x2F;p&gt;
&lt;p&gt;When a machine gets created, what does one worker host actually do?&lt;&#x2F;p&gt;
&lt;p&gt;For me, the answer is:&lt;&#x2F;p&gt;
&lt;p&gt;It takes a request, prepares the machine, builds the network around it, starts the guest, waits until it is actually usable, plugs it into the rest of the platform, and cleans up if anything goes wrong.&lt;&#x2F;p&gt;
&lt;p&gt;That is a lot of work.&lt;&#x2F;p&gt;
&lt;p&gt;It is also where the platform becomes real. The worker does much more than start Firecracker. It builds the machine around it.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Why a MicroVM Platform Needs a Crash-Resistant Machine FSM</title>
          <pubDate>Thu, 02 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/crash-resistant-machine-fsms/</link>
          <guid>https://aaqa.dev/notes/crash-resistant-machine-fsms/</guid>
          <description xml:base="https://aaqa.dev/notes/crash-resistant-machine-fsms/">&lt;p&gt;While working on the worker side of the platform, one thing became obvious pretty quickly: machine lifecycle code looks easy only when you test happy paths.&lt;&#x2F;p&gt;
&lt;p&gt;Create a machine. Start it. Stop it. Delete it.&lt;&#x2F;p&gt;
&lt;p&gt;That idea falls apart the first time a host reboots halfway through startup.&lt;&#x2F;p&gt;
&lt;p&gt;Now you have harder questions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Was the VM process created?&lt;&#x2F;li&gt;
&lt;li&gt;Did networking finish?&lt;&#x2F;li&gt;
&lt;li&gt;Did the root filesystem get prepared?&lt;&#x2F;li&gt;
&lt;li&gt;Did the API return before the host died?&lt;&#x2F;li&gt;
&lt;li&gt;Should restart continue, roll back, or wait?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You cannot answer those questions with request handlers and hope.&lt;&#x2F;p&gt;
&lt;p&gt;That is why I keep coming back to a durable machine FSM.&lt;&#x2F;p&gt;
&lt;p&gt;In this article, I want to explain why I think this matters so much.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem-with-one-shot-handlers&quot;&gt;The problem with one-shot handlers&lt;&#x2F;h2&gt;
&lt;p&gt;A normal HTTP handler wants to do work and return. That is fine for small things. It is not fine for machine lifecycle.&lt;&#x2F;p&gt;
&lt;p&gt;Machine lifecycle is long, messy, and full of partial failure. It has steps that touch:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;local storage&lt;&#x2F;li&gt;
&lt;li&gt;network namespaces&lt;&#x2F;li&gt;
&lt;li&gt;cgroups&lt;&#x2F;li&gt;
&lt;li&gt;Firecracker process state&lt;&#x2F;li&gt;
&lt;li&gt;proxy registration&lt;&#x2F;li&gt;
&lt;li&gt;DNS registration&lt;&#x2F;li&gt;
&lt;li&gt;snapshots&lt;&#x2F;li&gt;
&lt;li&gt;cleanup&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If each endpoint owns its own little workflow, recovery gets scattered everywhere. One path retries here. Another path cleans up there. A third path adds a special boot-time scan to heal the leftovers.&lt;&#x2F;p&gt;
&lt;p&gt;You end up with a system where every bug fix adds one more side lane.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-the-fsm-gives-you&quot;&gt;What the FSM gives you&lt;&#x2F;h2&gt;
&lt;p&gt;The useful part of an FSM is not the word &quot;state machine.&quot; The useful part is discipline.&lt;&#x2F;p&gt;
&lt;p&gt;You write down:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the current durable state&lt;&#x2F;li&gt;
&lt;li&gt;the desired next state&lt;&#x2F;li&gt;
&lt;li&gt;the allowed transitions&lt;&#x2F;li&gt;
&lt;li&gt;the work for each transition that is safe to run twice&lt;&#x2F;li&gt;
&lt;li&gt;what to do when the process comes back after a crash&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That forces the system to stop improvising.&lt;&#x2F;p&gt;
&lt;p&gt;I like to think of it this way:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;request handler:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  validate input&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  record desired change&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  wake machine run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;machine run:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  inspect durable state&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  inspect what is really on the host&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  do the next safe step&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  persist progress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  repeat until steady&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That split is boring, which is exactly why it works.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-key-idea-one-main-machine-run&quot;&gt;The key idea: one main machine run&lt;&#x2F;h2&gt;
&lt;p&gt;The clean model is one main run per machine.&lt;&#x2F;p&gt;
&lt;p&gt;Not one FSM for create, another for stop, another for cleanup, and a startup reconciler that tries to guess what the others meant.&lt;&#x2F;p&gt;
&lt;p&gt;One machine run.&lt;&#x2F;p&gt;
&lt;p&gt;That run owns the job of moving the machine toward its desired state.&lt;&#x2F;p&gt;
&lt;p&gt;It can decide:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;should this machine be started?&lt;&#x2F;li&gt;
&lt;li&gt;does it need cleanup?&lt;&#x2F;li&gt;
&lt;li&gt;is the VM still alive?&lt;&#x2F;li&gt;
&lt;li&gt;did the last transition finish?&lt;&#x2F;li&gt;
&lt;li&gt;do we need to recover from a crash?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is the shape:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;desired state + durable record + observed reality&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            +-----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            | machine   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            |   run     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            +-----------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      +-----------+------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      |           |            |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      v           v            v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   create      start        destroy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   network     wait         cleanup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   rootfs      recover      release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That machine run becomes the adult in the room.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-real-failure-case&quot;&gt;A real failure case&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the kind of failure that changed how I think about this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;network setup succeeds&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Firecracker starts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;guest never becomes ready&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;host reboots&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;machine run resumes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;system decides whether to retry, wait, or destroy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If your lifecycle model cannot explain that sequence cleanly, it is going to leak mess all over the node.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;safe-retries-are-not-optional&quot;&gt;Safe retries are not optional&lt;&#x2F;h2&gt;
&lt;p&gt;The most important phrase in lifecycle code is not &quot;fast.&quot; It is &quot;safe to run twice.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;If the host crashes after setting up a tap device but before marking the step complete, you need to be able to run that step again without making things worse.&lt;&#x2F;p&gt;
&lt;p&gt;Same for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;creating directories&lt;&#x2F;li&gt;
&lt;li&gt;allocating leases&lt;&#x2F;li&gt;
&lt;li&gt;registering routes&lt;&#x2F;li&gt;
&lt;li&gt;restoring snapshots&lt;&#x2F;li&gt;
&lt;li&gt;deleting leftovers&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The system should be able to ask, &quot;What is true right now?&quot; and then move one safe step forward.&lt;&#x2F;p&gt;
&lt;p&gt;If your lifecycle logic depends on perfect memory of the previous process, it will fail in production.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cleanup-has-to-be-first-class&quot;&gt;Cleanup has to be first-class&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of systems treat cleanup like an apology at the end.&lt;&#x2F;p&gt;
&lt;p&gt;That is backwards.&lt;&#x2F;p&gt;
&lt;p&gt;Cleanup is part of the lifecycle. It needs the same level of care as create.&lt;&#x2F;p&gt;
&lt;p&gt;When a machine dies badly, the leftovers are not random junk. They are real resources:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;disk overlays&lt;&#x2F;li&gt;
&lt;li&gt;snapshots&lt;&#x2F;li&gt;
&lt;li&gt;proxy routes&lt;&#x2F;li&gt;
&lt;li&gt;IP allocations&lt;&#x2F;li&gt;
&lt;li&gt;namespaces&lt;&#x2F;li&gt;
&lt;li&gt;DNS records&lt;&#x2F;li&gt;
&lt;li&gt;leases&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If cleanup is scattered across handlers, deferred callbacks, and boot-time repair code, it will drift.&lt;&#x2F;p&gt;
&lt;p&gt;When cleanup is owned by the same machine run that owns creation, the system gets simpler. There is one place that knows what the machine owns and one place that can release it safely.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-this-matters-for-user-facing-latency&quot;&gt;Why this matters for user-facing latency&lt;&#x2F;h2&gt;
&lt;p&gt;This is not just a correctness story. It affects speed too.&lt;&#x2F;p&gt;
&lt;p&gt;A good FSM lets you separate cold work from fast work.&lt;&#x2F;p&gt;
&lt;p&gt;It lets you:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;prepare assets ahead of time&lt;&#x2F;li&gt;
&lt;li&gt;resume interrupted work instead of starting over&lt;&#x2F;li&gt;
&lt;li&gt;expose exact lifecycle state to the control plane&lt;&#x2F;li&gt;
&lt;li&gt;measure where time really goes&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Without that, every slow start looks the same from the outside. You have no idea whether the machine was waiting on rootfs prep, network setup, guest boot, or cleanup from a previous failure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-watch-for-now&quot;&gt;What I watch for now&lt;&#x2F;h2&gt;
&lt;p&gt;When I read lifecycle code, I ask a few blunt questions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is there one owner of recovery and cleanup?&lt;&#x2F;li&gt;
&lt;li&gt;Can it resume after a crash?&lt;&#x2F;li&gt;
&lt;li&gt;Are transitions explicit?&lt;&#x2F;li&gt;
&lt;li&gt;Is cleanup part of the same model?&lt;&#x2F;li&gt;
&lt;li&gt;Can every step run twice safely?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If the answer is no, the code may still work on a laptop. It will not stay honest under load.&lt;&#x2F;p&gt;
&lt;p&gt;For me, that is the real value of the machine FSM. It gives the platform a way to explain half-finished work instead of just leaving a mess behind. If a machine lifecycle cannot resume after a crash, it is not finished.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Building a MicroVM Control Plane in Public</title>
          <pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/building-a-microvm-control-plane/</link>
          <guid>https://aaqa.dev/notes/building-a-microvm-control-plane/</guid>
          <description xml:base="https://aaqa.dev/notes/building-a-microvm-control-plane/">&lt;p&gt;Over the past couple of years, I have been spending a lot of time with Firecracker, microVMs, and a distributed compute platform I have been building.&lt;&#x2F;p&gt;
&lt;p&gt;It started with a simple goal: run Firecracker on a machine I control and understand every moving part.&lt;&#x2F;p&gt;
&lt;p&gt;That sounds small, but it really is not.&lt;&#x2F;p&gt;
&lt;p&gt;The first few steps are easy enough to explain. Boot a VM. Get KVM working. Start Firecracker. Launch a guest. Once that works, the next question shows up right away: what if this was not one machine, but a fleet?&lt;&#x2F;p&gt;
&lt;p&gt;That is where the real work starts.&lt;&#x2F;p&gt;
&lt;p&gt;Running one microVM is a neat trick. Running thousands means you need a control plane. You need placement, state, networking, ingress, observability, cleanup, and recovery when the host does something rude like reboot in the middle of a machine start.&lt;&#x2F;p&gt;
&lt;p&gt;In this post, I want to set up the rest of the series and talk about that jump.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-shape-of-the-system&quot;&gt;The shape of the system&lt;&#x2F;h2&gt;
&lt;p&gt;Over time, the repo turned into a small compute platform with a few clear pieces:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;a regional control-plane service decides where work should go&lt;&#x2F;li&gt;
&lt;li&gt;a worker daemon runs machines on worker hosts&lt;&#x2F;li&gt;
&lt;li&gt;an image service prepares root filesystems from OCI images&lt;&#x2F;li&gt;
&lt;li&gt;an ingress proxy handles public traffic, TLS, and SSH access&lt;&#x2F;li&gt;
&lt;li&gt;an internal DNS service gives private names to machines&lt;&#x2F;li&gt;
&lt;li&gt;a host agent owns host-level changes and node health&lt;&#x2F;li&gt;
&lt;li&gt;a guest agent runs inside the guest and brings the machine to life&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At a high level it looks like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                public API&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +--------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | regional API |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | placement    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             | auth         |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             +------+-------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          commands &#x2F; reads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     +--------------+------------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     |                                 |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     v                                 v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------------+                   +------------+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| worker     |                   | worker     |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;| worker A   |                   | worker B   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+------+-----+                   +------+-----+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       |                                |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       | local services                 | local services&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;       v                                v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  image service &#x2F; ingress proxy &#x2F; DNS &#x2F; host agent &#x2F; Firecracker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That diagram is clean. The real thing was not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-request-in-motion&quot;&gt;A request in motion&lt;&#x2F;h2&gt;
&lt;p&gt;One of the easiest ways to understand the platform is to follow one machine request from start to finish:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;client asks for a machine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;control plane picks a worker&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;worker prepares and starts the machine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;proxy and DNS get updated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        v&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;user reaches a running machine&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That flow looks simple on paper.&lt;&#x2F;p&gt;
&lt;p&gt;The hard part is everything hiding inside each step.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-first-lesson-every-shortcut-becomes-a-subsystem&quot;&gt;The first lesson: every shortcut becomes a subsystem&lt;&#x2F;h2&gt;
&lt;p&gt;Early on, a lot of things can live in shell scripts and one-off flows. That is normal. You need speed while you are learning.&lt;&#x2F;p&gt;
&lt;p&gt;Then the edges show up.&lt;&#x2F;p&gt;
&lt;p&gt;You need network setup that works every time, not just on a good day. You need logs that survive long enough to explain a bad boot. You need to know if a machine is still real after the host process dies. You need a way to expose HTTP and SSH without making every guest solve TLS and routing on its own.&lt;&#x2F;p&gt;
&lt;p&gt;Each shortcut turns into a real component:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Root filesystem prep becomes a real image service.&lt;&#x2F;li&gt;
&lt;li&gt;Traffic routing becomes a real ingress proxy.&lt;&#x2F;li&gt;
&lt;li&gt;Guest boot logic becomes a guest agent.&lt;&#x2F;li&gt;
&lt;li&gt;Host reconciliation becomes a host agent.&lt;&#x2F;li&gt;
&lt;li&gt;Cluster state becomes a control-plane problem, not a local script problem.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is the pattern I keep coming back to: small experiments turn into real features faster than you think.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-second-lesson-the-hard-parts-are-not-the-obvious-parts&quot;&gt;The second lesson: the hard parts are not the obvious parts&lt;&#x2F;h2&gt;
&lt;p&gt;People hear &quot;microVM platform&quot; and think the hard part is booting Firecracker.&lt;&#x2F;p&gt;
&lt;p&gt;It is not.&lt;&#x2F;p&gt;
&lt;p&gt;Booting Firecracker is table stakes. The real pain lives in everything around it:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;deciding where a machine should run&lt;&#x2F;li&gt;
&lt;li&gt;cleaning up half-failed starts&lt;&#x2F;li&gt;
&lt;li&gt;preserving state across crashes&lt;&#x2F;li&gt;
&lt;li&gt;connecting private networks across hosts&lt;&#x2F;li&gt;
&lt;li&gt;making machine names resolve correctly&lt;&#x2F;li&gt;
&lt;li&gt;exposing services without leaking the whole host&lt;&#x2F;li&gt;
&lt;li&gt;understanding why one request took 150ms and the next took 5s&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The control plane is not glamorous, but it is the difference between a demo and a platform.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-third-lesson-state-is-the-whole-game&quot;&gt;The third lesson: state is the whole game&lt;&#x2F;h2&gt;
&lt;p&gt;Once you run more than one node, you stop asking &quot;did the API succeed?&quot; and start asking better questions:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What happens if the writer crashes after the side effect but before the state update?&lt;&#x2F;li&gt;
&lt;li&gt;What if two nodes both think they own the same action?&lt;&#x2F;li&gt;
&lt;li&gt;What data can be rebuilt, and what data must survive?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is why so much of this series ends up talking about FSMs, state replication, networking, and cleanup paths. Those are not side details. That is the platform.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-i-am-writing-this-series&quot;&gt;Why I am writing this series&lt;&#x2F;h2&gt;
&lt;p&gt;There is a lot of writing about containers, and there is a lot of writing about big cloud systems. There is less writing about the middle ground: building your own compute platform when you still want to understand every moving piece.&lt;&#x2F;p&gt;
&lt;p&gt;That middle ground is where most of the interesting tradeoffs live.&lt;&#x2F;p&gt;
&lt;p&gt;You do not have infinite headcount. You do not want five databases because a diagram looked impressive. You do not want a service mesh because you got bored. You want a system that can survive failure, stay understandable, and move fast enough to keep building.&lt;&#x2F;p&gt;
&lt;p&gt;That is the lens for the posts that follow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-is-coming-next&quot;&gt;What is coming next&lt;&#x2F;h2&gt;
&lt;p&gt;This series will cover:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;durable machine state and crash recovery&lt;&#x2F;li&gt;
&lt;li&gt;how a worker node actually brings up a machine&lt;&#x2F;li&gt;
&lt;li&gt;how a stateless regional control plane can still make good decisions&lt;&#x2F;li&gt;
&lt;li&gt;faster starts with snapshots, clones, and warm slots&lt;&#x2F;li&gt;
&lt;li&gt;private networking for microVM fleets&lt;&#x2F;li&gt;
&lt;li&gt;boring internal DNS&lt;&#x2F;li&gt;
&lt;li&gt;ingress and SSH routing&lt;&#x2F;li&gt;
&lt;li&gt;host reconciliation and self-healing&lt;&#x2F;li&gt;
&lt;li&gt;observability that can explain real failures&lt;&#x2F;li&gt;
&lt;li&gt;scheduling compute without cheating&lt;&#x2F;li&gt;
&lt;li&gt;what this all means for AI workloads&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That is the kind of system I am aiming for here: small enough to understand, but solid enough to run real work. A single microVM is mostly a runtime problem. A fleet of microVMs is a coordination problem.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Move untracked git files to another directory</title>
          <pubDate>Tue, 19 Mar 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/move-git-untracked-files-to-temp-dir/</link>
          <guid>https://aaqa.dev/notes/move-git-untracked-files-to-temp-dir/</guid>
          <description xml:base="https://aaqa.dev/notes/move-git-untracked-files-to-temp-dir/">&lt;p&gt;I had a lot of files in a git repository, which I didn&#x27;t want to add in &lt;code&gt;git&lt;&#x2F;code&gt;, So to remove all of them
to a temporary directory I used a collection of Unix commands.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; status&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-porcelain&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; awk&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{print $2}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; xargs&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ..&#x2F;scratch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</description>
      </item>
      <item>
          <title>Animal Farm by George Orwell</title>
          <pubDate>Thu, 07 Mar 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/reading/animal-farm-george-orwell/</link>
          <guid>https://aaqa.dev/reading/animal-farm-george-orwell/</guid>
          <description xml:base="https://aaqa.dev/reading/animal-farm-george-orwell/">
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;animal_farm.761b7c351effac79.jpg&quot; alt=&quot;Image generated using Adobe Firefly AI&quot;&gt;
  &lt;figcaption&gt;Image generated using Adobe Firefly AI&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;I picked up &lt;em&gt;Animal Farm&lt;&#x2F;em&gt; right after &lt;a href=&quot;&#x2F;reading&#x2F;1984-george-orwell&quot;&gt;1984&lt;&#x2F;a&gt;. I expected something smaller and easier. It is smaller. It is not easier.&lt;&#x2F;p&gt;
&lt;p&gt;The plot is almost too neat. Animals kick out the farmer, promise a better world, and end up under a new set of tyrants. Orwell keeps it plain, which is exactly why it works. Nothing feels dressed up. You watch the hope drain out of the farm step by step.&lt;&#x2F;p&gt;
&lt;p&gt;That slow slide is the whole book. Nobody wakes up one morning and says the revolution is dead. The rules change a little. The language gets slippery. The animals get tired. They start doubting what they saw with their own eyes. By the time the truth is fully broken, they do not have much left to fight with.&lt;&#x2F;p&gt;
&lt;p&gt;Boxer got to me more than anyone else. He is loyal, decent, hardworking, and completely unequipped for the kind of lies being used against him. Napoleon is awful in a colder way. He does not need charm. He just needs control, patience, and the right people to repeat his version of events.&lt;&#x2F;p&gt;
&lt;p&gt;What stayed with me most is how familiar the book feels. Not because life is literally a farm run by pigs, obviously. Because Orwell understands how people get managed. Keep them busy. Keep them confused. Give them a slogan. Change the record. Do it again.&lt;&#x2F;p&gt;
&lt;p&gt;It is a sharp book. Mean, too. I finished it with that bad taste you get when a story stops feeling like a story and starts feeling like a pattern you have seen before.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;If you have thoughts on the book, ping me on Twitter &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Pulga, Kalga - Himachal Pradesh 2024</title>
          <pubDate>Tue, 05 Mar 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/travel/fairy-forest-pulga-kalga/</link>
          <guid>https://aaqa.dev/travel/fairy-forest-pulga-kalga/</guid>
          <description xml:base="https://aaqa.dev/travel/fairy-forest-pulga-kalga/">&lt;p&gt;In the heart of Himachal&#x27;s Parvati Valley lie its hidden gems: Pulga and Kalga. Picture-perfect villages embraced by towering mountains, where every corner tells a story of nature&#x27;s magnificence. Here, snow-capped peaks stand tall, kissing the sky, while icy waterfalls dance down the slopes, painting the landscape with their pure, untamed beauty. Despite the biting cold, every moment feels like a warm embrace from Mother Nature herself. It&#x27;s not just a trip; it&#x27;s a journey of awe, wonder, and connection with the raw essence of the mountains.&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;1.5e577373be6e4c5a.png&quot; alt=&quot;&quot;&gt;
  &lt;figcaption&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
 \&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;2.2773b9820d90fe11.png&quot; alt=&quot;&quot;&gt;
  &lt;figcaption&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
 \&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;3.6d603f61e8595e65.png&quot; alt=&quot;&quot;&gt;
  &lt;figcaption&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
 \&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;4.e226c101a075352a.png&quot; alt=&quot;&quot;&gt;
  &lt;figcaption&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
 \&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;5.24606b3d4aeaec9b.png&quot; alt=&quot;&quot;&gt;
  &lt;figcaption&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
 \&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>1984 by George Orwell</title>
          <pubDate>Sat, 03 Feb 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/reading/1984-george-orwell/</link>
          <guid>https://aaqa.dev/reading/1984-george-orwell/</guid>
          <description xml:base="https://aaqa.dev/reading/1984-george-orwell/">
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;1984.35001f0a19803122.jpg&quot; alt=&quot;Image generated using Adobe Firefly AI&quot;&gt;
  &lt;figcaption&gt;Image generated using Adobe Firefly AI&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;I knew the broad shape of &lt;em&gt;1984&lt;&#x2F;em&gt; before I read it. Big Brother. Surveillance. Thought Police. All that. What I was not ready for was how suffocating the book feels page by page.&lt;&#x2F;p&gt;
&lt;p&gt;Orwell does not rely on giant twists or clever worldbuilding tricks. He just keeps pressing on the same sore spot. The telescreen is always there. The slogans are always there. The Party is always there, reaching right into memory and language and private thought. It wears you down while you read.&lt;&#x2F;p&gt;
&lt;p&gt;That is the part that hit me hardest. The regime does not only want obedience. It wants to wreck your grip on what is real. It wants you to doubt your own memory before anyone else even has to argue with you. That feels more disturbing than the surveillance itself.&lt;&#x2F;p&gt;
&lt;p&gt;Winston works because he is small and shaky and ordinary. He is not built like a movie rebel. He is a lonely man trying to protect a corner of his mind. Sometimes that corner is a memory. Sometimes it is desire. Sometimes it is just the urge to say that two plus two still matters.&lt;&#x2F;p&gt;
&lt;p&gt;There is no fake heroism in this book. Orwell is too ruthless for that. He keeps asking what power can do when it does not stop at laws or prisons and goes straight for the self. Not the body first. The self.&lt;&#x2F;p&gt;
&lt;p&gt;I finished &lt;em&gt;1984&lt;&#x2F;em&gt; feeling tired in the best way. It is brutal, but it earns that brutality. A lot of books warn you about tyranny. This one makes tyranny feel intimate.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;If you have thoughts on the book, ping me on Twitter &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Idiot by Fyodor Dostoevsky</title>
          <pubDate>Mon, 01 Jan 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/reading/the-idiot-fyodor-dostoevsky/</link>
          <guid>https://aaqa.dev/reading/the-idiot-fyodor-dostoevsky/</guid>
          <description xml:base="https://aaqa.dev/reading/the-idiot-fyodor-dostoevsky/">
&lt;figure&gt;
  &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;aaqa.dev&amp;#x2F;processed_images&amp;#x2F;the_idiot.50d7c3f86080377d.jpg&quot; alt=&quot;Image generated using Adobe Firefly AI&quot;&gt;
  &lt;figcaption&gt;Image generated using Adobe Firefly AI&lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;&lt;em&gt;The Idiot&lt;&#x2F;em&gt; is not a smooth read. It is crowded, restless, dramatic, and at times almost too much. That is also why I liked it.&lt;&#x2F;p&gt;
&lt;p&gt;Prince Myshkin is the reason the whole thing works. He is kind in a way that feels dangerous to everyone around him. Not flashy. Not saintly. Just open, honest, and weirdly free of the usual games people play. That makes him hard to place. Some people see innocence. Some see weakness. Some want to crush him for it.&lt;&#x2F;p&gt;
&lt;p&gt;What makes the book interesting is that goodness does not solve anything here. If anything, it makes the mess easier to see. Myshkin walks into rooms full of vanity, wounded pride, jealousy, self-pity, and desire, and all of it starts showing its face faster.&lt;&#x2F;p&gt;
&lt;p&gt;Nastasya Filippovna is impossible to ignore. So is Rogozhin. Every time either of them shows up, the temperature changes. You can feel trouble coming even in the quiet scenes. That tension carries the book through its longer stretches.&lt;&#x2F;p&gt;
&lt;p&gt;Dostoevsky is great at letting people embarrass themselves on the page. They talk too much. They misread each other. They act out. They want love, status, forgiveness, revenge, sometimes all at once. Nobody stays simple for long.&lt;&#x2F;p&gt;
&lt;p&gt;I did not come away from &lt;em&gt;The Idiot&lt;&#x2F;em&gt; with a clean moral. I came away thinking about how badly people want tenderness and how often they wreck it the second it gets close. That felt true. Painfully true.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;If you have thoughts on the book, ping me on Twitter &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Firecracker Dev Machine Setup (GCP)</title>
          <pubDate>Thu, 26 Jan 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/firecracker-dev-machine-setup/</link>
          <guid>https://aaqa.dev/notes/firecracker-dev-machine-setup/</guid>
          <description xml:base="https://aaqa.dev/notes/firecracker-dev-machine-setup/">&lt;p&gt;VM on Google Compute Engine (GCE) supports nested virtualisation, unlike AWS, and allows to run KVM.
We can create a VM on GCE to run and test Firecracker microVM.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;here-are-the-steps&quot;&gt;Here are the steps&lt;&#x2F;h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Setup GCP Project and Zone&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_PROJECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_REGION&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_ZONE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; set&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; project&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_PROJECT&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; set&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compute&#x2F;region&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_REGION&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; set&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compute&#x2F;zone&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_ZONE&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Create a VM image (Machine Image) able to run KVM&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_VDISK&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_IMAGE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compute&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; disks&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_VDISK&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-image-project&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ubuntu-os-cloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-image-family&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ubuntu-2204-lts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compute&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; images&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_IMAGE&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-source-disk&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_VDISK&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-source-disk-zone&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_ZONE&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-licenses&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;www.googleapis.com&#x2F;compute&#x2F;v1&#x2F;projects&#x2F;vm-options&#x2F;global&#x2F;licenses&#x2F;enable-vmx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Create the VM&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_VM&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compute&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; instances&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; create&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_VM&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-zone&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_ZONE&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-image&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_IMAGE&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Connect to the VM via SSH.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;gcloud&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compute&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ssh&lt;&#x2F;span&gt;&lt;span&gt; $&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;FC_VM&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Verify that VMX is enabled, enable KVM&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;cw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; vmx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;proc&#x2F;cpuinfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; setfacl&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u:&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;USER&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:rw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;dev&#x2F;kvm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;dev&#x2F;kvm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ]&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -w&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;dev&#x2F;kvm &lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;OK&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;FAIL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;OK&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</description>
      </item>
      <item>
          <title>Linux Container Networking from Scratch</title>
          <pubDate>Thu, 26 Jan 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/linux-container-networking/</link>
          <guid>https://aaqa.dev/notes/linux-container-networking/</guid>
          <description xml:base="https://aaqa.dev/notes/linux-container-networking/">&lt;p&gt;In this article, we will be looking into setting up networking on a linux box from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;We will be creating a fresh new VM using Lima on macOS.
You can create a new VM using VirtualBox, Vagrant, or even create a VM on OCI for free.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;isolation-based-on-network-namespace&quot;&gt;Isolation based on Network Namespace&lt;&#x2F;h2&gt;
&lt;p&gt;The common thing that constitutes a network stack includes the:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Network Devices&lt;&#x2F;li&gt;
&lt;li&gt;Routing Rules&lt;&#x2F;li&gt;
&lt;li&gt;Netfilter Hooks&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We can create a non-comprehensive &lt;code&gt;inspect-net-stack&lt;&#x2F;code&gt; script.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;env bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;gt; Network devices&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; link&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\n&amp;gt; Route table&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; route&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;\n&amp;gt; Iptables rules&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;iptables&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-list-rules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After the execution of the inspect script on my machine produces the following input:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;inspect-net-stack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Network devices&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; lo:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;LOOPBACK,UP,LOWER_U&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mtu&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 65536&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; qdisc&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; noqueue&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; UNKNOWN&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; DEFAULT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; group&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; default&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; qlen&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    link&#x2F;loopback&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 00:00:00:00:00:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 00:00:00:00:00:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;2:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; eth0:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;BROADCAST,MULTICAST,UP,LOWER_U&lt;&#x2F;span&gt;&lt;span&gt;P&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mtu&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1500&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; qdisc&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fq_codel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; UP&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; DEFAULT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; group&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; default&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; qlen&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    link&#x2F;ether&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 52:55:55:a3:ad:92&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ff:ff:ff:ff:ff:ff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    altname&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enp0s1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Route table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;default&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; via&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 192.168.5.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; proto&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dhcp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 192.168.5.15&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; metric&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;192.168.5.0&#x2F;24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dev&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; proto&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kernel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; scope&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; link&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 192.168.5.15&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; metric&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Iptables rules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; INPUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; OUTPUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We want to make sure that each of the containers we are going to create soon will get a separate network stack.&lt;&#x2F;p&gt;
&lt;p&gt;Linux namespaces used for container isolation are called &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;man7.org&#x2F;linux&#x2F;man-pages&#x2F;man8&#x2F;ip-netns.8.html&quot;&gt;network namespaces&lt;&#x2F;a&gt;. We won&#x27;t be creating the fully isolated container, rather restrict the scope to only the network stack. One of the ways to create a network stack is by using the &lt;code&gt;ip&lt;&#x2F;code&gt; tool, part of &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Iproute2&quot;&gt;&lt;code&gt;iproute2&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; netns&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; netns0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; netns&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;netns0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We have a new network namespace but to start using the network namespace, We can use a command called &lt;code&gt;nsenter&lt;&#x2F;code&gt;. It enters one or more of the specified namespaces and then executes the given program:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This is create a new bash process under netns0 namespace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; nsenter&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-net=&#x2F;var&#x2F;run&#x2F;netns&#x2F;netns0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;inspect-net-stack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Network devices&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; lo:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;LOOPBAC&lt;&#x2F;span&gt;&lt;span&gt;K&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mtu&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 65536&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; qdisc&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; noop&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; state&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; DOWN&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; DEFAULT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; group&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; default&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; qlen&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    link&#x2F;loopback&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 00:00:00:00:00:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; brd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 00:00:00:00:00:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Route table&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; Iptables rules&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; INPUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; FORWARD&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; OUTPUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ACCEPT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see from the above output, the &lt;code&gt;bash&lt;&#x2F;code&gt; process running inside the &lt;code&gt;netns0&lt;&#x2F;code&gt; namespace sees a different network stack. There are no routing rules and no custom iptables chain. Only one loopback device (&lt;code&gt;lo&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                        Network&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Namespace&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;┌─────────────────────────────────────────────────────────────────────┐&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                                                     │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                          Root&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Namespace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                                                     │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; lo0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    ┌────────────────────────────────────────┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ┌─┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    lo0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             Container&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Namespace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    ┌─┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;              netns0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;             │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    ┌────────────┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                 │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  ┌───────────┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; routes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;           │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │routes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    └────────────┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  └───────────┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; └─┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    └─┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                 │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ┌─┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    ┌────────────┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         ┌───────────┐&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;           │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; iptables&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         │iptables&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         └───────────┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    └────────────┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; └─┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                    │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                        │&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; eth0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                   └────────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                                                     │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;│&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;                                                                     │&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;└─────────────────────────────────────────────────────────────────────┘&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Beware&lt;&#x2F;em&gt;: The &lt;code&gt;nsenter&lt;&#x2F;code&gt; command from above started a nested bash session in the netns0 network namespace. Don&#x27;t forget to exit from it.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;In the upcoming posts, I will discuss connecting the host with this namespace. Interconnecting various network switches, Just like patching the physical switch with a LAN cable.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Git exclude files from working copy</title>
          <pubDate>Fri, 29 Jul 2022 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/git-exclude-files/</link>
          <guid>https://aaqa.dev/notes/git-exclude-files/</guid>
          <description xml:base="https://aaqa.dev/notes/git-exclude-files/">&lt;h2 id=&quot;how-to-ignore-new-files&quot;&gt;How to ignore new files&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;globally&quot;&gt;Globally&lt;&#x2F;h3&gt;
&lt;p&gt;Add the path(s) to your file(s) which you would like to ignore to your &lt;code&gt;.gitignore&lt;&#x2F;code&gt; file (and commit them). These file entries will also apply to others checking out the repository.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;locally&quot;&gt;Locally&lt;&#x2F;h3&gt;
&lt;p&gt;Add the path(s) to your file(s) which you would like to ignore to your &lt;code&gt;.git&#x2F;info&#x2F;exclude&lt;&#x2F;code&gt; file. These file entries will only apply to your local working copy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-ignore-changed-files-temporarily&quot;&gt;How to ignore changed files (temporarily)&lt;&#x2F;h2&gt;
&lt;p&gt;In order to ignore changed files to being listed as modified, you can use the following git command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; update-index&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-assume-unchanged&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;file-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;1&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;file-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;2&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;file-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To revert that ignorance use the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; update-index&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-no-assume-unchanged&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;file-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;1&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;file-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;2&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;file-&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;3&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note: If you find errors, typos or would like to add new tips, feel free to
reach out to me on twitter. I&#x27;m &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;. Thank
you for reading ! And if you find this useful, share it with your friends and
coworkers !&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Open markdown links in a new tab</title>
          <pubDate>Fri, 05 Jun 2020 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/hugo-open-markdown-new-tab/</link>
          <guid>https://aaqa.dev/notes/hugo-open-markdown-new-tab/</guid>
          <description xml:base="https://aaqa.dev/notes/hugo-open-markdown-new-tab/">&lt;p&gt;I created a static website &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;linkbin.aaqa.dev&#x2F;&quot;&gt;linkbin&lt;&#x2F;a&gt;, Where I could save links in a markdown file that can be viewed later.
It is serving its purpose and because it uses &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;hugo&lt;&#x2F;a&gt;, I don&#x27;t have to think about VPS cost.&lt;&#x2F;p&gt;
&lt;p&gt;Recently, I ran into an issue where my website serves links but when you click on it, It will open the link in the same tab. Ugggh! I don&#x27;t want to close my website just to open a link. Ideally, it should open the link in a new tab.&lt;&#x2F;p&gt;
&lt;p&gt;How can we do it? It would be easy Eh?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-generic-way&quot;&gt;The generic way&lt;&#x2F;h2&gt;
&lt;p&gt;Since markdown is eventually rendered as HTML, The most naive way I found was to write HTML in markdown&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;http:&#x2F;&#x2F;example.com&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; target&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;_blank&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;example&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No way, I am going to rewrite all my links into HTML. It adds cost later on as well. I will have to add HTML tags to write the link instead of this syntax:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-other z-link&quot;&gt;link&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;example.com&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-specialized-way&quot;&gt;The specialized way&lt;&#x2F;h2&gt;
&lt;p&gt;This could vary depending upon the markdown parser you are using.
If you&#x27;re using Jekyll, like this website, then you can use the following syntax to open links in a new tab.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-other z-link&quot;&gt;link&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;url&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;{:target=&amp;quot;_blank&amp;quot;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But, I am not using Jekyll for &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;linkbin.aaqa.dev&quot;&gt;linkbin&lt;&#x2F;a&gt;. It uses a fairly newer version of &lt;a href=&quot;httpsP:&#x2F;&#x2F;gohugo.io&quot;&gt;Hugo&lt;&#x2F;a&gt;. Hugo ,&lt;code&gt;v0.62.0 or later&lt;&#x2F;code&gt;, uses &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yuin&#x2F;goldmark&quot;&gt;Goldmark&lt;&#x2F;a&gt; parser and supports &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;templates&#x2F;render-hooks&#x2F;&quot;&gt;Markdown render hooks&lt;&#x2F;a&gt;. Markdown Render Hooks offer you several ways to extend the default markdown behavior, e.g. resizing uploaded images, opening links in new tabs, or creating mermaid diagrams from code. You can do this by creating templates in the &lt;code&gt;layouts&#x2F;_default&#x2F;_markup&lt;&#x2F;code&gt; directory with base names &lt;code&gt;render-link&lt;&#x2F;code&gt; or &lt;code&gt;render-image&lt;&#x2F;code&gt; or &lt;code&gt;render-codeblock&lt;&#x2F;code&gt;. Your directory layout may look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;layouts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;└──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; _default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    └──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; _markup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        ├──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; render-image.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        ├──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; render-image.rss.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        ├──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; render-link.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        ├──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; render-codeblock.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        └──&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; render-codeblock-bash.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;render-hook-to-open-link-in-a-new-tab&quot;&gt;Render hook to open link in a new tab&lt;&#x2F;h3&gt;
&lt;p&gt;Add the following HTML template file (or render hook) at &lt;code&gt;layouts&#x2F;_default&#x2F;_markup&#x2F;render-link.html&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; href&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ .Destination | safeURL }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;{{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; with&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; .Title}}&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; title&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{{ . }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;{{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; }}{{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; strings.HasPrefix&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; .Destination&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal&quot;&gt; &amp;quot;http&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; }}&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; target&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;_blank&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; rel&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;noopener&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt;{{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity&quot;&gt; }}&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{ .Text | safeHTML }}&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;a&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You&#x27;ll find that the links now open in a new tab!
For internal blog links (which you would want to open in the same tab), you can use the relative link of the post, e.g. for an &lt;code&gt;other-post.md&lt;&#x2F;code&gt; file within the &lt;code&gt;posts&lt;&#x2F;code&gt; directory, you could use&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-other z-link&quot;&gt;Other post&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;posts&#x2F;other-post&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;If I’ve missed something or made a horrible mistake if you have any questions regarding this article then feel free to ping me on Twitter. I’m
&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Recipe for a Great RESTful API</title>
          <pubDate>Sun, 30 Dec 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/recipe-of-great-rest-api/</link>
          <guid>https://aaqa.dev/notes/recipe-of-great-rest-api/</guid>
          <description xml:base="https://aaqa.dev/notes/recipe-of-great-rest-api/">&lt;p&gt;I personally love writing APIs. It&#x27;s my favourite thing about backend
development. As developers, we interact with APIs all the time: to process
payments with Stripe, handle geolocation with Google Maps, retrieve tweets,
etc.&lt;&#x2F;p&gt;
&lt;p&gt;So what exactly makes a RESTful API great? What can you do to ensure that it&#x27;s
easy for other developers to use? Let&#x27;s dive right in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;responses&quot;&gt;Responses&lt;&#x2F;h2&gt;
&lt;p&gt;In your responses, you should separate the metadata from the body and put them in their own objects.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example: GET &#x2F;api&#x2F;user&#x2F;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;success&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;code&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 200&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;request_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;someid&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; etc ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Aaqa&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;location&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Delhi&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;job&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Software Developer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When creating a new resource, always return a &lt;code&gt;201 created&lt;&#x2F;code&gt; instead of a &lt;code&gt;200 OK&lt;&#x2F;code&gt;. It&#x27;s a common mistake developers make.
Another best practice is to return a url to the newly created resource in the location header of your response.
You can also choose to send a serialised version of the resource in the response body. (I personally like to do that).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example: POST &#x2F;api&#x2F;users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Response Headers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Content-Type: application&#x2F;json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Location: https:&#x2F;&#x2F;yoursite.com&#x2F;api&#x2F;users&#x2F;2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;success&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;code&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 201&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;request_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;some_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;User successfully added&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Harry_Potter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;location&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;London&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;job&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Auror&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;href&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;yoursite.com&#x2F;api&#x2F;users&#x2F;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;errors&quot;&gt;Errors&lt;&#x2F;h3&gt;
&lt;p&gt;Properly dealing with errors is crucial to provide the best experience possible
to your users.  Just like with normal responses, always include the status code in the meta part.&lt;&#x2F;p&gt;
&lt;p&gt;You should also provide a nice descriptive message detailing the cause of the
error as well as a potential solution to fix it.&lt;&#x2F;p&gt;
&lt;p&gt;Doing this will help the consumers of your API to gracefully handle these errors on the client side. They will thank you for it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Example GET &#x2F;api&#x2F;secretendpoint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 401&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;        &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;request_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;weoifwe&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;       &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;message&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Unauthorized. Please login or create an account&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;status-codes&quot;&gt;Status codes&lt;&#x2F;h2&gt;
&lt;p&gt;This part is subject to many passionate debates, apparently it&#x27;s a very touchy
topic.&lt;&#x2F;p&gt;
&lt;p&gt;Below I will list the most common status codes, what they mean and how I use
them.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;200 - OK - Request went well, errthang&#x27;s fine.&lt;&#x2F;li&gt;
&lt;li&gt;201 - Resource created - The resource was successfully saved to the database.&lt;&#x2F;li&gt;
&lt;li&gt;204 - No Content - There used to be a resource at this endpoint but not
anymore (Used for &lt;code&gt;DELETE&lt;&#x2F;code&gt; requests)&lt;&#x2F;li&gt;
&lt;li&gt;400 - Bad request - The request was badly formatted. (ex: Invalid JSON)&lt;&#x2F;li&gt;
&lt;li&gt;401 - Unauthorized - Authentication failed due to invalid credentials.&lt;&#x2F;li&gt;
&lt;li&gt;403 - Forbidden - Authentication passed but the user does not have permission to access the resource&lt;&#x2F;li&gt;
&lt;li&gt;404 - Not Found - Well, &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=yX2vWL2b2Rc&quot;&gt;you know what it is&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;405 - Method Not Allowed - The HTTP verb used to interact with the resource is not allowed. (eg: User tried to POST to a GET only endpoint)&lt;&#x2F;li&gt;
&lt;li&gt;409 - Conflict - The data passed in the payload conflicts with the resource in
the server. (I return this status code in cases where a user creates&#x2F;updates a
resource with a unique field constraint attached to it such as a username or
email)&lt;&#x2F;li&gt;
&lt;li&gt;422 - Unprocessable Entity - Again, another controversial one. I return a 422
when the user sends an incomplete payload thereby violating the NOT NULL constraint attached to those fields.&lt;&#x2F;li&gt;
&lt;li&gt;429 - Too many requests - You made too many requests.&lt;&#x2F;li&gt;
&lt;li&gt;50x - Server Related Errors - Something went wrong server side.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;caching&quot;&gt;Caching&lt;&#x2F;h3&gt;
&lt;p&gt;Caching is great and is a must when deploying an API. It helps a huge
amount with performace by reducing server load as you are not required to
perform the same action multiple times. You could choose to do it manually or use a reverse proxy like nginx or even something like varnish to handle that for you.&lt;&#x2F;p&gt;
&lt;p&gt;Caching will return a &lt;code&gt;304 Not Modified&lt;&#x2F;code&gt; if the resource hasn&#x27;t changed. The great thing about this is that it does not affect your rate limiting, so there&#x27;s
literally no excuse not to implement it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;rate-limiting&quot;&gt;Rate Limiting&lt;&#x2F;h3&gt;
&lt;p&gt;For security and performance reasons you want limit the amount of requests made
against your API.
You must return the maximum and remaining number of request allowed for a given user in a particular time window (which you are free to determine).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cors&quot;&gt;CORS&lt;&#x2F;h3&gt;
&lt;p&gt;You want to enable CORS to allow requests from browsers using AJAX. This can
be done by setting the following headers:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Access-Control-Allow-Origin:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; this means allow all domains to interact with the API&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Access-Control-Allow-Headers:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; All the headers you want to accept should be listed here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;a-few-tips&quot;&gt;A few tips&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Return urls to resources and total count when GETting collections&lt;&#x2F;li&gt;
&lt;li&gt;Map your endpoints to collections and resources&lt;&#x2F;li&gt;
&lt;li&gt;Always use plural nouns (Ex: &#x2F;api&#x2F;users not &#x2F;api&#x2F;user)&lt;&#x2F;li&gt;
&lt;li&gt;Actions on resources must be described with HTTP verbs&lt;&#x2F;li&gt;
&lt;li&gt;for partial updates of resources use PATCH instead of PUT&lt;&#x2F;li&gt;
&lt;li&gt;for versioning, use dates instead of numbers in the URL (foursquare does exactly that)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;If you have any comment, suggestions or remarks of any sort, you can ping
me on twitter &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt; !&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>How to Set Up the Scrapy Splash Plugin</title>
          <pubDate>Sat, 01 Sep 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/scrapy-splash-setup/</link>
          <guid>https://aaqa.dev/notes/scrapy-splash-setup/</guid>
          <description xml:base="https://aaqa.dev/notes/scrapy-splash-setup/">&lt;p&gt;Scrapy is great for scraping static web pages with Python, but when it comes to
dynamic pages it can only do so much. That&#x27;s where &lt;code&gt;Selenium&lt;&#x2F;code&gt; usually comes
in, but as good as Selenium is, Scrapy still beats it in terms of speed.&lt;&#x2F;p&gt;
&lt;p&gt;The web these days is full of dynamic JS-based pages and AJAX. For exactly that
scenario, the folks over at &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scrapy-plugins&quot;&gt;scrapy-plugins&lt;&#x2F;a&gt; created &lt;code&gt;scrapy-splash&lt;&#x2F;code&gt;.
Scrapy-Splash is a plugin that connects Scrapy with Splash (a lightweight,
scriptable browser as a service with an HTTP API). In a nutshell, Splash takes
the response received from the server and renders it. Then it returns a
&lt;code&gt;render.html&lt;&#x2F;code&gt; response which is static and can be scraped easily.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;0-setting-up-the-machine&quot;&gt;0 - Setting up the machine&lt;&#x2F;h2&gt;
&lt;p&gt;A. Before we begin you need to install &lt;code&gt;Docker&lt;&#x2F;code&gt; first, You can follow the &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;install&#x2F;&quot;&gt;official instruction&lt;&#x2F;a&gt; as per your Operating System.&lt;&#x2F;p&gt;
&lt;p&gt;B. After installing Docker, navigate to your project folder, activate
&lt;code&gt;virtualenv&lt;&#x2F;code&gt; and install the scrapy-splash plugin&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pip3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; scrapy-splash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;C. Pull the Splash Docker Image and run it&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pull&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; scrapinghub&#x2F;splash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;docker&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 8050:8050&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; scrapinghub&#x2F;splash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;1-configuration&quot;&gt;1 - Configuration&lt;&#x2F;h2&gt;
&lt;p&gt;A. Add the Splash server address to &lt;code&gt;settings.py&lt;&#x2F;code&gt; of your Scrapy project like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;SPLASH_URL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;http:&#x2F;&#x2F;localhost:8050&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you are running docker on your local machine then you can simply use &lt;code&gt;http:&#x2F;&#x2F;localhost:&amp;lt;port&amp;gt;&lt;&#x2F;code&gt; , but if you are running it on a remote machine you need to specify it&#x27;s I.P. Address like this &lt;code&gt;http:&#x2F;&#x2F;192.168.59.103:&amp;lt;port&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;B. Enable the Splash middleware by adding it to &lt;code&gt;DOWNLOADER_MIDDLEWARES&lt;&#x2F;code&gt; in your &lt;code&gt;settings.py&lt;&#x2F;code&gt; file and changing HttpCompressionMiddleware priority:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;DOWNLOADER_MIDDLEWARES&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;scrapy_splash.SplashCookiesMiddleware&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 723&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;scrapy_splash.SplashMiddleware&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 725&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 810&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;C. Enable SplashDeduplicateArgsMiddleware by adding it to SPIDER_MIDDLEWARES in your settings.py:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;SPIDER_MIDDLEWARES&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;scrapy_splash.SplashDeduplicateArgsMiddleware&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;D. Set a custom DUPEFILTER_CLASS:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;DUPEFILTER_CLASS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;scrapy_splash.SplashAwareDupeFilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;2-scraping-with-splash&quot;&gt;2 - Scraping with Splash&lt;&#x2F;h2&gt;
&lt;p&gt;Before you use &lt;code&gt;scrapy-splash&lt;&#x2F;code&gt; you need to import it in your spider.
You can do that by adding this line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; scrapy_splash&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; SplashRequest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;from now on insted of using &lt;code&gt;scrapy.Request&lt;&#x2F;code&gt; you can simply use &lt;code&gt;SplashRequest&lt;&#x2F;code&gt; to get response from &lt;code&gt;Splash&lt;&#x2F;code&gt; insted of directly from ther server.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-using-scrapy-splash-in-shell&quot;&gt;Bonus - Using Scrapy-Splash in Shell&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s all well and good but actual spider buiding does not happens in &lt;code&gt;vim&lt;&#x2F;code&gt; or &lt;code&gt;sublime&lt;&#x2F;code&gt;, it takes place in &lt;code&gt;shell&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;So how to use Splash in the shell?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Good Question.&lt;&#x2F;p&gt;
&lt;p&gt;Insted of invoking shell with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;scrapy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; shell&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fetch(http:&#x2F;&#x2F;domain.com&#x2F;page-with-javascript.html&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or with this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;scrapy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; http:&#x2F;&#x2F;domain.com&#x2F;page-with-javascript.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;You invoke shell with this&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;scrapy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; shell&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;http:&#x2F;&#x2F;localhost:8050&#x2F;render.html?url=http:&#x2F;&#x2F;domain.com&#x2F;page-with-javascript.html&amp;amp;timeout=10&amp;amp;wait=0.5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let me explain&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;localhost:port&lt;&#x2F;code&gt; is where your splash service is running&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;url&lt;&#x2F;code&gt; is url you want to crawl&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;render.html&lt;&#x2F;code&gt; is one of the possible http api endpoints, returns redered html page in this case&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;timeout&lt;&#x2F;code&gt; time in seconds for timeout&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;wait&lt;&#x2F;code&gt; time in seconds to wait for javascript to execute before reading&#x2F;saving the html.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If I’ve missed something, made a horrible mistake of if you have any questions regarding this article then feel free to ping me on Twitter. I’m
&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Build and Deploy a React App with Sass and Nginx</title>
          <pubDate>Sat, 02 Jun 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/build-deploy-react-app-with-nginx/</link>
          <guid>https://aaqa.dev/notes/build-deploy-react-app-with-nginx/</guid>
          <description xml:base="https://aaqa.dev/notes/build-deploy-react-app-with-nginx/">&lt;p&gt;A couple of days ago (at the time of writing), I started my newest side
project. It&#x27;s a portfolio showcasing my (very very very) amateur
photography. It&#x27;s written in React.js with Sass and I have to say it was
extremely enjoyable to work on. Unsurprisingly though, I ran into some issues
while deploying to production which, after a lot of head banging against every
possible flat surface I could find, I managed to sort out. So this post will be
about how to make React.js work with Sass in production and how to serve the
project using Nginx as a front-end web server.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll be using the official starter kit &#x2F; CLI tool provided by the Facebook
team called &lt;code&gt;create-react-app&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can install it by running the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; create-react-app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;adding-sass-to-a-react-project&quot;&gt;Adding Sass to a React project&lt;&#x2F;h2&gt;
&lt;p&gt;Including Sass in a React app can be done in two ways: You can either eject the
project and manually modify the webpack config files or you can follow the
procedure in the &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;facebookincubator&#x2F;create-react-app&#x2F;#getting-started&quot;&gt;official docs&lt;&#x2F;a&gt;. I&#x27;ve personally chosen to go with the first approach.
You can just follow the steps in this &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@Connorelsea&#x2F;using-sass-with-create-react-app-7125d6913760&quot;&gt;tutorial&lt;&#x2F;a&gt; to get up and running.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: If you went with the second approach, you can just skip the following and
directly jump to the next section&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Once you&#x27;ve done that, open the config&#x2F;webpack.config.prod.js file, locate the
&lt;code&gt;rules&lt;&#x2F;code&gt; section under &lt;code&gt;module.exports&lt;&#x2F;code&gt; and add the following snippet to it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    test&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp&quot;&gt;sass&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    use&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; ExtractTextPlugin&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;extract&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        fallback&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; require&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;style-loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        use&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;css-loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; require&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;resolve&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sass-loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    include&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; paths&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;appSrc&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This config will be executed when you call &lt;code&gt;npm run build&lt;&#x2F;code&gt;. If you don&#x27;t do
this, you&#x27;ll end up with an empty css file.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;important-note&quot;&gt;Important note&lt;&#x2F;h2&gt;
&lt;p&gt;Before building the project for the first time, we must first unregister the
service worker. Doing this will ensure that the static assets aren&#x27;t cached by
the client&#x27;s browsers. It&#x27;s important because if you skip this step, any
subsequent change &#x2F; build you&#x27;ll deploy won&#x27;t necessarily be reflected right away
client side. (I&#x27;m not knowledgable enough on service workers to provide details
on this behaviour, but it&#x27;s something to note. If you really need service
workers in your project, you might want to explore other solutions to avoid
asset caching).&lt;&#x2F;p&gt;
&lt;p&gt;Your index.js file should now look something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; unregister&lt;&#x2F;span&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;registerServiceWorker&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; App&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;App&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;ReactDOM&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;render&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;App&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; document&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;getElementById&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;root&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&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;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unregister&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;building-the-project&quot;&gt;Building the project&lt;&#x2F;h2&gt;
&lt;p&gt;This is the part where we actually build our project. By building I mean
compiling all React files and their related dependencies, transpiling them into
vanilla Javascript, compiling sass files into css, minifying them etc ...
To do this, we can simply run &lt;code&gt;npm run build&lt;&#x2F;code&gt; and voila ! You should have a
brand new &lt;code&gt;build&lt;&#x2F;code&gt; folder in your project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-our-deploy-script&quot;&gt;Creating our deploy script&lt;&#x2F;h2&gt;
&lt;p&gt;Your app is now compiled and ready to be served. Now is a good time to start
thinking about deployment strategies. In this basic scenario
(and quite frankly, most scenraios), you really just want to upload the build
folder to a remote server and have it accessible as a static site.&lt;&#x2F;p&gt;
&lt;p&gt;You can use ftp to transfer the files and it would be perfectly acceptable, but
it&#x27;s not the most flexible solution. The alternative is to use a CLI utility called
&lt;code&gt;rsync&lt;&#x2F;code&gt; (which is available on mac and linux, not sure about windows). With
rsync, you can synchronise files and folders within the same computer or across
machines you have ssh access to.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the command we would run to synchronise the build folder to a server
on the internet:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Asssuming we&amp;#39;re inside the project folder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;avP&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; username@remote_ip:&#x2F;destination&#x2F;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s break down this command:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;-a&lt;&#x2F;code&gt; means archive, which is a shortcut for multiple switches. It
recursively syncs all files and subfolders within &lt;code&gt;build&lt;&#x2F;code&gt; to the
destnation path, keeping the modification dates, permissions and other metadata
unchanged.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;-v&lt;&#x2F;code&gt; means verbose. It just outputs the steps to the screen so you can see
what happens in real time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;-P&lt;&#x2F;code&gt; stands for progress. This is particularly useful in this case because you
rely on a network connection to sync the files. Using this option will
display a progress bar for each file in the queue.&lt;&#x2F;p&gt;
&lt;p&gt;But you don&#x27;t want to keep doing all of that every time we want to push now do
you ?&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully, you can use create a bash script to automate this process a litte
bit. Here&#x27;s how mine looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Merging branch to master&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; master&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; merge&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; develop&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; push&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; origin&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; master&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Merge completed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Compiling project to build folder ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;npm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Build process done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Deploying files to server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;rsync&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;avP&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user@host:&#x2F;destination&#x2F;path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Deployment completed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Switching to develop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; develop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Done!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, let&#x27;s walk through that script section by section:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;I checkout to master, merge develop and push. This ensures that my master
branch is always up to date with the latest version of my working codebase.&lt;&#x2F;li&gt;
&lt;li&gt;I execute &lt;code&gt;npm run build&lt;&#x2F;code&gt; which, as previously explained, will create the
build directory with our compiled, ready to be deployed files.&lt;&#x2F;li&gt;
&lt;li&gt;I use rsync to copy over the contents of the build folder to the destination
path in the remote machine I administer. (notice the trailing slash after
build&#x2F;, this tells rsync to copy the contents of the folder and not the
folder itself).&lt;&#x2F;li&gt;
&lt;li&gt;I switch the current working branch back to develop so that I can start
developing without accidentally altering the state of &lt;code&gt;master&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Obviously this is very basic and in a more complex project, you&#x27;d have to run
unit tests and do other things your project requires.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, you need to give executable permissions to the file by running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; chmod&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; +x&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; deploy.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now all you have to do when you want to deploy your project to production is run&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;deploy.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;serving-our-site-with-nginx&quot;&gt;Serving our site with Nginx&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Note: this assumes your server is running ubuntu or any other debian based
distro&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ok, so if you&#x27;ve followed the steps correctly, you should have your project
files uploaded to your remote server. Now we need to use Nginx to make the site
accessible to the internet.&lt;&#x2F;p&gt;
&lt;p&gt;First, create a new config file inside &lt;code&gt;&#x2F;etc&#x2F;nginx&#x2F;sites-available&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;etc&#x2F;nginx&#x2F;sites-available&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;touch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mywebsiteconfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; File extension is not required in this case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next step is to edit the file using either vim or nano (sudo privileges may be
required).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;nginx&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;server&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    listen&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 80&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    server_&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt; mywebsite.com www.mywebsite.com&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    location&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; &#x2F; &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        root&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;path&#x2F;to&#x2F;your&#x2F;project&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        index&lt;&#x2F;span&gt;&lt;span&gt; index.html index.htm&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        default_type&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&#x2F;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    access_log&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;nginx&#x2F;mywebsite_access.log&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    error_&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;var&#x2F;log&#x2F;nginx&#x2F;mywebsite_errors.log&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you&#x27;re not familiar with Nginx, let me explain what you just copied.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;We created a server block to hold our configuration and keep it separate from
other configs we may add in the future (like https for example).&lt;&#x2F;li&gt;
&lt;li&gt;We declare the listen directive which tells nginx to listen on port 80.&lt;&#x2F;li&gt;
&lt;li&gt;We set the server_name to our domain name. This tells nginx to apply the
config settings to any incoming request from any of listed urls.&lt;&#x2F;li&gt;
&lt;li&gt;Finally, we specify the paths to both the access and error logs. It&#x27;s
optional but highly recommended, so that you know exactly where to look when
errors happen. This will save you a tonne of time when troubleshooting issues
in the future.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Close the file and exit nano or vim.&lt;&#x2F;p&gt;
&lt;p&gt;Nginx keeps its configuration files in two separate directories:
&lt;code&gt;&#x2F;etc&#x2F;nginx&#x2F;sites-available&lt;&#x2F;code&gt; and &lt;code&gt;&#x2F;etc&#x2F;nginx&#x2F;sites-enabled&lt;&#x2F;code&gt;. It will serve
any website whose configuration file is in the latter folder.&lt;&#x2F;p&gt;
&lt;p&gt;All you have to do now is create a symlink (think of it like a shortcut to an app
in a desktop GUI) to your config, and store it in &lt;code&gt;sites-enabled&lt;&#x2F;code&gt;.
That way, if you ever decide to shut down the site, you&#x27;ll simply need to
delete the symlink and you&#x27;re good.&lt;&#x2F;p&gt;
&lt;p&gt;Before creating the symlink, it&#x27;s good measure to check if the configuration
file has any errors in it. To check for errors just run the following command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; nginx&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It will scan all of your config files and check for errors (and return them to
you if there are any).&lt;&#x2F;p&gt;
&lt;p&gt;Now you can create the symlink by executing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ln&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;etc&#x2F;nginx&#x2F;sites-available&#x2F;mywebsite&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;etc&#x2F;nginx&#x2F;sites-enabled&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note: If you decide to use service workers with your project and you&#x27;re still
running into caching issues, you should know that Nginx can also be used as a
static assets server. I haven&#x27;t looked into this scenario yet. I might test that
approach in the future and detail the process in another post.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Lastly, reload nginx and your website should now be accessible via its URL
(provided you correctly setup the DNS settings with your domain name registrar)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; service&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; nginx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you read this article all the way through, thanks for sticking with me ! You
can send me questions, remarks, or comments on twitter, I&#x27;m &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt; on
twitter.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Ultimate PostgreSQL Cheat Sheet</title>
          <pubDate>Wed, 09 May 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/the-ultimate-postgresql-cheatsheet/</link>
          <guid>https://aaqa.dev/notes/the-ultimate-postgresql-cheatsheet/</guid>
          <description xml:base="https://aaqa.dev/notes/the-ultimate-postgresql-cheatsheet/">&lt;p&gt;So I&#x27;d been working with Django, Flask, and Express.js for a while, and my
database of choice for pretty much every project had, of course, always been
Postgres.
What makes these frameworks great (regardless of language) is the ability to use
an ORM (Object Relational Mapper) that sits between your code and the DB.
It does all the heavy lifting for you and takes care of executing SQL queries on
your behalf.&lt;&#x2F;p&gt;
&lt;p&gt;This is great, but I couldn&#x27;t stop thinking, &quot;what if I have to manually debug
something directly in Postgres?&quot; That was when reality slapped me in the face:
I barely knew SQL. So I thought it&#x27;d be fun to create a cheat sheet that both I
and you could keep around for those times when you absolutely need to set a
column to &lt;code&gt;UNIQUE&lt;&#x2F;code&gt; and you don&#x27;t know how.&lt;&#x2F;p&gt;
&lt;p&gt;Enjoy ! (and yeah I went all in with the pokemon references)&lt;&#x2F;p&gt;
&lt;h3 id=&quot;create-a-user-or-role&quot;&gt;Create a User (or Role)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; create a user without privileges&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ROLE&lt;&#x2F;span&gt;&lt;span&gt; aaqa;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; create a user with privileges&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ROLE&lt;&#x2F;span&gt;&lt;span&gt; aaqa &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;LOGIN&lt;&#x2F;span&gt;&lt;span&gt; CREATEDB CREATEROLE REPLICATION;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Add privileges to existing user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ROLE&lt;&#x2F;span&gt;&lt;span&gt; aaqa &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WITH&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; LOGIN&lt;&#x2F;span&gt;&lt;span&gt; CREATEROLE CREATEDB REPLICATION;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;make-a-user-superuser-bump-their-privileges&quot;&gt;Make a user superuser (bump their privileges)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ROLE&lt;&#x2F;span&gt;&lt;span&gt; aaqa &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WITH&lt;&#x2F;span&gt;&lt;span&gt; superuser;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;rename-an-existing-user&quot;&gt;Rename an existing user&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ROLE&lt;&#x2F;span&gt;&lt;span&gt; psyduck RENAME &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TO&lt;&#x2F;span&gt;&lt;span&gt; brock;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;create-a-db&quot;&gt;Create a DB&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pokemons&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;rename-a-db&quot;&gt;Rename a DB&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span&gt; pokemons RENAME &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TO&lt;&#x2F;span&gt;&lt;span&gt; charizard;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;create-a-table-in-a-db&quot;&gt;Create a table in a DB&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; trainers&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; PRIMARY KEY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pokemon_type &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    name&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; UNIQUE&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    gender &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; UNIQUE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;delete-a-db&quot;&gt;Delete a DB&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DROP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span&gt; pokemons;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;delete-a-user&quot;&gt;Delete a user&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; assuming there&amp;#39;s a pikachu role on the system &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DROP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ROLE&lt;&#x2F;span&gt;&lt;span&gt; pikachu;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;change-db-ownership&quot;&gt;Change DB ownership&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; DATABASE&lt;&#x2F;span&gt;&lt;span&gt; pokemons &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;OWNER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TO&lt;&#x2F;span&gt;&lt;span&gt; aaqa;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;rename-a-table&quot;&gt;Rename a table&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; trainers RENAME &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TO&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;change-column-type&quot;&gt;Change column type&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span&gt; COLUMN pokemon_type &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; TEXT&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; it makes zero&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;sense to want to change this column type to TEXT but YOLO &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;rename-a-column&quot;&gt;Rename a column&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span&gt; COLUMN &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt; RENAME &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TO&lt;&#x2F;span&gt;&lt;span&gt; trainer_name;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-column-to-a-table&quot;&gt;Add a column to a table&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ADD&lt;&#x2F;span&gt;&lt;span&gt; COLUMN bio &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;TEXT&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;ALTER TABLE &amp;lt;table_name&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;ADD COLUMN &amp;lt;column_name&amp;gt; &amp;lt;data_type&amp;gt; &amp;lt;constraints if any&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-column-with-a-unique-constraint&quot;&gt;Add a column with a UNIQUE constraint&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ADD&lt;&#x2F;span&gt;&lt;span&gt; COLUMN age &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; UNIQUE&lt;&#x2F;span&gt;&lt;span&gt;; &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; cause why not &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-column-with-a-not-null-constraint&quot;&gt;Add a column with a NOT NULL constraint&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ADD&lt;&#x2F;span&gt;&lt;span&gt; COLUMN main_pokemon &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;60&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;remove-not-null-constraint-from-a-column&quot;&gt;Remove NOT NULL CONSTRAINT from a column&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span&gt; COLUMN main_pokemon &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;DROP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-column-with-a-not-null-constraint-and-a-default-value&quot;&gt;Add a column with a NOT NULL constraint and a DEFAULT value&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; gym_trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ADD&lt;&#x2F;span&gt;&lt;span&gt; COLUMN city &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;80&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; DEFAULT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Indigo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;Plateau&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-column-with-a-check-constraint&quot;&gt;Add a column with a CHECK constraint&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; trainers&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; PRIMARY KEY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    trainer_name &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;50&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        method 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        Add the check yolo style&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CHECK&lt;&#x2F;span&gt;&lt;span&gt; (age &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 18&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        method 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        Add a named constraint for better error handling&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt; legal_age &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;CHECK&lt;&#x2F;span&gt;&lt;span&gt; (age &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 18&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;NOT NULL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        method 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        Add the constraint at the end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        for more clarity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    age &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt; legal_age &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;CHECK&lt;&#x2F;span&gt;&lt;span&gt; (age &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 18&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;NOT NULL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;add-a-constraint-to-an-existing-column&quot;&gt;Add a CONSTRAINT to an existing column&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ADD&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt; unique_name &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;UNIQUE&lt;&#x2F;span&gt;&lt;span&gt; (trainer_name);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;remove-a-named-constraint-from-a-table&quot;&gt;Remove a named CONSTRAINT from a table&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;DROP&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt; unique_name;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;insert-a-row-into-a-table&quot;&gt;Insert a row into a table&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span&gt; trainers &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;brock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; or &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span&gt; trainers (age, trainer_name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;VALUES&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;brock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    Note that in the second case we don&amp;#39;t have pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    the id. Postgres will automatically generate and autoincrement&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    it for us. To omit the id column we must use named inserts otherwise an&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    error is raised.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;insert-multiple-rows-into-a-table&quot;&gt;Insert multiple rows into a table&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;INSERT INTO&lt;&#x2F;span&gt;&lt;span&gt; trainers (age, trainer_name) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;VALUES&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;19&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;misty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;22&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;chen&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;clear-a-table-without-deleting-it&quot;&gt;Clear a table (without deleting it)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;TRUNCATE&lt;&#x2F;span&gt;&lt;span&gt; trainers;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;set-the-primary-key-type-to-a-serial-an-auto-incrementing-integer&quot;&gt;Set the primary key type to a serial (An auto incrementing integer)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Considering this table structure &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pokemon_list&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; PRIMARY KEY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ... &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    1.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    Create a sequence for the auto generating prinary key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    It follows the tablename_columnname_seq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; SEQUENCE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pokemon_list_id_seq&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 2. Set the id column to not null &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span&gt; COLUMN id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 3. Set the default value to the next value in the sequence&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span&gt; COLUMN pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; DEFAULT&lt;&#x2F;span&gt;&lt;span&gt; nextval(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pokemon_list_id_seq&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 4. Link the sequence to the correct table and column &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; SEQUENCE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list_id_seq OWNED &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;BY&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; pokemon_list&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;import-data-from-a-file&quot;&gt;Import data from a file&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    Must use absolute path and the user must have appropriate permissions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    Defaults to importing using TAB as the default parameter.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    We&amp;#39;ll use a csv file as an example&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;path&#x2F;to&#x2F;yourfile.csv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; DELIMITER &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    This only works if a pk is specified for each row&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    The (my) prefered way to do it is the following&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;path&#x2F;to&#x2F;yourfile.csv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; DELIMITER &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; It&amp;#39;s much more flexible because you control what data you actually import&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;export-a-table-to-a-file&quot;&gt;Export a table to a file&lt;&#x2F;h3&gt;
&lt;p&gt;To be able to export a table to a file, we need to ensure that postgres has
write permissions to the file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; chmod&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 777&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;path&#x2F;to&#x2F;directory&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This is just an example, edit this as needed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now safely copy the table to the file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;TO&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;path&#x2F;to&#x2F;file.csv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; DELIMITER &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-columns-by-using-aliases&quot;&gt;Select columns by using aliases&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span&gt; pokemon_name, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-elements-based-on-a-criteria&quot;&gt;Select elements based on a criteria&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-elements-based-on-string-comparison&quot;&gt;Select elements based on string comparison&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; LIKE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;%water%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-all-results-and-order-them-by-id-in-reverse&quot;&gt;Select all results and order them by id in reverse&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-all-results-and-order-them-by-a-column-name&quot;&gt;Select all results and order them by a column name&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; level&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; If the column you&amp;#39;re ordering by is not of type INT then the ordering will be&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;done alphabetically &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-distinct-column-from-table&quot;&gt;Select DISTINCT column from table&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT DISTINCT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;limit-the-results-from-a-select-query&quot;&gt;Limit the results from a SELECT query&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;select-the-last-3-items&quot;&gt;Select the last 3 items&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;DESC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;LIMIT&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;create-two-tables-with-a-foreign-key-relationship&quot;&gt;Create two tables with a foreign key relationship&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;SERIAL&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; PRIMARY KEY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    type_name &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;120&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pokemon_list&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    id &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;serial&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; PRIMARY KEY&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pokemon_name &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;CHAR&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;120&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pokemon_level &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pokemon_type &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;INT&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; REFERENCES&lt;&#x2F;span&gt;&lt;span&gt; pokemon_types(id) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;NOT NULL&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage&quot;&gt;    CONSTRAINT&lt;&#x2F;span&gt;&lt;span&gt; pokemon_level_not_zero &lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;CHECK&lt;&#x2F;span&gt;&lt;span&gt; (pokemon_level &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;perform-joins-based-on-a-criteria&quot;&gt;Perform Joins based on a criteria&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; pokemon_types&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type_id  &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type_id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Will return the name, level and type name for all water pokemons &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;perform-joins&quot;&gt;Perform joins&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;level&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; pokemon_types&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type_id  &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;create-a-view-based-on-a-join&quot;&gt;Create a VIEW based on a JOIN&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;CREATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; VIEW&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pokemonswithtypes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;level&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; pokemon_types&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type_id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; To see the data &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemonswithtypes;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;update-the-view-change-the-query&quot;&gt;Update the VIEW (Change the query)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; type&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; pokemon_types&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; pokemon_types&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_type &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; only show the name and type for water pokemons &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;delete-the-view&quot;&gt;Delete the VIEW&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DROP&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; VIEW&lt;&#x2F;span&gt;&lt;span&gt; pokemonswithtypes;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;use-aggregate-functions-min-max-sum-count-avg&quot;&gt;Use aggregate functions (MIN, MAX, SUM, COUNT, AVG)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; MAX &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; MAX&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pokemon_level)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; MIN &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; MIN&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pokemon_level)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; AVG &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; AVG&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pokemon_level)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ROUND &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; ROUND&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;AVG&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pokemon_level))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; COUNT &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; COUNT&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; SUM &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; SUM&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;pokemon_level)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;use-boolean-aggregate-functions&quot;&gt;Use boolean aggregate functions&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Add a column is_legendary of type boolean to table pokemon_list &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ADD&lt;&#x2F;span&gt;&lt;span&gt; COLUMN is_legendary BOOL &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;NOT NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; DEFAULT&lt;&#x2F;span&gt;&lt;span&gt; TRUE;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;  BOOL_AND&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    returns a result if **ALL** records have that column set to true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; BOOL_AND(is_legendary) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    BOOL_OR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;    returns a result if one or more records have that column set to true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; BOOL_OR(is_legendary) &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;update-a-table-and-change-all-column-values&quot;&gt;Update a table and change all column values&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span&gt; is_legendary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; FALSE;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;update-a-table-and-change-value-based-on-a-criteria&quot;&gt;Update a table and change value based on a criteria&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;UPDATE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;SET&lt;&#x2F;span&gt;&lt;span&gt; is_legendary &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; TRUE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;delete-row-with-specific-id&quot;&gt;Delete row with specific id&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DELETE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;delete-rows-withing-a-range-of-ids&quot;&gt;Delete rows withing a range of ids&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DELETE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; id &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;BETWEEN&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; AND&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;delete-all-rows&quot;&gt;Delete all rows&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DELETE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; pokemon_list;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note: The difference between DELETE and DROP or TRUNCATE is that the former can
be undone (rolled back) the latter can&#x27;t&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;alter-a-table-to-drop-a-constraint-if-it-exist&quot;&gt;Alter a table to drop a CONSTRAINT if it exist&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;ALTER&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; TABLE&lt;&#x2F;span&gt;&lt;span&gt; pokemon_types&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;DROP&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; CONSTRAINT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; IF&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; EXISTS&lt;&#x2F;span&gt;&lt;span&gt; unique_type_name;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;comments&quot;&gt;Comments&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;COMMENT ON TABLE &lt;&#x2F;span&gt;&lt;span&gt;pokemon_types &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;is&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pokemon with types&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; To display the comment, in psql simply run \dt+. It will return a description&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;column containing that comment. It&amp;#39;s useful when working on a legacy database&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;for example&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Please note that comments aren&amp;#39;t exclusive to tables, they can be executed on&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;schemas and multiple other objects.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Note: If you find errors, typos or would like to add new tips, feel free to
reach out to me on twitter. I&#x27;m &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;. Thank
you for reading ! And if you find this useful, share it with your friends and
coworkers !&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>The Ultimate Remote Development Setup</title>
          <pubDate>Tue, 08 May 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/the-ultimate-setup-for-remote-development/</link>
          <guid>https://aaqa.dev/notes/the-ultimate-setup-for-remote-development/</guid>
          <description xml:base="https://aaqa.dev/notes/the-ultimate-setup-for-remote-development/">&lt;p&gt;I&#x27;m a programmer. Like most programmers, I use an Apple laptop. They&#x27;re just the
best on the market and the best purchase you can make as a developer. No
fanboyism here, just stating facts. They&#x27;re fast, well built, and durable.&lt;&#x2F;p&gt;
&lt;p&gt;I rely on this laptop for all my personal &#x2F; client work. I run Vagrant boxes,
Docker containers on it and all the usual stuff.&lt;&#x2F;p&gt;
&lt;p&gt;As a result, I&#x27;ve developed this irrational fear that it would get stolen or
fall off my bedroom window (things like that happen, trust me). Interestingly
enough, it coincides with my growing interest for remote work.&lt;&#x2F;p&gt;
&lt;p&gt;So I started to look for ways to create a development server that would allow me
to remain productive even if I lose &#x2F; break my laptop, or when I&#x27;m on the road.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, so you&#x27;ve read all this and you&#x27;re thinking &quot;How is it going to benefit me ?&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;The main selling points to creating a remote development environment are the
following:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It&#x27;s cheap&lt;&#x2F;li&gt;
&lt;li&gt;You learn linux&lt;&#x2F;li&gt;
&lt;li&gt;You become OS agnostic (I said no fanboyism)&lt;&#x2F;li&gt;
&lt;li&gt;You can work from almost anywhere&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;what-you-need&quot;&gt;What you need&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;laptop&quot;&gt;Laptop&lt;&#x2F;h3&gt;
&lt;p&gt;Because all of your work is now done on a remote machine you don&#x27;t really have
to care about what computer you&#x27;re using. It can be a super expensive (notice I
didn&#x27;t say overpriced) Apple laptop or any of its really good windows competitors (the DELL xps 13&#x2F;15 comes to mind) or even a super cheap, 35$ raspberry Pi. Some people even use chromebooks ! They stick ubuntu on them and use them as their primary machines (SSH is a bit tricky to setup on chrome OS) but hey! Official &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.xda-developers.com&#x2F;chromebooks-linux-app-support&#x2F;&quot;&gt;Linux support&lt;&#x2F;a&gt; is coming for you ChromeOS folks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dev-tools&quot;&gt;Dev Tools&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;git&quot;&gt;Git&lt;&#x2F;h3&gt;
&lt;p&gt;This one&#x27;s obvious. While git is a life saver and a great tool for collaboration in large teams (distributed or not), you can also use it as a backup system for your code when you&#x27;re a solo developer.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;vim&quot;&gt;Vim&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;ve used sublime text but felt bad for continuously extending the trial because I
couldn&#x27;t pay for it. Then I switched back to VSCode and got frustrated by how slow it
runs after using Sublime. Then I tried vim, and I never
looked back. It&#x27;s the lightest, fastest and overall best text editor out there by a huge
margin (in my opinion).&lt;&#x2F;p&gt;
&lt;p&gt;Vim is highly customizable and lets you save your settings inside a
&lt;code&gt;.vimrc&lt;&#x2F;code&gt; file, which makes it version control friendly. It also makes your vim
environment 100% portable as it comes standard in most linux server distros.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tmux&quot;&gt;Tmux&lt;&#x2F;h3&gt;
&lt;p&gt;The best companion to vim. Tmux is a terminal multiplexer. With Tmux you can
essentially access multiple terminal sessions inside a single window. This gives
you the ability to work on multiple projects at a time. You can even save
sessions, attach and reattach to them. It&#x27;s painless.
Just like vim, it&#x27;s extremely customizable. All of your settings can be stored
inside of a &lt;code&gt;.tmux.conf&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-vps&quot;&gt;A VPS&lt;&#x2F;h3&gt;
&lt;p&gt;To start developing on a remote server, you&#x27;ll need ... well, a remote
server. If you don&#x27;t know what a VPS is, it stands for &lt;strong&gt;Virtual Private Server&lt;&#x2F;strong&gt;.
It&#x27;s essentially a virtual machine that you pay for monthly, which runs a server
distribution of linux (Ubuntu, CentOS ...), or Unix (FreeBSD). You can connect to it via SSH (it has a public ip address) and start playing around. You have complete control over the server, you can configure it however way you want.&lt;&#x2F;p&gt;
&lt;p&gt;There&#x27;s a large range of VPS providers on the market, the most notable
ones are &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.linode.com&#x2F;&quot;&gt;Linode&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&quot;&gt;Digital Ocean&lt;&#x2F;a&gt;, and &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;ec2&#x2F;&quot;&gt;Amazon EC2&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;dotfiles&quot;&gt;Dotfiles&lt;&#x2F;h3&gt;
&lt;p&gt;As I previously mentioned above, you can save your settings for vim and tmux in
what are called &lt;strong&gt;dotfiles&lt;&#x2F;strong&gt; (files that start with a period). However dotfiles
are not exclusive to vim and tmux, you can for example save your shell configuration in a &lt;strong&gt;.zshrc&lt;&#x2F;strong&gt; or &lt;strong&gt;.bashrc&lt;&#x2F;strong&gt; config file, or your git settings in a &lt;strong&gt;.gitconfig&lt;&#x2F;strong&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;Doing this is extremely powerful because you can store these configuration files
on github and always pull the latest version when you launch a new development server.&lt;&#x2F;p&gt;
&lt;p&gt;You can check out my own &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;aaqaishtyaq&#x2F;dotfiles&quot;&gt;dotfiles&lt;&#x2F;a&gt; on github to help you get started.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;optional-ansible&quot;&gt;(Optional) Ansible&lt;&#x2F;h3&gt;
&lt;p&gt;Manually setting up servers is fun for the first couple of times, then it just
becomes repetitive. And what do you do with repetitive tasks ? You automate
them.&lt;&#x2F;p&gt;
&lt;p&gt;Ansible is a provisioning tool written in python that will help you do just that.
You give it the ip address (or addresses) of the server you want to configure and it will execute all the tasks you tell it to.&lt;&#x2F;p&gt;
&lt;p&gt;With Ansible you can:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;run shell commands&lt;&#x2F;li&gt;
&lt;li&gt;install packages&lt;&#x2F;li&gt;
&lt;li&gt;create directories and files&lt;&#x2F;li&gt;
&lt;li&gt;add users and groups&lt;&#x2F;li&gt;
&lt;li&gt;clone git repos&lt;&#x2F;li&gt;
&lt;li&gt;use templates and pass variables to them&lt;&#x2F;li&gt;
&lt;li&gt;and much more&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you don&#x27;t like Ansible, there are other server provisioning tools like
&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;puppet.com&#x2F;&quot;&gt;puppet&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.chef.io&#x2F;&quot;&gt;chef&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;saltstack.com&#x2F;&quot;&gt;salt&lt;&#x2F;a&gt; that will work just as good.&lt;&#x2F;p&gt;
&lt;!--If you&#x27;re interested, you can have a look at the [ansible playbook I&#x27;ve made](https:&#x2F;&#x2F;github.com&#x2F;aaqaishtyaq&#x2F;night-city) to provision my development servers.--&gt;
&lt;h2 id=&quot;caveats&quot;&gt;Caveats&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;it takes time to learn linux and networking (SSH etc)&lt;&#x2F;li&gt;
&lt;li&gt;vim has a learning curve to it&lt;&#x2F;li&gt;
&lt;li&gt;you become reliant on an internet connection&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Deploy a Django App with Git</title>
          <pubDate>Mon, 07 May 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/deploy-django-application-git/</link>
          <guid>https://aaqa.dev/notes/deploy-django-application-git/</guid>
          <description xml:base="https://aaqa.dev/notes/deploy-django-application-git/">&lt;p&gt;I&#x27;m going to make a bold statement: Django replaced Ruby on Rails in the hearts
of many developers. With this increase in popularity, we&#x27;ve seen tons of
articles, videos, and websites dedicated to setting up Django and creating apps
with the framework.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, when it comes to deployment, many of these resources only mention
heroku or pythonanywhere. While these are excellent solutions for quickly
shipping your MVP or prototype, they lack a bit of flexibility if you
want to create your custom deployment pipeline.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;tl;dr: If you manage your own server infrastructure, we&#x27;re going to set up a
Git deployment workflow with Django.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-you-ll-need&quot;&gt;What you&#x27;ll need&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Working knowledge of ssh&lt;&#x2F;li&gt;
&lt;li&gt;Working knowledge of git&lt;&#x2F;li&gt;
&lt;li&gt;Working knowledge of the bash shell&lt;&#x2F;li&gt;
&lt;li&gt;Basic linux command line skills (sorry hipsters)&lt;&#x2F;li&gt;
&lt;li&gt;(Very) Basic knowledge of vi&#x2F;vim&lt;&#x2F;li&gt;
&lt;li&gt;Patience&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The typical workflow usually looks like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You have your development environment, either on your local machine or a remote server&lt;&#x2F;li&gt;
&lt;li&gt;A git server (on GitHub, BitBucket, GitLab ...) that you and your team push your work to&lt;&#x2F;li&gt;
&lt;li&gt;A production server (aka your live app).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Usually when you commit and push work you do something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; push&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; origin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;branch_nam&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;origin&lt;&#x2F;code&gt; being the name of the remote server your code is being pushed to.
What took me a while to realise is that you can have many remotes for your repo
that point to different servers.&lt;&#x2F;p&gt;
&lt;p&gt;The idea here is to add a new remote to our repo. It will point to our
production server such that when we run &lt;code&gt;git push live master&lt;&#x2F;code&gt;, our code will be
copied over to there.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-the-production-server&quot;&gt;On the production server&lt;&#x2F;h2&gt;
&lt;p&gt;To achieve this, we have some setup work to do on our live server. So go ahead
and connect to it via ssh.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user@host_or_ip_address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; If your server&amp;#39;s ssh service listens on a port other than 22, you&amp;#39;ll need&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; to add the -p switch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ssh&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; PORT&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; user@host_or_ip_address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once we&#x27;re in, we need to create a new directory for our application. This is
where our deployed code will be copied to.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;home&#x2F;user&#x2F;sites&#x2F;myawesomedjangoproject&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Some people prefer to use &#x2F;var&#x2F;www&#x2F;&amp;lt;project_name&amp;gt;, it&amp;#39;s really up to you. Just&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; make sure remember the path to your project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now head over to &lt;code&gt;&#x2F;var&lt;&#x2F;code&gt; and create another directory called &lt;code&gt;repos&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;var&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; repos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Depending on your setup, you might need sudo priveleges&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Inside that directory, we need to create a folder named after our project
(or domain name) and append it with &lt;code&gt;.git&lt;&#x2F;code&gt; (not necessary but it&#x27;s good practice)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myawsomedjangoproject.com.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Inside this folder we&#x27;ll create what is called a &lt;code&gt;bare&lt;&#x2F;code&gt; repository. To do this
just run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; init&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-bare&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you run &lt;code&gt;ls&lt;&#x2F;code&gt; inside that folder you&#x27;ll see a bunch of files and directories
(the same ones found inside the &lt;code&gt;.git&lt;&#x2F;code&gt; folder in normal repos). One of these
directories is called &lt;code&gt;hooks&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Inside that folder, we&#x27;ll need create a file called post-receive.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Assuming you are inside &#x2F;var&#x2F;repos&#x2F;yourproject.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; touch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hooks&#x2F;post-receive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now open it up with vi&#x2F;vim&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hooks&#x2F;post-receive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hit &lt;code&gt;i&lt;&#x2F;code&gt; to switch to insert mode, and add the following to the file:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;w&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; or whatever path you chose&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;GIT_WORK_TREE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Please note that the first shebang line is important, it instructs git to use
bash instead of the default shell. Otherwise it won&#x27;t activate our (soon to be
created) virtual environment&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;exit vim by hitting &lt;code&gt;:wq&lt;&#x2F;code&gt; (which in vim lingo means write and quit)&lt;&#x2F;p&gt;
&lt;p&gt;What we&#x27;ve done here is set two variables. &lt;code&gt;DEPLOYDIR&lt;&#x2F;code&gt; is an alias for our
project path on the server, and &lt;code&gt;GIT_WORK_TREE&lt;&#x2F;code&gt; which is a special variable that
tells git to copy the code it receives inside of our &lt;code&gt;DEPLOYDIR&lt;&#x2F;code&gt;. This ensures
that we&#x27;re always running the latest version of our code.&lt;&#x2F;p&gt;
&lt;p&gt;As you&#x27;ve probably noticed, this post-receive file looks very much like a shell
script. That&#x27;s because it is (as explained above). It&#x27;s executed every time you
push code to the repo.&lt;&#x2F;p&gt;
&lt;p&gt;The last thing we need to is make the script executable, so as soon as you&#x27;re
back in the shell run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; chmod&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; +x&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hooks&#x2F;post-receive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now exit the server and go back to your local machine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;on-our-local-dev-environment&quot;&gt;On our local dev environment&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we&#x27;ve created our remote repository, we need to add it to our
project (I like to call mine &lt;code&gt;live&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;It takes one simple command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; live&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; root@ip_address:&#x2F;var&#x2F;repos&#x2F;myawesomedjangoproject.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; And if your server&amp;#39;s ssh service listens on a different port :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; live&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ssh:&#x2F;&#x2F;root@ip_address:PORT&#x2F;var&#x2F;repos&#x2F;myawesomedjangoproject.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To make sure it was added, you can print the list of available remotes by running:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; remote&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; v for verbose&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and that&#x27;s it ! You can now make changes locally, commit and deploy
them live (or staging if it&#x27;s a staging server) and see your changes instantly.&lt;&#x2F;p&gt;
&lt;p&gt;You can obviously still push to github&#x2F;lab or bitbucket with
&lt;code&gt;git push origin &amp;lt;branch&amp;gt;&lt;&#x2F;code&gt;
like you normally would.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus&quot;&gt;Bonus&lt;&#x2F;h2&gt;
&lt;p&gt;As I mentioned in the first part, the post-receive hook is a shell script. Which
means you can use it to perform all kinds of tasks against your code, like
running front-end builds, installing dependencies, etc ...&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example for a basic Django App:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;&#x2F;bin&#x2F;bash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;w&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Starting code update &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;GIT_WORK_TREE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished code update &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; [[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -d&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;ENV_projectname&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Cleaning virtualenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;rf&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ENV_projectname&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished creating virtualenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Creating virtualenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; virtualenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; python3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ENV_projectname&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished creating virtualenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Activating virtualEnv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; source&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ENV_projectname&#x2F;bin&#x2F;activate&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished activating virtualenv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Pulling down pip dependencies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; pip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; requirements.txt&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished pulling down pip dependencies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Staring DB migration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; manage.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; makemigrations&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; manage.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; migrate&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished DB migration &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Pulling Node Dependencies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; npm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished Pulling Node Dependencies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Building the Front end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; gulp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished building the Front end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Collecting static assets&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;DEPLOYDIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; python&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; manage.py&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; collectstatic&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-clear&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-no-input&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished collecting static assets&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Restarting App&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; service&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myawesomedjangoapp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; restart&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;[log] - Finished collecting static assets&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;I run my Django Apps as systemd services, if you don&#x27;t you can just call python
manage.py runserver. If you want to know how to setup Django the way I do just
follow this very comprehensive tutorial over on &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.digitalocean.com&#x2F;community&#x2F;tutorials&#x2F;how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-14-04&quot;&gt;Digital Ocean&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I am fully aware that there are more sophisticated methods of deployment through
Docker, Travis (For continious integration) etc. But if you have a small app that
you want to ship and you already have an infrastructure, I&#x27;ve found this method
to be more than suitable.&lt;&#x2F;p&gt;
&lt;p&gt;Please report any missing info, mistake, error, typo. I&#x27;m on &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt; twitter &lt;&#x2F;a&gt; if you
wanna chat.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Useful File Operations in Python</title>
          <pubDate>Wed, 28 Mar 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/basic-file-operations-in-python/</link>
          <guid>https://aaqa.dev/notes/basic-file-operations-in-python/</guid>
          <description xml:base="https://aaqa.dev/notes/basic-file-operations-in-python/">&lt;p&gt;In this short post (spoiler: it&#x27;s actually quite lengthy), I&#x27;m going to walk
through a list of useful methods in the &lt;code&gt;os&lt;&#x2F;code&gt; module (which is part of the
Python standard library) for handling files and directories.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-create-a-directory&quot;&gt;1. Create a directory&lt;&#x2F;h2&gt;
&lt;p&gt;This one is pretty straightforward. If you&#x27;re comfortable with the linux shell,
you know that &lt;code&gt;mkdir&lt;&#x2F;code&gt; is the command to use to create directories.
Unsurprisingly, Python uses the same naming convention.&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mkdir&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;my_awesome_directory&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The method takes a string as its argument and will create the directory under the
file&#x27;s parent folder. (For instance, if the path to the file calling os.mkdir()
is &#x2F;home&#x2F;username&#x2F;Documents&#x2F;app.py, the &quot;my_awesome_directory&quot; will be created
under &#x2F;home&#x2F;username&#x2F;Documents)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-get-a-file-s-parent-directory&quot;&gt;2. Get a file&#x27;s parent directory.&lt;&#x2F;h2&gt;
&lt;p&gt;This is useful if you want the path to a file or folder that you know lives
under the working file&#x27;s parent directory. If that sounded confusing, here&#x27;s an
example.&lt;&#x2F;p&gt;
&lt;p&gt;In the Linux shell (bash or otherwise), you can issue the command &lt;code&gt;pwd&lt;&#x2F;code&gt;
(which I believe stands for &quot;print working directory&quot;) to quickly print your
current location within a given session.&lt;&#x2F;p&gt;
&lt;p&gt;In Python you would achieve this like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getcwd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice I used all caps for the variable name. This is because it&#x27;s usually a
constant. This variable isn&#x27;t meant to be changed.
You can now use this variable to locate any file or folder within that
directory. Keep reading and I&#x27;ll show you how.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-concatenate-paths&quot;&gt;3. Concatenate paths&lt;&#x2F;h2&gt;
&lt;p&gt;This is something you&#x27;ll find yourself doing a lot. Especially on large projects
that require configuration files and other such things. If you have experience
working with Django for example, they have a &lt;code&gt;settings.py&lt;&#x2F;code&gt; file littered with
calls to the os module. There are many benefits to this approach. Perhaps the
most obvious being is that if you ever decide to move your project to another
location, you don&#x27;t want to keep modifying the path every time. Remember,
programming is all about being lazy.&lt;&#x2F;p&gt;
&lt;p&gt;So this is how you would do it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Assuming this file is located at &#x2F;home&#x2F;username&#x2F;myproject&#x2F;app.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; and that you want to operate on a a file called config.cfg within the same&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; directory :&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getcwd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; evaluates to &#x2F;home&#x2F;username&#x2F;myproject&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;MY_TEXT_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;config.cfg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;MY_TEXT_FILE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; &#x2F;home&#x2F;username&#x2F;myproject&#x2F;config.cfg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;An important note: os.path.join() merely concatenates the two paths together.
It doesn&#x27;t check whether the path is valid. So be careful when using this
method. Also notice how the method call is to os.path.join() and not os.join()&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-check-that-a-path-exists&quot;&gt;4. Check that a path exists&lt;&#x2F;h2&gt;
&lt;p&gt;The other day I was working on a small web scraper for a side project of mine.
After the it was done fetching data, my script would save the results into a
pickle file (don&#x27;t worry if you don&#x27;t know what it is) that would be read by my
program, saving me the trouble of sitting there waiting to fetch the same info
over and over again each time I run the script.&lt;&#x2F;p&gt;
&lt;p&gt;The solution was to tell my script to check whether a specific file (let&#x27;s call
it results.pkl) exists at a given path. If it does, the program continues and
if not, the program executes the crawler function.&lt;&#x2F;p&gt;
&lt;p&gt;This is clever because now I only have to fetch the data and if the file gets
deleted I know I can rely on the program to go and crawl the sites as expected.&lt;&#x2F;p&gt;
&lt;p&gt;And now for the example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getcwd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;RESULTS_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;results.pkl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; crawl_data&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;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; scrapes a bunch of websites and saves the result in a file called&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; results.pkl under the current directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;exists&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;RESULTS_FILE&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    crawl_data&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;# the file exists so we can open it and work with its content&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same thing can be done to check that the path exists AND that it&#x27;s a
directory:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getcwd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;MY_DIRECTORY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;CURRENT_DIR&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;my_directory&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;exists&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;MY_DIRECTORY&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; and&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;isdir&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;MY_DIRECTORY&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;# do something with the files inside the folder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;mkdir&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;MY_DIRECTORY&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;5-list-files-within-a-given-directory&quot;&gt;5. List files within a given directory&lt;&#x2F;h2&gt;
&lt;p&gt;Very useful when you want to read several files that are under the same
directory.
It can be done in two ways: conventional and pythonic. I&#x27;ll show you both.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;listdir&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;path&#x2F;to&#x2F;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; do something with the filename (open it, copy it,  move it, rename it...)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;filenames&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; os&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;listdir&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;path&#x2F;to&#x2F;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Guess which way is more pythonic!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;These have been the most useful file&#x2F;directory functions for me in Python. I
really love the fact that the method names sound natural and are (for the most
part) similar to linux commands. What are your favourite file operation methods? Any tip or trick you want to share with me? Something I&#x27;ve missed? Ping on
twitter! I&#x27;m &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you found this article useful, please share it with your nerd friends&#x2F;coworkers and spread the word!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Mind-Blowing Python Tips and Tricks</title>
          <pubDate>Thu, 15 Feb 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/mind-blowing-python-tips/</link>
          <guid>https://aaqa.dev/notes/mind-blowing-python-tips/</guid>
          <description xml:base="https://aaqa.dev/notes/mind-blowing-python-tips/">&lt;p&gt;A short list of Python tricks that make day-to-day code a little nicer.
Nothing too magical, just handy stuff.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;0-loop-over-a-range-of-numbers&quot;&gt;0 - Loop over a range of numbers&lt;&#x2F;h2&gt;
&lt;p&gt;Use &lt;code&gt;range&lt;&#x2F;code&gt; instead of &lt;code&gt;xrange&lt;&#x2F;code&gt;.
In Python 3, the former creates an iterator-like object that produces values
one at a time, which makes it much more efficient.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;nums&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 34&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 55&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;nums&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;1-looping-backwards&quot;&gt;1 - Looping backwards&lt;&#x2F;h2&gt;
&lt;p&gt;Just use &lt;code&gt;reversed&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Case&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Armitage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Maelcum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; reversed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;2-looping-over-a-list-and-its-indices&quot;&gt;2 - Looping over a list and its indices&lt;&#x2F;h2&gt;
&lt;p&gt;To keep track of the index of each item in a collection, enumerate is your buddy.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Case&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Armitage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Maelcum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; enumerate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; index&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;3-looping-over-two-lists-simultaneously&quot;&gt;3 - Looping over two lists simultaneously&lt;&#x2F;h2&gt;
&lt;p&gt;Yeah, you could use &lt;code&gt;zip&lt;&#x2F;code&gt;, but &lt;code&gt;izip&lt;&#x2F;code&gt; is faster, so use that instead.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; itertools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; izip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Case&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Armitage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Maelcum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; age&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; izip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ages&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; age&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;4-looping-over-a-sorted-list&quot;&gt;4 - Looping over a sorted list&lt;&#x2F;h2&gt;
&lt;p&gt;You can sort out the list first and then loop through it, or you could use
sorted.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Case&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Armitage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Maelcum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; sorted&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And BAM, you&#x27;re ... sorted.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-call-a-function-until-a-sentinel-value-is-returned&quot;&gt;5 - Call a function until a sentinel value is returned&lt;&#x2F;h2&gt;
&lt;p&gt;To do that, use iter().&lt;&#x2F;p&gt;
&lt;p&gt;Bad example:&lt;&#x2F;p&gt;
&lt;p&gt;Loop over a file containing a list of names
until the loop returns an empty string,
in which case we break out of it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;while&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        break&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    names&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Beautiful example:&lt;&#x2F;p&gt;
&lt;p&gt;In this case, we call a function (f.read) until it returns the sentinel value
passed as a second argument to iter.
That way we avoid having to make the unnecessary if check.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt; partial&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;f&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;32&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 class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;6-looping-over-a-dictionary&quot;&gt;6 - Looping over a dictionary&lt;&#x2F;h2&gt;
&lt;p&gt;The normal way to do it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly Millions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Age&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Occupation&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Professional Killer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; molly&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you wish to mutate the data, prefer &lt;code&gt;dict.keys()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly Millions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Age&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Occupation&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Professional Killer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; molly&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keys&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;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; do the mutation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;7-looping-over-a-dict-keys-and-values&quot;&gt;7 - Looping over a dict keys AND values&lt;&#x2F;h2&gt;
&lt;p&gt;Don&#x27;t do this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly Millions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Age&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Occupation&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Professional Killer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; molly&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; molly&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;key&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s slow because we have to rehash the dictionary and do a lookup everytime.&lt;&#x2F;p&gt;
&lt;p&gt;Instead choose &lt;code&gt;iteritems()&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly Millions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Age&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Occupation&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Professional Killer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; molly&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;iteritems&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;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;8-create-a-dict-out-of-two-lists&quot;&gt;8 - Create a dict out of two lists&lt;&#x2F;h2&gt;
&lt;p&gt;Just instantiate a new dict with two zipped lists. Real magic.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; itertools&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; izip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Case&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Molly&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Armitage&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Maelcum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ages&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;23&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 41&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;characters&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; dict&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;izip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;names&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; ages&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;9-use-named-tuples-for-returning-multiple-values&quot;&gt;9 - Use named tuples for returning multiple values&lt;&#x2F;h2&gt;
&lt;p&gt;Like in the case of an API response in Flask.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; collections&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; import&lt;&#x2F;span&gt;&lt;span&gt; namedtuple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; namedtuple&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;APIResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;status_code&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;route&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;users&#x2F;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid z-illegal&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    try&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; db&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;getuserbyid&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    except&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; Response&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;404&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;notfound&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 class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;content-type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;application&#x2F;json&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    else&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span&gt; Response&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;200&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;json&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 class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;content-type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;application&#x2F;json&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;other&quot;&gt;Other&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Always clarify function calls by using keyword arguments&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you learned something from this article, share it with your co-workers and
fellow hackers. If you notice any typo, error etc let me know on
&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Mind-Blowing Git Tips for Beginners</title>
          <pubDate>Mon, 05 Feb 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/mind-blowing-git-tips/</link>
          <guid>https://aaqa.dev/notes/mind-blowing-git-tips/</guid>
          <description xml:base="https://aaqa.dev/notes/mind-blowing-git-tips/">&lt;p&gt;As developers, we all (hopefully) use git. It&#x27;s not extremely hard or
time-consuming to get started with it, and you&#x27;ll surely thank your future self
for taking the time to learn it. Ok, that was the cringy intro.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s get down to business: what I really want to share in this post is a
list of tricks I&#x27;ve learned during the past 2 1&#x2F;2 years of using git. Some of
it might seem trivial to seasoned developers, but if you&#x27;re just getting
started, stick with me because a couple of these might just blow your mind.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-difference-between-git-fetch-and-pull&quot;&gt;The difference between git fetch and pull&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;code&gt;git fetch&lt;&#x2F;code&gt; only updates the tracking remote branches. If you actually want to
update the local repo, you need to merge the local branch with the remote
tracking branch using &lt;code&gt;git merge&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;remote branches are prefixed with the name of the remote and a slash:
origin&#x2F;branchname&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;git pull&lt;&#x2F;code&gt;, on the other hand, will execute both commands for you so when you issue
a &lt;code&gt;git pull&lt;&#x2F;code&gt; in a branch it will fetch that branch from the remote repo &lt;strong&gt;and&lt;&#x2F;strong&gt;
merge it with yours.&lt;&#x2F;p&gt;
&lt;p&gt;To list all remote tracking branches, &lt;code&gt;git branch -r&lt;&#x2F;code&gt; is your friend.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;merge-conflicts&quot;&gt;Merge conflicts&lt;&#x2F;h2&gt;
&lt;p&gt;At some point you&#x27;ll inevitably have to deal with merge conflicts. Essentially what this means is that git noticed a file was modified on both branches and it does not know which version is correct. It leaves it up to you to decide which one you want to push.&lt;&#x2F;p&gt;
&lt;p&gt;If you open the file you will see a &lt;code&gt;HEAD&lt;&#x2F;code&gt; part prefixed with &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt; signs and a
second part containing the code on the branch you&#x27;re trying to merge. Both
sections are separated with an equal sign.&lt;&#x2F;p&gt;
&lt;p&gt;The top HEAD section contains the version of the file as it is on your current
branch. The other shows you what the code looks like on the branch you&#x27;re trying to merge from.&lt;&#x2F;p&gt;
&lt;p&gt;To resolve the conflict just delete the part you don&#x27;t want (Including all the equal signs etc), save the file and commit it again.&lt;&#x2F;p&gt;
&lt;p&gt;Note that as a safety measure it&#x27;s always good practice to do a &lt;code&gt;git pull&lt;&#x2F;code&gt; to
see if you don&#x27;t have any remaining conflicts. If not you can just push your code and you&#x27;re all set!&lt;&#x2F;p&gt;
&lt;p&gt;As for the tips:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;git merge --abort&lt;&#x2F;code&gt; will clean up the current working directory and go back to
the last version before the merge (it pretty much nullifies the merge).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;git merge --squash&lt;&#x2F;code&gt; is an interesting one as it will bring the changes you made in the feature branch and create a new commit on your current branch without
mixing the two histories.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dealing-with-files&quot;&gt;Dealing with files&lt;&#x2F;h2&gt;
&lt;p&gt;Now this one&#x27;s tricky !&lt;&#x2F;p&gt;
&lt;p&gt;To remove a file from &lt;strong&gt;both&lt;&#x2F;strong&gt; the working directory and version control, you
can use &lt;code&gt;git rm &amp;lt;filename&amp;gt;&lt;&#x2F;code&gt; but if you already deleted a file in the cli like I (and almost everyone) usually do then just run &lt;code&gt;git rm &amp;lt;path to the file&amp;gt;&lt;&#x2F;code&gt; and it will stage it as deleted so you can commit.&lt;&#x2F;p&gt;
&lt;p&gt;But what if you ramrafed (&lt;code&gt;rm -rf&lt;&#x2F;code&gt;) a bunch of files in your working directory?
You don&#x27;t really want to manually stage every file for deletion, do you? (DO YOU ?) So what do you do in that case? Well, you just run &lt;code&gt;git add -u&lt;&#x2F;code&gt; (u for updating the working tree) and all of your deleted files will be staged so you can commit and push.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;What if a man accidentally tracked a file and man doesn&#x27;t want it deleted
from the index ?&quot; I hear you ask with an exquisite South London accent.&lt;&#x2F;p&gt;
&lt;p&gt;Well, my G, just run:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-cached&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fil&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and you&#x27;re done. Efficience ting.&lt;&#x2F;p&gt;
&lt;p&gt;Something else that happens quite often is moving&#x2F;renaming files (which is
essentially the same thing on Linux systems, as the path&#x2F;address of the file
changed).&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s an example: imagine you have a file called index.html that you
want to rename to home.html. you can use &lt;code&gt;git mv&lt;&#x2F;code&gt; which takes a source and a
destination:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; home.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;if you want to move &lt;strong&gt;and&lt;&#x2F;strong&gt; rename just run&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mv&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; path&#x2F;to&#x2F;home.html&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;However if you moved &#x2F; renamed the file manually on the command line, running
&lt;code&gt;git status&lt;&#x2F;code&gt; will tell you that index.html was deleted and home.html is untracked.&lt;&#x2F;p&gt;
&lt;p&gt;To fix this you will have to run two commands&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rm&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; aka the file you moved&#x2F;renamed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; home.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; aka the file with the new name x path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running git status again will mark the file as renamed.&lt;&#x2F;p&gt;
&lt;p&gt;Note that this also works if you don&#x27;t rename the file. For example, if you just
want to move index.html to src&#x2F;index.html. The same command will apply
(&lt;code&gt;git mv index.html src&#x2F;index.html&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;The other way of achieving this is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;A&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which will pick up the changes and automatically stage them for commit.&lt;&#x2F;p&gt;
&lt;p&gt;So there you go, I hope you learned something useful in this article. If you know
other mind-blowing tips and tricks for git, &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;aaqaishtyaq&quot;&gt;@ me on twitter&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Don&#x27;t Be Scared, Switch to Vim</title>
          <pubDate>Sat, 03 Feb 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/dont-be-scared-switch-to-vim/</link>
          <guid>https://aaqa.dev/notes/dont-be-scared-switch-to-vim/</guid>
          <description xml:base="https://aaqa.dev/notes/dont-be-scared-switch-to-vim/">&lt;p&gt;I&#x27;m currently sitting at the most boring meetup I&#x27;ve probably ever attended in
Delhi. It&#x27;s about chatbots. I don&#x27;t care about chatbots, I care about free
stickers and pizza. So I&#x27;m using this opportunity to open up about a subject
that&#x27;s dear to my heart: vim.&lt;&#x2F;p&gt;
&lt;p&gt;I used to believe vim was exclusive to this superior race of developers who
gulp coffee like it&#x27;s water and seem to only read HN and nothing else. (Hi, if
you&#x27;re coming from HN). Architecture and software design come naturally to them,
they never run into bugs and they can recognize the most obscure of algorithms
at a glance (Shout out to Shashank, one of my mentors).&lt;&#x2F;p&gt;
&lt;p&gt;Shanky is a good, productive developer. Shanky uses vim. I want to be like Shanky. I want
to use vim.&lt;&#x2F;p&gt;
&lt;p&gt;There are a million reasons why you should jump ship and join the cult. In the
next paragraphs, I will detail some of these reasons.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-s-not-that-hard&quot;&gt;It&#x27;s not (that) hard&lt;&#x2F;h2&gt;
&lt;p&gt;There&#x27;s a learning curve to vim, but it&#x27;s worth the
trouble. And if you&#x27;re on Linux or MacOS, there&#x27;s a built-in tool called
&lt;code&gt;vimtutor&lt;&#x2F;code&gt; (just fire it up from a terminal, I am not sure about Windows though) and
a wide variety of online tools to learn vim. Namely &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.openvim.com&#x2F;&quot;&gt;openvim&lt;&#x2F;a&gt;,
&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vim-adventures.com&#x2F;&quot;&gt;vim adventures&lt;&#x2F;a&gt;, and &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;www.vimgenius.com&#x2F;&quot;&gt;vim genius&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, The way I learned was by using it on small, fun side projects of
mine during the weekends, mostly to become familiar with the new mental model.
And just like everything in life, shit takes time, and practice makes perfect.
So keep at it and you&#x27;ll eventually come to your &quot;aha&quot; moment.
As you get more and more comfortable using vim, it will become harder and harder
to go back to a regular editor &#x2F; IDE.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;it-s-fast-and-customisable&quot;&gt;It&#x27;s Fast and Customisable&lt;&#x2F;h2&gt;
&lt;p&gt;Because it runs on the terminal, you&#x27;ll never have to wait 20 seconds to get
on with your work. (Atom anyone ?)&lt;&#x2F;p&gt;
&lt;p&gt;And if you like pretty things, there&#x27;s a &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;vimcolors.com&#x2F;&quot;&gt;large selection of colorschemes&lt;&#x2F;a&gt;
for you to choose from. On top of that, there&#x27;s a plugin for just about anything
you might need. And if there isn&#x27;t, you can program your own.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ubiquity&quot;&gt;Ubiquity&lt;&#x2F;h2&gt;
&lt;p&gt;Not really, but I wanted to place a complicated word to sound smart.
Seriously though, it&#x27;s everywhere. On Mac OS, Windows and of course Linux&#x2F;Unix. If
you work on remote servers you can quickly edit files on the fly without having
to use nano. (Don&#x27;t use nano)&lt;&#x2F;p&gt;
&lt;p&gt;Say for example a coworker&#x2F;friend is running into a bug, you come to help and
they&#x27;re using an IDE you&#x27;re not familiar with, well you can just access the files
from their terminal and start debugging right away.&lt;&#x2F;p&gt;
&lt;p&gt;Or if you&#x27;re like me, and you spill water on your Macbook keyboard and it becomes
toast, you can spin up a VPS on Digital Ocean or AWS, and pick up where you
left off (almost) right away.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus-some-of-my-favorite-plugins&quot;&gt;Bonus: Some of my favorite plugins&lt;&#x2F;h2&gt;
&lt;p&gt;My color scheme of choice (at the time of writing) is &lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;danilo-augusto&#x2F;vim-afterglow&quot;&gt;afterglow&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And here&#x27;s a list of my favorite plugins:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;scrooloose&#x2F;nerdtree&quot;&gt; Nerdtree &lt;&#x2F;a&gt; (A tree explorer much like the sidebar in traditional IDEs)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vim-airline&#x2F;vim-airline&quot;&gt; Airline &lt;&#x2F;a&gt; (A sleek, customizable status bar)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-surround&quot;&gt; Surround &lt;&#x2F;a&gt; (Helpful tool that helps with &quot;surrounding&quot; words with brackets etc)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kien&#x2F;ctrlp.vim&quot;&gt; CtrlP &lt;&#x2F;a&gt; (A fuzzy finder for vim)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;SirVer&#x2F;ultisnips&quot;&gt; UtilSnips &lt;&#x2F;a&gt; (Snippet utility for many languages)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;plasticboy&#x2F;vim-markdown&quot;&gt; Vim  Markdown&lt;&#x2F;a&gt; (Markdown syntax highlighting)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;goyo.vim&quot;&gt; Goyo &lt;&#x2F;a&gt; (Allows for distraction-free editing)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I&#x27;ll end this article with a quote from a Chamillionaire:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;They see you vimmin&#x27;, they hatin&#x27;. Patroling they tryna catch me coding dirty&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</description>
      </item>
      <item>
          <title>Algorithms in Python: Understanding Bubble Sort</title>
          <pubDate>Mon, 08 Jan 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/algorithms-in-python-bubble-sort/</link>
          <guid>https://aaqa.dev/notes/algorithms-in-python-bubble-sort/</guid>
          <description xml:base="https://aaqa.dev/notes/algorithms-in-python-bubble-sort/">&lt;h2 id=&quot;some-theory&quot;&gt;Some theory&lt;&#x2F;h2&gt;
&lt;p&gt;Bubble sort is one of the most commonly known sorting algorithms. The idea is
simple: scan a list of items (say integers) sequentially, from left to right,
and compare consecutive pairs of elements starting at index 0.&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;92&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2234&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 92 is index 0 and the consecutive pairs are&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; (92,11), (11,45), (45,2234) and so on ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First we compare elements (list[0],list[1]) then (list[1],list[2]) then
(list[2],list[3]) and so on until we reach the end of the list.&lt;&#x2F;p&gt;
&lt;p&gt;When comparing, we check if element i is greater than element i + 1. If it is,
we swap the two elements and move on to the next pair. If not, it means the
pair is already sorted, so we still move on to the next pair.&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;92&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2234&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Let&amp;#39;s compare my_numbers[0] and my_numbers[1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; my_numbers&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; my_numbers&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    swap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;my_numbers&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; my_numbers&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;my_numbers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [11, 92, 45, 2234, 0, 7, 65]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This process has to be repeated for however many items are on the list. So if
the list holds 9 items, it means we need to loop through it 9 times at most.
But what if our original list is partially sorted? We might not need 9 passes
through the list.&lt;&#x2F;p&gt;
&lt;p&gt;One way for us to know that the list is fully sorted is if we have made no
swaps during our pass. For that, we need a variable to keep track of how many
swaps were made during a pass.&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;92&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;45&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2234&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;65&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Elements (0,1) are compared and swapped. List is now 11,92,45,2234,0,7,65&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Elements (1,2) are compared and swapped. List now 11,45,92,2234,0,7,65&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Elements (2,3) are compared and not swapped. List remains the same.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Elements (3,4) are compared and swapped. List is now 11,45,92,0,2234,0,7,65&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Elements (4,5) are compared and swapped. List is now 11,45,92,0,7,2234,65&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Elements (5,6) are compared and swapped. List is now 11,45,92,0,7,65,2234&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This represents one unique pass through the list.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice how after each pass the highest value number is pushed at len(list) - 1.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-code&quot;&gt;Some code&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s look at how to implement Bubble Sort in Python:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bubble_sort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;some_list&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; is_sorted&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;some_list&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                some_list&lt;&#x2F;span&gt;&lt;span&gt;[&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; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works fine and it will sort any list you throw at it. However we can
slightly optimise it: We know that, after each pass the highest value element is
guaranteed to be sorted and placed at len(some_list) - 1. Because of this, for
each subsequent pass, we can stop comparing the last sorted item. instead of
comparing pairs that we know are already sorted.
This is what it looks like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bubble_sort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;some_list&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_sorted_item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;some_list&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; is_sorted&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; last_sorted_item&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                some_list&lt;&#x2F;span&gt;&lt;span&gt;[&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; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        last_sorted_item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After each pass through the loop, we know the right side of the list is sorted
so we decrement the value of last_sorted_item. What this means is that the 1st
pass will loop from 0 to len(some_list) -1, the second time, it will be from 0
to len(some_list) - 2 and so on ...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;time-complexity&quot;&gt;Time complexity&lt;&#x2F;h2&gt;
&lt;p&gt;The rate of growth of this algorithm is quadratic. Expressed as O(n^2) in
&quot;big-oh&quot; notation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; bubble_sort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;some_list&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; False&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                       #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; time here is constant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    last_sorted_item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;some_list&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    while&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; is_sorted&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We go through this first loop n times&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; last_sorted_item&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; we go through this loop n-1 times&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; execution here is constant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                some_list&lt;&#x2F;span&gt;&lt;span&gt;[&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; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; some_list&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                is_sorted&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; False&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        last_sorted_item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; constant time&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It&#x27;s O(n^2) because, for each pass through the loop n times, we loop n times
through the consecutive pairs. It&#x27;s not a very efficient algorithm when used on large samples of data. It should only be used if you have a
specific case on a small data set.&lt;&#x2F;p&gt;
&lt;p&gt;Next in the series is QuickSort, another interesting and more efficient sorting
algorithm. As always, if you have questions, comments or if you spotted a typo
or a mistake, please feel free to let me know on Twitter, I&#x27;m
&lt;a rel=&quot;noopener nofollow noreferrer external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;zabanaa&quot;&gt;@aaqaishtyaq&lt;&#x2F;a&gt; and always happy to help!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Algorithms in Python: Understanding Quick Sort</title>
          <pubDate>Mon, 08 Jan 2018 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://aaqa.dev/notes/algorithms-in-python-quick-sort/</link>
          <guid>https://aaqa.dev/notes/algorithms-in-python-quick-sort/</guid>
          <description xml:base="https://aaqa.dev/notes/algorithms-in-python-quick-sort/">&lt;h2 id=&quot;theory&quot;&gt;Theory&lt;&#x2F;h2&gt;
&lt;p&gt;Quicksort is a &quot;divide and conquer&quot; type of algorithm. One good thing about
it is that the worst case can almost always be avoided by using what&#x27;s called a
randomized version of quicksort (more on that later).&lt;&#x2F;p&gt;
&lt;p&gt;The idea of Quicksort is to take an unsorted list and select one element from
it called a &quot;pivot&quot;. Then the list is rearranged such that all elements greater
(in value) than the pivot are placed to its right, and all elements lesser (in
value) are placed to its left.&lt;&#x2F;p&gt;
&lt;p&gt;This process is called partitioning. At this stage in the execution of the
algorithm, the order of the elements doesn&#x27;t matter so long as the
lesser&#x2F;bigger values are placed on the correct side of the pivot.&lt;&#x2F;p&gt;
&lt;p&gt;Partitioning will produce two sublists with the pivot as a separator (
this is because the pivot will be at its natural place after the first pass aka
sorted). The problem then becomes sorting these two sublists.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Note: Partitioning does not require creating copies of the
list, we work on it directly as long as we keep track of the start and end
indices of each sublist.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To sort the two sublists, we can apply the same logic as above (choosing a
pivot, and sorting the two resulting sublists) because QuickSort is a recursive
algorithm.&lt;&#x2F;p&gt;
&lt;p&gt;When a sublist only contains a single element, it&#x27;s already sorted so we can
stop the recursion at this point, it&#x27;s our exit condition.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Note on choosing a pivot&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Some people use the last item of the list, and some people use the median of the
first, last, and medium elements but the most common way is to choose a random
pivot to ensure &lt;code&gt;n log n&lt;&#x2F;code&gt; execution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;some-code&quot;&gt;Some Code&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; swap_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;lst&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; val1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; val2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lst&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;val1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; lst&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;val2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; lst&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;val2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; lst&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;val1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; quicksort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        partition_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; partition&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        quicksort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; partition_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        quicksort&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; partition_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; partition&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pivot&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    partition_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;pivot&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;            print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is less than &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;format&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span&gt;[&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; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;pivot&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;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            swap_values&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; partition_index&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            partition_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;pivot&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;partition_index&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;partition_index&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;pivot&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; partition_index&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A randomized version of Quicksort would look similar to what&#x27;s above except that
we must randomize the selection of our pivot.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span&gt; random&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; partition&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-parameter z-function&quot;&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        pivot&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; random&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;randint&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;pivot&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;pivot&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; array&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;end&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        partition_index&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;array&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; start&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; end&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, we set the pivot to a random integer in the range between &lt;code&gt;start&lt;&#x2F;code&gt;
and &lt;code&gt;end&lt;&#x2F;code&gt;. Then, we swap the value at that index with the value at array[end].
If you run the code successively, you&#x27;ll notice that the pivot is
different every time. It&#x27;s a nice optimization that can save some time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;time-complexity&quot;&gt;Time Complexity&lt;&#x2F;h2&gt;
&lt;p&gt;It&#x27;s one of the most efficient sorting algorithm. In fact, most sorting
functions that come packaged in many language&#x27;s standard libraries use an
implementation of QuickSort.&lt;&#x2F;p&gt;
&lt;p&gt;The order of growth for QuickSort in the worst case is quadratic O(n^2). The
average case, however, which is the most common scenario, has a complexity of
O(n log n).&lt;&#x2F;p&gt;
&lt;p&gt;QuickSort works best when used on large sets of data because of its recursive nature.&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
