<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[James Quigley's Blog]]></title><description><![CDATA[Personal blog on things like JavaScript, Docker, and more.]]></description><link>https://blog.quigley.codes</link><generator>GatsbyJS</generator><lastBuildDate>Fri, 06 Nov 2026 02:22:45 GMT</lastBuildDate><item><title><![CDATA[Kubernetes Autoscaling Overview]]></title><description><![CDATA[Table of Contents Summary Autoscalers Horizontal Pod Autoscaler Vertical Pod Autoscaler Cluster Autoscaler Autoscaling Caveats Cost…]]></description><link>https://blog.quigley.codes/kubernetes-autoscaling/</link><guid isPermaLink="false">https://blog.quigley.codes/kubernetes-autoscaling/</guid><pubDate>Tue, 15 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;table-of-contents&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#table-of-contents&quot; aria-label=&quot;table of contents permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Table of Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#summary&quot;&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#autoscalers&quot;&gt;Autoscalers&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#horizontal-pod-autoscaler-hpa&quot;&gt;Horizontal Pod Autoscaler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#vertical-pod-autoscaler-vpa&quot;&gt;Vertical Pod Autoscaler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#cluster-autoscaler&quot;&gt;Cluster Autoscaler&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#autoscaling-caveats&quot;&gt;Autoscaling Caveats&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#cost&quot;&gt;Cost&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#reasonable-limits&quot;&gt;Reasonable Limits&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#resource-constraints&quot;&gt;Resource Constraints&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;Kubernetes is often touted as the solution for modern cloud native deployments of applications. It provides an agnostic platform for running code in a fashion that can tick all the “-ility” boxes (i.e. reliability, scalability, observability, manageability etc).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;However when working with Kubernetes, by default nothing autoscales!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Autoscaling is a common tool when considering the scalability of your application. After all having to scale up a production application manually is time consuming and error prone. In Kubernetes you can specify a deployment with multiple replicas which can help with high availability, but that doesn’t address any sort of autoscaling concerns. Autoscaling can help your application keep up with increased load and save you money in times of reduced load.&lt;/p&gt;
&lt;p&gt;While they don’t come setup by default, there are three main types of autoscaling that you can utilize when it comes to Kubernetes. They are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Horizontal Pod Autoscaler (HPA)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vertical Pod Autoscaler (VPA)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster Autoscaler&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As implied by the names, HPA and VPA work on the pod level inside the cluster, whereas cluster autoscaler will add entire nodes to your worker fleet, dynamically scaling the entire cluster. Note that both HPA and VPA require Metrics Server installed in your cluster in order to function.&lt;/p&gt;
&lt;p&gt;HPA and VPA should &lt;strong&gt;not&lt;/strong&gt; be used together on CPU/Memory for a deployment. You can however combine them if using custom metrics on your HPA definition. That would allow you to scale up if you hit a CPU threshold, and scale out if you hit another limit, like request throughput, or queue length if you are autoscaling some kind of task processing pod.&lt;/p&gt;
&lt;h2 id=&quot;autoscalers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#autoscalers&quot; aria-label=&quot;autoscalers permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Autoscalers&lt;/h2&gt;
&lt;h3 id=&quot;horizontal-pod-autoscaler-hpa&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#horizontal-pod-autoscaler-hpa&quot; aria-label=&quot;horizontal pod autoscaler hpa permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Horizontal Pod Autoscaler (HPA)&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/&quot;&gt;Horizontal Pod Autoscaler&lt;/a&gt; is a part of the “autoscaling” &lt;a href=&quot;https://kubernetes.io/docs/reference/using-api/#api-groups&quot;&gt;api group&lt;/a&gt; in Kubernetes. As of right now, the v1 version of this API only supports autoscaling based on CPU, but the beta version supports autoscaling based on memory or custom metrics.&lt;/p&gt;
&lt;p&gt;HPA is a resource in your cluster that you can create with a definition like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; autoscaling/v1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; HorizontalPodAutoscaler
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;app
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;maxReplicas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;minReplicas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;scaleTargetRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; apps/v1
    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Deployment
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;app
  &lt;span class=&quot;token key atrule&quot;&gt;targetCPUUtilizationPercentage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It behaves pretty simply. You set a target utilization, minimum and maximum number of pods, and what deployment to target, and HPA does the rest. It will scale your deployment up/down based on the CPU utilization and try to keep the CPU metric as close to the target as possible, respecting the min and max replica values. If overnight you get a lot less traffic, now your deployment can scale down so as not to be using as many resources during that time. Then in the morning when traffic picks back up, it will automatically scale up to keep up with the increased load.&lt;/p&gt;
&lt;h3 id=&quot;vertical-pod-autoscaler-vpa&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#vertical-pod-autoscaler-vpa&quot; aria-label=&quot;vertical pod autoscaler vpa permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Vertical Pod Autoscaler (VPA)&lt;/h3&gt;
&lt;p&gt;Whereas HPA deals with scaling horizontally, or adding/removing pods, &lt;a href=&quot;https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler&quot;&gt;Vertical Pod Autoscaler&lt;/a&gt; scales vertically, which adjusts the resources allocated to pods in order to give them more CPU/Memory.&lt;/p&gt;
&lt;p&gt;Also unlike HPA, VPA is not baked into one of the default APIs, and must be installed into the cluster with a &lt;a href=&quot;https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/&quot;&gt;Custom Resource Definition (CRD)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A sample VPA definition might look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; autoscaling.k8s.io/v1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; VerticalPodAutoscaler
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;app
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;targetRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; apps/v1
    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;       Deployment
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;       my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;app
  &lt;span class=&quot;token key atrule&quot;&gt;updatePolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;updateMode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Auto&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;VPA will examine your pods, and if they are maxing out their resources, will update the pods to give them more resources. There’s some nuance to the “updateMode”, in that “Auto” by default will evict running pods to adjust their resources. This gives you a more dynamic scaling, but also means that pods can be evicted by VPA, potentially causing downtime if your configuration doesn’t have multiple replicas and/or you haven’t configured Pod Disruption Budgets.&lt;/p&gt;
&lt;p&gt;There is no current way for VPA to update resources on a pod in place, but if/when that becomes available in the future, it is likely that it will become the default updateMode when selecting “Auto”.&lt;/p&gt;
&lt;h3 id=&quot;cluster-autoscaler&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cluster-autoscaler&quot; aria-label=&quot;cluster autoscaler permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Cluster Autoscaler&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler&quot;&gt;Cluster Autoscaler&lt;/a&gt; behaves much like HPA, but instead of scaling pods it adds/removes worker nodes in your cluster. When combined with HPA and/or VPA, this allows for a truly dynamic cluster experience, allowing you to go from a single worker node with a single pod all the way up to a large cluster with tons of pods without having to scale anything manually.&lt;/p&gt;
&lt;p&gt;Installing and using cluster autoscaler takes a little bit more work than HPA though, since it needs to be aware of where and how you are running your cluster. For example, if you’re running a cluster in AWS, cluster autoscaler needs IAM permissions to manage the autoscaling groups for your worker nodes, where as if you’re running in Azure, you’ll need to create a service principal in your Subscription with at least the “Contributor” role.&lt;/p&gt;
&lt;p&gt;Cluster autoscaler works by looking at the resources of all the nodes and all the pods, and determining if nodes need to be added to support the current number of pods (or unschedulable pods because of a lack of resources), or if entire nodes can be removed because they are either unused or their workload could be moved to other nodes.&lt;/p&gt;
&lt;p&gt;Cluster Autoscaler is powerful because it doesn’t simply scale on the CPU Utilization % on the worker nodes, but performs pod scheduling simulations to see where pods could be scheduled if it were to add or remove nodes.&lt;/p&gt;
&lt;h2 id=&quot;autoscaling-caveats&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#autoscaling-caveats&quot; aria-label=&quot;autoscaling caveats permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Autoscaling Caveats&lt;/h2&gt;
&lt;h3 id=&quot;cost&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cost&quot; aria-label=&quot;cost permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Cost&lt;/h3&gt;
&lt;p&gt;Since your infrastructure usage can fluctuate day to day or even minute to minute, your costs could vary greatly. Likely for any company already running applications in the cloud, you are used to the pay-as-you-go model, but its still something to take into consideration. Month to month your cloud bill could look quite different&lt;/p&gt;
&lt;h3 id=&quot;reasonable-limits&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#reasonable-limits&quot; aria-label=&quot;reasonable limits permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Reasonable Limits&lt;/h3&gt;
&lt;p&gt;When setting up autoscaling, you are likely operating in an elastic cloud environment that could scale up “infinitely”. Due to this, an issue with your autoscaling definitions, a bug, or a force majeure could cause your cloud bill to sky rocket unexpectedly. To prevent this, you should always place reasonable maximums on your autoscaling policies to prevent situations like these. What is “reasonable” will differ between companies or even between applications at the same company, but don’t get caught with thousands of dollars in extra cloud spend because you let your cluster scale up to 100 nodes on accident!&lt;/p&gt;
&lt;h3 id=&quot;resource-constraints&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#resource-constraints&quot; aria-label=&quot;resource constraints permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Resource constraints&lt;/h3&gt;
&lt;p&gt;In the last paragraph, I put “infinitely” in quotes. This is more than me just saying that obviously there isn’t infinite computing power. Within your cloud provider, there will be limits that could prevent you from autoscaling, even if you wanted to. I speak mostly in an AWS context, but these are sure to apply to other clouds. Here is a non-comprehensive list of some limits you could run into:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;IP Address exhaustion (Make sure your VPC/subnet CIDRs have enough IPs available!)
&lt;ul&gt;
&lt;li&gt;Every pod in Kubernetes gets its own IP address. Depending on your networking setup, a cluster can easily eat up all the available IPs in your CIDR.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Availability Zone EC2 Capacity
&lt;ul&gt;
&lt;li&gt;As hinted at before, the number of available EC2s running in a given Availability Zone is not infinite. It is possible to try to spin up an EC2 and have AWS reject your request because there isn’t capacity at the current moment.&lt;/li&gt;
&lt;li&gt;It can be useful to be able to use multiple instance types, as sometimes only a specific instance type can be at capacity&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AWS Service limits
&lt;ul&gt;
&lt;li&gt;In part to protect you from unexpected spend, and in part to protect them from people eating up a lot of resources unnecessarily, AWS has &lt;a href=&quot;https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html&quot;&gt;Service Quotas&lt;/a&gt;. If you hit limits on things like Network Interfaces or EC2 Instances, you will have to request a quota increase from AWS.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CPU/Memory
&lt;ul&gt;
&lt;li&gt;If either you can’t or don’t autoscale your cluster, but do autoscale applications within the cluster, you can quickly exhaust the available cluster resources. In that scenario you might then be unable to schedule new pods and/or lower priority pods will be killed so that higher priority pods can continue to run smoothly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Network Throughput
&lt;ul&gt;
&lt;li&gt;If your applications scales up and is serving more and more traffic, you will need to ensure that the path that the traffic takes is also elastic enough to keep up with demand. This might mean needing beefier instances, scaling up load balancers etc so you don’t flood your own network.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m sure there are other nuances and caveats that I haven’t addressed, but these are some major ones that I am aware of or have personally experienced in the past. Keep them in consideration when planning out for a Kubernetes cluster that will involve autoscaling!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[My CLI has been getting a little Rusty]]></title><description><![CDATA[I also made a video version of this post, if you’d rather watch than read. Over the past few years I’ve adopted a handful of various CLI…]]></description><link>https://blog.quigley.codes/useful-cli-tools/</link><guid isPermaLink="false">https://blog.quigley.codes/useful-cli-tools/</guid><pubDate>Mon, 21 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I also made a &lt;a href=&quot;https://youtu.be/Hc4g05Fg5iY&quot;&gt;video version of this post&lt;/a&gt;, if you’d rather watch than read.&lt;/p&gt;
&lt;p&gt;Over the past few years I’ve adopted a handful of various CLI tools that I lean on frequently. Some of them I discovered on my own, some from coworkers, some from discussion topics during &lt;a href=&quot;https://www.meetup.com/NYC-CoffeeOps&quot;&gt;NYC CoffeeOps&lt;/a&gt;, a weekly meetup that I help co-organize. However one thing that I’ve noticed is that all of these tools happen to be written in &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;! Take from that what you will, but regardless of what language they’re written in, these tools are pretty neat, and I’d highly recommend them!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Note: I blatantly stole this idea from someone in the meetup who said this would make a good blog post. Thank you for your wonderful idea.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-tools&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-tools&quot; aria-label=&quot;the tools permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The tools&lt;/h2&gt;
&lt;h3 id=&quot;starship&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#starship&quot; aria-label=&quot;starship permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;starship&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/starship/starship&quot;&gt;Starship&lt;/a&gt; is the prompt I use for my shell. I love that basically with zero configuration, I get a really nice looking shell that integrates with all the tools/languages I use regularly. Alongside oh-my-zsh and iTerm2, it makes for a great terminal aesthetic.&lt;/p&gt;
&lt;h3 id=&quot;lsd&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#lsd&quot; aria-label=&quot;lsd permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;lsd&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Peltoche/lsd&quot;&gt;Lsd&lt;/a&gt; is an alternative to &lt;code class=&quot;language-text&quot;&gt;ls&lt;/code&gt;. I like it because it includes colors and icons to more easily distinguish between types of files and directories&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;insert requisite drug joke here&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;ripgrep&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#ripgrep&quot; aria-label=&quot;ripgrep permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;ripgrep&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/BurntSushi/ripgrep&quot;&gt;Ripgrep&lt;/a&gt; is an alternative to &lt;code class=&quot;language-text&quot;&gt;grep&lt;/code&gt;. It searches text, but does it lightning fast. I once was trying to search a ~200GB dump of hacked usernames/passwords to ensure that none of my accounts had been compromised, and other methods of searching would have taken literal days, but ripgrep did the search in less than a minute.&lt;/p&gt;
&lt;p&gt;Some other pros of ripgrep that I enjoy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Obeys &lt;code class=&quot;language-text&quot;&gt;.gitignore&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Easily searches gzip archives&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I use the latter feature occasionally to search logs automatically put into S3 by AWS. They’re usually categorized by date, so I can pull all the gzipped files for a specific day, search the archives, and only unzip and go into detail on files that match. Big time saver!&lt;/p&gt;
&lt;h3 id=&quot;bat&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#bat&quot; aria-label=&quot;bat permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;bat&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/sharkdp/bat&quot;&gt;bat&lt;/a&gt; bills itself as a ”&lt;code class=&quot;language-text&quot;&gt;cat&lt;/code&gt; clone with wings” The TL;DR on this one is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built in syntax highlighting and line numbers&lt;/li&gt;
&lt;li&gt;Will automatically pipe to &lt;code class=&quot;language-text&quot;&gt;less&lt;/code&gt; if the output is large&lt;/li&gt;
&lt;li&gt;Integration with git to show you if lines have been modified or added in the index&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Need I say more?&lt;/p&gt;
&lt;h3 id=&quot;fd&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#fd&quot; aria-label=&quot;fd permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;fd&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/sharkdp/fd&quot;&gt;fd&lt;/a&gt; is an alternative to &lt;code class=&quot;language-text&quot;&gt;find&lt;/code&gt;. As with basically all of these Rust based tools, one of its biggest pros is that it is super fast. But in addition to that, I like using it because it has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sane defaults. I can just do &lt;code class=&quot;language-text&quot;&gt;fd foo&lt;/code&gt; instead of having to remember &lt;code class=&quot;language-text&quot;&gt;find -name &quot;*foo*&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Color output&lt;/li&gt;
&lt;li&gt;Like &lt;a href=&quot;#ripgrep&quot;&gt;ripgrep&lt;/a&gt;, it ignores things in .gitignore by default&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;mcfly&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#mcfly&quot; aria-label=&quot;mcfly permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;mcfly&lt;/h3&gt;
&lt;p&gt;This one is a hidden gem in my opinion. &lt;a href=&quot;https://github.com/cantino/mcfly&quot;&gt;mcfly&lt;/a&gt; is an alternative to the default history search in your terminal when you press &lt;code class=&quot;language-text&quot;&gt;ctrl-r&lt;/code&gt;. I didn’t even know that was a thing until recently, and had always just used &lt;code class=&quot;language-text&quot;&gt;$ history | grep foo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As with basically all the others, it has a nice color output, and shows a list of options instead of the single one that matches closest to what you’ve typed. Saves you a lot of time compared to grepping history, finding what you’re looking for, and then either copy/pasting, or using the &lt;code class=&quot;language-text&quot;&gt;!{num}&lt;/code&gt; shortcut. (Every entry in your history has a number next to it. If you type &lt;code class=&quot;language-text&quot;&gt;!&lt;/code&gt; and then the number, your shell will rerun the command that was at that number in your history)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Dev Lessons Learned From Factorio]]></title><description><![CDATA[Factorio is one of my all time favorites games all about automation. You create an ever growing factory, with increasing complexity…]]></description><link>https://blog.quigley.codes/dev-lessons-learned-from-factorio/</link><guid isPermaLink="false">https://blog.quigley.codes/dev-lessons-learned-from-factorio/</guid><pubDate>Sat, 15 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://www.factorio.com/&quot;&gt;Factorio&lt;/a&gt; is one of my all time favorites games all about automation. You create an ever growing factory, with increasing complexity, dependencies, and threats. It probably shouldn’t be surprising, and some of these may seem fairly obvious but this game taught me many lessons about development. There is a lot of shared language between this game and development work in general. The lessons I’ve learned are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#refactoring-is-inevitable&quot;&gt;Refactoring is inevitable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#modular-code-and-shared-libraries-will-save-you-a-lot-of-time&quot;&gt;Modular code and shared libraries will save you a lot of time&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#dont-let-perfect-be-the-enemy-of-the-good&quot;&gt;Don’t let perfect be the enemy of the good&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#prioritize-your-work-and-eliminate-bottlenecks&quot;&gt;Prioritize your work and eliminate bottlenecks&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;refactoring-is-inevitable&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#refactoring-is-inevitable&quot; aria-label=&quot;refactoring is inevitable permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Refactoring is inevitable&lt;/h2&gt;
&lt;p&gt;In Factorio, at some point or another, you’re going to refactor the work you’ve done before. You might tear it all up and start fresh or replace it with something else. Or maybe you’ll just upgrade your belts, inserters, and furnaces to the next tier. Theoretically some of your original factory might survive until you win or stop playing, but likely it will be contributing very little, and is probably just in the way.&lt;/p&gt;
&lt;p&gt;In many ways the same can be said of code in large projects. Almost all parts of it will be refactored, rewritten, or upgraded, and that’s okay. It’s even necessary. Keeping code fresh can help improve performance, fix unknown issues, and keep developers familiar with different parts of the code base. I wasn’t able to find a source, but I swear I once saw that at Google, a project’s codebase gets completely rewritten every three to five years. Refactoring for refactoring sake is obviously not what you should be doing, but the point is to not put off refactoring if it is necessary or could help.&lt;/p&gt;
&lt;h2 id=&quot;modular-code-and-shared-libraries-will-save-you-a-lot-of-time&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#modular-code-and-shared-libraries-will-save-you-a-lot-of-time&quot; aria-label=&quot;modular code and shared libraries will save you a lot of time permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Modular code and shared libraries will save you a lot of time&lt;/h2&gt;
&lt;p&gt;In Factorio, there is a blueprint system that allows you to copy/paste parts of your factory. If you’ve managed to research and make construction robots, they’ll even place all the objects for you when you paste. What’s even better is when you create or find blueprints that are “tileable”, meaning you can place them side by side and keep expanding the factory with no additional modifications. As you can imagine, this saves you a lot of time and clicking when constructing your factory.&lt;/p&gt;
&lt;p&gt;There are many ways this lesson applies to code as well. You might write a quick script to automate a step of your regular workflow that saves your team a lot of time. You also might create or use a loosely coupled interface for your logging that allows you to easily use/swap out different logging outputs, such as console output, writing to a file, or dumping logs into Elasticsearch. Small productivity wins can really compound to save you a lot of time. If you spend two hours automating a task that normally takes you 30 seconds, but it’s something everyone on your team of five does twice a day, you’ll make up the time in less than a month. If it’s a task that takes five minutes a day, you’ll make up the time in 3 days.&lt;/p&gt;
&lt;h2 id=&quot;dont-let-perfect-be-the-enemy-of-the-good&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#dont-let-perfect-be-the-enemy-of-the-good&quot; aria-label=&quot;dont let perfect be the enemy of the good permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Don’t let perfect be the enemy of the good&lt;/h2&gt;
&lt;p&gt;So often in Factorio I found myself trying to make a perfect ratio setup that would be optimized to consume 100% of the input and ensure a constant steady flow of maximum output. However I’d take so long trying to make this perfect setup that a different part of my factory would turn into a larger issue and get neglected, eventually causing more problems. If instead I had just gotten the new setup working 50%, I could have dealt with the other parts of the factory and come back to optimize later on.&lt;/p&gt;
&lt;p&gt;This pops up all the time when you have competing priorities when working on a product or feature. Someone will want to do the best job and make it the most efficient they possibly can. Someone else will want the feature out the door ASAP. Find your happy medium. Don’t deliver something broken, but don’t hold back others or neglect larger problems by trying to squeeze every ounce of performance possible out of your code, unless that’s something that’s explicitly needed. Come back and refactor in the future (see point one about &lt;a href=&quot;#refactoring-is-inevitable&quot;&gt;refactoring&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id=&quot;prioritize-your-work-and-eliminate-bottlenecks&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#prioritize-your-work-and-eliminate-bottlenecks&quot; aria-label=&quot;prioritize your work and eliminate bottlenecks permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Prioritize your work and eliminate bottlenecks&lt;/h2&gt;
&lt;p&gt;In line with the last point, in Factorio it’s really important to find what your current biggest issue or bottleneck is and address that first. It doesn’t make sense to scale up the production of green circuits when you’re not even maximizing current production because you don’t have enough copper wire to support the throughput needed. If you do, you’ll just have a bunch of assembling machines sitting idle, waiting for input resources.&lt;/p&gt;
&lt;p&gt;This applies to so many things in software. I’ve been guilty of this myself, where I spend way too much time optimizing a system that doesn’t even need it, or making a feature that nobody wants. That time would be much better spent working on an issue that is actually affecting users, or on making a troubled system more scalable. This is where having monitoring of various kinds comes in handy. What actions are your users taking most often? Where is your application having performance problems? Spend time there instead of elsewhere.&lt;/p&gt;
&lt;p&gt;Finding bottlenecks can have huge benefits to your team. If you don’t eliminate bottlenecks, eventually there will be a backup of work in front of the bottleneck. The more you keep things the same, the more things will backup. Map out your value stream and figure out where things are getting held up. Stop piling more things into the backup, and instead spend time helping things get through the bottleneck, or even improving the throughput of the systems. As an example, maybe you have a QA team that manually reviews every ticket that gets completed. When they first started, most tickets got completed in the same day, but over time, a larger and larger backlog of tickets has piled up. Now it can take upwards of two to three weeks for tickets to get reviewed. If the status quo continues, things will only continue to get worse. You may feel really productive, since you “complete” and pass on more tickets to QA than the rest of your team, but really you’re just exacerbating the problem! Your team should prioritize changing or improving the processes around QA to improve throughput. Can you automate tasks? Have developers rotate in to help out on QA?&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Shamir's Secret Sharing]]></title><description><![CDATA[When I was a kid, I had the opportunity to tour the Titan II Missile Museum in Arizona. It’s the last of the 54 silos across the U.S. that…]]></description><link>https://blog.quigley.codes/shamirs-secret-sharing/</link><guid isPermaLink="false">https://blog.quigley.codes/shamirs-secret-sharing/</guid><pubDate>Fri, 15 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I was a kid, I had the opportunity to tour the &lt;a href=&quot;https://titanmissilemuseum.org/&quot;&gt;Titan II Missile Museum in Arizona&lt;/a&gt;. It’s the last of the 54 silos across the U.S. that hasn’t been destroyed or filled in, and instead was turned into a museum for the public to learn about the history of the Cold War and how these silos operated. In part of the tour of the museum, they show you the control room, and mock out what would have happened if the silo had ever received the command to launch. One step of the process is that two separate individuals have to insert a key into panels on opposite sides of the room and turn them at the same time, ensuring that a launch could not be completed by a single individual (unless you’re Mrs. Incredible).&lt;/p&gt;
&lt;p&gt;There are a few situations where the stakes are so high that we don’t want to trust a single person to have the full power to make a decision or act unilaterally. Broadly, this is referred to as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Two-man_rule&quot;&gt;Two-person rule&lt;/a&gt;, and has lots of uses. The nuclear launch two key setup is just a single example of that rule in action, but it is used in banking, hazardous materials handling, aircraft piloting, and more.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In cryptography, the two-person rule can be enforced using Shamir’s Secret Sharing (SSS), a mathematical algorithm that reconstructs a secret by bringing together multiple parts (Adi Shamir is a famous cryptographer known for creating SSS and being one of the three creators of the RSA public key encryption scheme). SSS even has the ability to not just split into two, but can split a secret into any number of parts and can require a different number of those parts to be present to recreate the whole. &lt;a href=&quot;https://www.vaultproject.io/&quot;&gt;Hashicorp’s Vault&lt;/a&gt;, a solution for securing and storing secrets, tokens, passwords, etc., supports using SSS to unseal the Vault. By default, Vault will generate 5 keys and requires at least 3 to be provided in order to unseal the Vault. This means that if you give each of the keys to a different person, it would require 3/5ths of the group to agree to unseal the Vault. No one or even two people could do it on their own.&lt;/p&gt;
&lt;p&gt;The general principle of SSS relies on some basic concepts in math. To define a line, you need two points, (1,2) (3,7) for example. With only one of these points, there are an infinite number of lines that pass through the single point. For a parabola, you need three points. Four points for a cubic curve and so on. For a secret split into &lt;em&gt;n&lt;/em&gt; parts where you require &lt;em&gt;k&lt;/em&gt; pieces to be present to recreate the secret, SSS essentially generates a polynomial of degree &lt;em&gt;k - 1&lt;/em&gt;, and then chooses &lt;em&gt;n&lt;/em&gt; random points on the curve to distribute as the parts.&lt;/p&gt;
&lt;p&gt;Let’s say like Vault, you want to generate &lt;em&gt;n&lt;/em&gt; keys (in our case 5), and require &lt;em&gt;k&lt;/em&gt; (in our case 3) of them to be present to recreate the original secret. SSS would use the original Vault encryption key as part of the curve, and then generate a random parabola (&lt;em&gt;ax^2 + bx + c&lt;/em&gt;). Then it will randomly pick 5 points on that curve. This is a simplification of the math, especially since it doesn’t actually use basic integers, but rather a finite field. But since that’s over my head, it’s much easier to conceptualize using the simpler algebra you might have learned in school.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;I find this algorithm insanely cool. I don’t know if there are any mystery novels out there that have SSS as a basis, but you could easily have a Knives Out style drama where the genius computer millionaire dies, but secretly leaves their children each a part of the secret, and enough of them have to agree to unlock their inheritance. Or maybe a spy novel where the latitude and longitude coordinates of spots on the globe represent the coordinates of the polynomial curve and can be used to save the world.&lt;/p&gt;
&lt;p&gt;One downside to SSS is that when contributing the parts of the secret to try to recreate the whole, there is no way to verify that a part is valid. Meaning someone could contribute fake data and either prevent the reconstruction of the original secret, or even make the reconstructed data be something else entirely. I think this plays well in my spy novel idea, where an unexpected betrayal happens and a double agent is revealed. This whole concept is a Dan Brown novel just waiting to happen.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Node 14 New JavaScript Feature Spotlight]]></title><description><![CDATA[Node.js version 14 was released recently, and will become active under Long Term Support (LTS) version in fall of 2020 (October 20th to be…]]></description><link>https://blog.quigley.codes/node-14-js-features/</link><guid isPermaLink="false">https://blog.quigley.codes/node-14-js-features/</guid><pubDate>Mon, 27 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Node.js version 14 was released recently, and will become active under Long Term Support (LTS) version in fall of 2020 (October 20th to be specific). There are a handful of changes, but to the average developer, I think a few are worth highlighting as they might change the JavaScript that gets read and written.&lt;/p&gt;
&lt;h3 id=&quot;nullish-coalescing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nullish-coalescing&quot; aria-label=&quot;nullish coalescing permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nullish Coalescing&lt;/h3&gt;
&lt;p&gt;Nullish Coalescing is similar to the &lt;code class=&quot;language-text&quot;&gt;||&lt;/code&gt; operator, but it only returns the right hand value when the left hand side is nullish, instead of falsy.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Zero is considered falsy and therefore
 * the right hand side value is returned
 * when using the `||` operator
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;oops&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;oops&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; bar &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;oops&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;oops&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Zero is not considered nullish
 * and therefore is returned when on
 * the left hand side of the `??` operator
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; baz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;oops&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 0&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; buzz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;oops&quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;oops&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id=&quot;falsy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#falsy&quot; aria-label=&quot;falsy permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Falsy&lt;/h4&gt;
&lt;p&gt;Falsy is a term that means a value that is considered to be false when treated as a boolean. In JavaScript, the following values are falsy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;NaN&lt;/code&gt; (Not a number)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;-0&lt;/code&gt; (yes that’s right, negative zero)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;0n&lt;/code&gt; (BigInt zero)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;&quot;&quot;&lt;/code&gt; (the empty string)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;false&lt;/code&gt; (You’d really hope)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These values being falsy can be simultaneously convenient, but also a pain if forgotten. It is common in JavaScript to pass a non-boolean value to an &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; statement, and let JavaScript check if the value is truthy or falsy. But if you unintentionally pass in &lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;&quot;&quot;&lt;/code&gt;, you might encounter unexpected behavior.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is why passing unsanitized input directly to an &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt; to check for the presence of value is an issue&lt;/p&gt;
&lt;h4 id=&quot;nullish&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#nullish&quot; aria-label=&quot;nullish permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Nullish&lt;/h4&gt;
&lt;p&gt;Similar to falsy, there are multiple values that are considered nullish. These values are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;undefined&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means that these values are both nullish &lt;em&gt;and&lt;/em&gt; falsy.&lt;/p&gt;
&lt;h3 id=&quot;optional-chaining&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#optional-chaining&quot; aria-label=&quot;optional chaining permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Optional Chaining&lt;/h3&gt;
&lt;p&gt;Optional Chaining is a new feature that allows you to reference a field nested within several objects, but without having to check that each object isn’t nullish.&lt;/p&gt;
&lt;p&gt;Let’s take the following object as an example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; users &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;Jack&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;phone&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;(123) 456-7890&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;street&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;6732 Main St&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;12345&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Notice jill has no address&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;Jill&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;phone&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;(349) 233-2348&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In the past, if we wanted to get the zip code, we would have done something like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; jack &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;jack&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; address &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zip &lt;span class=&quot;token comment&quot;&gt;// &quot;12345&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zip &lt;span class=&quot;token comment&quot;&gt;// &quot;12345&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or if you really want to do it in one line:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;address&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;zip&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of these are valid, but pretty verbose. With optional chaining you can now do the same thing still in one line, and without the use of &lt;code class=&quot;language-text&quot;&gt;if&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;, and without repeating any fields:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;address&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;zip &lt;span class=&quot;token comment&quot;&gt;// &quot;12345&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;?.&lt;/code&gt; replaces plain old &lt;code class=&quot;language-text&quot;&gt;.&lt;/code&gt; and short circuits if the value is nullish. In the above example, Jack has an address and a zip, but Jill doesn’t. To check for Jill’s zip code, its the same thing:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; zip &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jill&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;address&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;zip &lt;span class=&quot;token comment&quot;&gt;// undefined&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you tried this line without the &lt;code class=&quot;language-text&quot;&gt;?.&lt;/code&gt; operator, it would throw an error!&lt;/p&gt;
&lt;p&gt;One of the great things about Optional Chaining is that it works with just about everything. Not just object properties, but also arrays and function calls too.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;asyncHelloCallback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; callback&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; helloString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Hello, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;helloString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// If callback is undefined, there&apos;s no error&lt;/span&gt;
    callback&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;helloString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getFifthElement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Doesn&apos;t throw an error if arr is undefined&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; arr&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;combining-optional-chaining-and-nullish-coalescing&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#combining-optional-chaining-and-nullish-coalescing&quot; aria-label=&quot;combining optional chaining and nullish coalescing permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Combining Optional Chaining and Nullish Coalescing&lt;/h3&gt;
&lt;p&gt;Combined, these two features can be quite the powerhouse.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Check for value and provide a default if Nullish&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; middleName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; users&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Jack&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;middleName &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; quantity &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; order&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;quantity &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * Use multiple nullish coalescing and
 * optional chaining operators to check
 * several values before providing a default
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; userNames &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;John&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;middle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Doe&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Smith&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;middle&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;defaultName&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt;
  user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;first &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;last &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; user&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;?.&lt;/span&gt;middle &lt;span class=&quot;token operator&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Unknown&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// [ &apos;John&apos;, &apos;Smith&apos;, &apos;A&apos;, &apos;Unknown&apos; ]&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; defaultNames &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; userNames&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;defaultName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Frustrations without static types]]></title><description><![CDATA[Recently I was working on a piece of my company’s Python code base that I hadn’t touched before. It was part of an automation script that…]]></description><link>https://blog.quigley.codes/static-types/</link><guid isPermaLink="false">https://blog.quigley.codes/static-types/</guid><pubDate>Mon, 13 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently I was working on a piece of my company’s Python code base that I hadn’t touched before. It was part of an automation script that makes some API calls to GitHub using the &lt;a href=&quot;https://2.python-requests.org/en/master/&quot;&gt;Requests&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;I needed to check some of the parameters on the response, run some different functions based on the response code and various other checks. But without static types, there was no easy way to know exactly what parameters the response object had. Surely it had a status code of some kind right? But was it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;response.code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;response.status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;response.statusCode&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;response.status_code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;response.statuscode&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without static types there was no easy way for me to know. Even if I happened to remember that for this specific library the answer is &lt;code class=&quot;language-text&quot;&gt;response.status_code&lt;/code&gt;, is it a number? Is it a string? What about other values on the response? In order to figure all this out, I had to dig into the docs and source code of the requests library.&lt;/p&gt;
&lt;p&gt;Python has a lot of benefits, and I use it daily, but static typing is not definitely not one of them. With one of any of the many statically typed languages and a decent IDE or text editor, I would have been able to write the checks that I needed without having to do any external investigation. In my spare time I’ve been working on a little bit of Go, and the presence of static types is a breath of fresh air from the Python that I write at work, and the JavaScript that I used at my previous job.&lt;/p&gt;
&lt;p&gt;Clearly static types are not the only thing to consider when picking a language, but this is a clear, albeit simple, example of some frustrations of when you don’t have them.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Environment Variables]]></title><description><![CDATA[Inspiration I was inspired to write the post by an acquaintance who is new to the software industry. They couldn’t find any good resources…]]></description><link>https://blog.quigley.codes/environment-variables/</link><guid isPermaLink="false">https://blog.quigley.codes/environment-variables/</guid><pubDate>Fri, 03 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;inspiration&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#inspiration&quot; aria-label=&quot;inspiration permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Inspiration&lt;/h2&gt;
&lt;p&gt;I was inspired to write the post by an acquaintance who is new to the software industry. They couldn’t find any good resources on environment variables that covered everything in one place. They wanted to know things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#what-are-environment-variables&quot;&gt;What are environment variables?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#what-kind-of-things-should-be-in-environment-variables&quot;&gt;What kind of things should be in environment variables?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#how-can-i-set-environment-variables&quot;&gt;How can I set environment variables?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#how-can-i-read-environment-variables&quot;&gt;How can I read environment variables?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#environment-variables-and-secrets&quot;&gt;Do only secret things go in them?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#environment-variables-and-secrets&quot;&gt;How do I securely share them?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hopefully this post can become a kind of one stop shop for an introduction into environment variables.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;what-are-environment-variables&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-are-environment-variables&quot; aria-label=&quot;what are environment variables permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What are Environment Variables?&lt;/h2&gt;
&lt;p&gt;Environment variables, commonly referred to as env vars, are variables available to a process that are a part of the environment where the process runs. Lazy to define the word with the word, so let’s break it down a little bit more.&lt;/p&gt;
&lt;p&gt;A variable represents a value that can change. An environment variable typically represents a value set from outside the application, and exists as a part of system that is running the application. Even if you’re not aware of it, every time you use your computer, environment variables are impacting the applications you run. The browser that you are reading this blog post on probably uses hundreds of them. Some common examples are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;PATH&lt;/code&gt; (When you open a terminal and type a command, where should it look for the executable you are trying to run)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;HOME&lt;/code&gt; (The home directory for the current user)&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;ENVIRONMENT&lt;/code&gt; (commonly used to say either “development” or “production” to specify where the app is running.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Env vars keys by convention are written in all capital snake case, meaning multiple words in the key are separated by underscores. The value is a string. E.g.&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;THIS_IS_A_VAR_NAME=foobar&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Environment variables exist within your system whether or not you use them in your applications. If you open a terminal and type the following, you’ll see the content of the environment variable &lt;code class=&quot;language-text&quot;&gt;PATH&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Mac OS/Linux&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;sh&quot;&gt;&lt;pre class=&quot;language-sh&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token environment constant&quot;&gt;$PATH&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Windows&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cmd&quot;&gt;&lt;pre class=&quot;language-cmd&quot;&gt;&lt;code class=&quot;language-cmd&quot;&gt;echo %PATH%&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;what-kind-of-things-should-be-in-environment-variables&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-kind-of-things-should-be-in-environment-variables&quot; aria-label=&quot;what kind of things should be in environment variables permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What kind of things should be in environment variables?&lt;/h2&gt;
&lt;p&gt;There are many environment variables that will be set automatically by the system, but you can also set environment variables yourself specific to your application. Commonly you would set things that change based on where the app is running. These might be things such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Database credentials&lt;/li&gt;
&lt;li&gt;Whether your app is running in Dev/Prod&lt;/li&gt;
&lt;li&gt;What port your web application should run on&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;#environment-variables-and-secrets&quot;&gt;Some environment variables are secret and sensitive&lt;/a&gt;, like your database credentials. Others, like the port or dev/prod flag are not.&lt;/p&gt;
&lt;h2 id=&quot;how-can-i-set-environment-variables&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-can-i-set-environment-variables&quot; aria-label=&quot;how can i set environment variables permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How can I set environment variables?&lt;/h2&gt;
&lt;p&gt;Ah the tried and true answer: “It depends”&lt;/p&gt;
&lt;p&gt;In Unix based systems, like Linux or Mac OS, environment variables can be set for every shell session, the current shell session only, or exclusively for a single command:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Can be set for the shell session automatically (.bashrc/.zshrc etc)&lt;/li&gt;
&lt;li&gt;Can be set temporarily manually &lt;code class=&quot;language-text&quot;&gt;export MY_VAR=foo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Can be set for a single command &lt;code class=&quot;language-text&quot;&gt;MY_VAR=foo ls&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On Windows things are a little bit different. You can set in the environment variables settings for either the whole system or just current user, or in the terminal, use the command &lt;code class=&quot;language-text&quot;&gt;SET MY_VAR=foo&lt;/code&gt;. It’s different again if you’re using Powershell.&lt;/p&gt;
&lt;p&gt;It is important to note that processes inherit the environment variables of their parent processes. However if all you need is to set some environment variables for your application, a very common convention is to put key value pairs in a a file called &lt;code class=&quot;language-text&quot;&gt;.env&lt;/code&gt; (pronounced: “dot ee en vee”. Or at least that’s how I say it) that lives alongside your project files, but is &lt;strong&gt;not committed to git&lt;/strong&gt;. Many frameworks will automatically read from this file if it exists and set the environment variables for your process. If you aren’t using a framework that does this, many languages have libraries (usually called ”&lt;a href=&quot;https://www.npmjs.com/package/dotenv&quot;&gt;dotenv&lt;/a&gt;” or something similar) that will do the same. Some teams will have multiple &lt;code class=&quot;language-text&quot;&gt;.env&lt;/code&gt; files with different content, and might prefix them with their intended use, like &lt;code class=&quot;language-text&quot;&gt;sample.env&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;test.env&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;dev.env&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A common question is how to properly set environment variables when running in CI systems like GitHub Actions or CircleCI. These systems run your build/test/deploy steps in their own isolated, ephemeral (temporary) container, and therefore they might lack some of the same environment variables that you have on your local development environment, and have many extras that you don’t. You should read into the docs of your CI system to see how to properly set environment variables and figure out which ones are already made available to you.&lt;/p&gt;
&lt;h2 id=&quot;how-can-i-read-environment-variables&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#how-can-i-read-environment-variables&quot; aria-label=&quot;how can i read environment variables permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;How can I read environment variables?&lt;/h2&gt;
&lt;p&gt;Here’s a smattering of examples of how to read environment variables in a few programming languages:&lt;/p&gt;
&lt;p&gt;JavaScript:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;javascript&quot;&gt;&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;process&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;env&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;MY_VAR&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Using JavaScript fun, to provide a default you can use&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;process.env.MY_VAR || &quot;some default value&quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Python:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; os
os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;environ&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MY_VAR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;os.environ&lt;/code&gt; returns a dict. Python dicts raise a &lt;code class=&quot;language-text&quot;&gt;KeyError&lt;/code&gt; if you try to access a key that doesn’t exist, so it tends to be better to actually do something like &lt;code class=&quot;language-text&quot;&gt;os.environ.get(&quot;MY_VAR&quot;, &quot;some default value&quot;)&lt;/code&gt; to prevent that situation.&lt;/p&gt;
&lt;p&gt;Go&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;go&quot;&gt;&lt;pre class=&quot;language-go&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;os&quot;&lt;/span&gt;
os&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;Getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MY_VAR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unlike other languages, Go returns an empty string if the key doesn’t exist. Make sure to take that into consideration!&lt;/p&gt;
&lt;p&gt;Java&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;java&quot;&gt;&lt;pre class=&quot;language-java&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MY_VAR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;getenv()&lt;/code&gt; returns a &lt;code class=&quot;language-text&quot;&gt;Map&amp;lt;String, String&gt;&lt;/code&gt;, and therefore a get for a key that doesn’t exist returns &lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Rust&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;rust&quot;&gt;&lt;pre class=&quot;language-rust&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;token namespace&quot;&gt;env&lt;span class=&quot;token punctuation&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;MY_VAR&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Because it’s Rust, &lt;code class=&quot;language-text&quot;&gt;env::var&lt;/code&gt; returns Result that could contain an &lt;code class=&quot;language-text&quot;&gt;Ok&lt;/code&gt; variant or an &lt;code class=&quot;language-text&quot;&gt;Err&lt;/code&gt; variant. You’ll need to handle that with either an &lt;code class=&quot;language-text&quot;&gt;expect&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;unwrap&lt;/code&gt;, or &lt;code class=&quot;language-text&quot;&gt;is_err&lt;/code&gt; on the Result.&lt;/p&gt;
&lt;p&gt;If the value doesn’t exist, languages do different things. Some return undefined (JavaScript). Others throw an error. Whatever language you are using, make sure you properly handle the case where the value does not exist!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;environment-variables-and-secrets&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#environment-variables-and-secrets&quot; aria-label=&quot;environment variables and secrets permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Environment Variables and Secrets&lt;/h2&gt;
&lt;p&gt;Not all environment variables are secrets! Many of them are totally fine to share, post publicly etc. However, some of them inevitably will be sensitive. As soon as you introduce a database, the credentials to that database will likely be set as environment variables and need to be kept secret. However secrets don’t &lt;em&gt;have&lt;/em&gt; to be environment variables. There are other options too:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Encrypted files (fun fact: Kubernetes “secrets” aren’t actually encrypted by default. Just base64 encoded. You have to add the &lt;a href=&quot;https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/&quot;&gt;encryption at rest&lt;/a&gt; by yourself.)&lt;/li&gt;
&lt;li&gt;Fetched from some external secret store (&lt;a href=&quot;https://www.vaultproject.io/&quot;&gt;Hashicorp Vault&lt;/a&gt;, &lt;a href=&quot;https://aws.amazon.com/secrets-manager/&quot;&gt;AWS Secrets Manager&lt;/a&gt;, etc)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You will need to find the option that best suits you and your organization while still maintaining security best practices.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don’t share secrets in Slack. Please. Just don’t.&lt;/strong&gt; Use one of the myriad of options for sharing things securely:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://gnupg.org/&quot;&gt;GPG&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Password Managers (&lt;a href=&quot;https://1password.com/&quot;&gt;1Password&lt;/a&gt;, &lt;a href=&quot;https://www.lastpass.com/&quot;&gt;LastPass&lt;/a&gt;, &lt;a href=&quot;https://bitwarden.com/&quot;&gt;BitWarden&lt;/a&gt;, etc)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://send.firefox.com/&quot;&gt;Firefox Send&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.sendsafely.com/&quot;&gt;Send Safely&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.signal.org/&quot;&gt;Signal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Use one of the above secret stores (Vault, Secrets Manager)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m sure there are a million other options I didn’t include. This is just a few one of the ones I’m familiar with.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-if-i-really-want-to-commit-my-secrets-to-git&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-if-i-really-want-to-commit-my-secrets-to-git&quot; aria-label=&quot;what if i really want to commit my secrets to git permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What if I really want to commit my secrets to git?&lt;/h3&gt;
&lt;p&gt;I really don’t recommend it, but if you absolutely must, you should at least use &lt;a href=&quot;https://github.com/AGWA/git-crypt&quot;&gt;git-crypt&lt;/a&gt; or something similar so the file is encrypted!&lt;/p&gt;
&lt;h3 id=&quot;what-if-i-really-want-to-just-put-the-secret-in-a-slack-message&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#what-if-i-really-want-to-just-put-the-secret-in-a-slack-message&quot; aria-label=&quot;what if i really want to just put the secret in a slack message permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;What if I really want to just put the secret in a Slack message?&lt;/h3&gt;
&lt;p&gt;It’s just so easy to quickly send it over right? And you’ll definitely delete the message right after the person has a chance to copy it, right? There’s &lt;em&gt;no way&lt;/em&gt; anybody might somehow get a hold of that secret, and you totally trust Slack that your messages will never be lost or read by someone else!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BAD!! STOP IT!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Seriously people, don’t do this!! There are so many good ways to send things securely, so stop posting plain text secrets in Slack, no matter how badly you want to. No matter how much of a rush you’re in. No matter how lazy you are.&lt;/p&gt;
&lt;p&gt;Right now go download Signal and make an account. Go generate a GPG key pair and post your public key so people can send you encrypted messages. Do something encrypted. Anything! Just please don’t post it in plain text in Slack.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Merging and Overriding IAM Policies in Terraform]]></title><description><![CDATA[TL;DR Use the  and/or  attributes on a Terraform . Summary When creating IAM policies in AWS, it can be really easy to either: Give things…]]></description><link>https://blog.quigley.codes/merging-iam-in-terraform/</link><guid isPermaLink="false">https://blog.quigley.codes/merging-iam-in-terraform/</guid><pubDate>Mon, 30 Mar 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;tldr&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tldr&quot; aria-label=&quot;tldr permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Use the &lt;code class=&quot;language-text&quot;&gt;source_json&lt;/code&gt; and/or &lt;code class=&quot;language-text&quot;&gt;override_json&lt;/code&gt; attributes on a Terraform &lt;code class=&quot;language-text&quot;&gt;aws_iam_policy_document&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;hcl&quot;&gt;&lt;pre class=&quot;language-hcl&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data &lt;span class=&quot;token type variable&quot;&gt;&quot;aws_iam_policy_document&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;source_json&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; data.aws_iam_policy_document.bar.json
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# OR&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;data &lt;span class=&quot;token type variable&quot;&gt;&quot;aws_iam_policy_document&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;buzz&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;override_json&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; data.aws_iam_policy_document.fizz.json
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;p&gt;When creating IAM policies in AWS, it can be really easy to either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Give things way too many permissions because you’re lazy and don’t want to repeat yourself&lt;/li&gt;
&lt;li&gt;End up repeating things a lot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When using Terraform, you can get the best of both worlds by merging disparate policy documents to both avoid repeating yourself and limit permissions. This capability is especially useful when creating modules or useful base policies. You could create a base policy that enforces the best practices of your organization and use that as the &lt;code class=&quot;language-text&quot;&gt;source_json&lt;/code&gt; on every &lt;code class=&quot;language-text&quot;&gt;aws_iam_policy_document&lt;/code&gt;. Or if there is already a policy document in place, but you want to override specific statements, you can do that too!&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;could&lt;/em&gt; accomplish some of the same things with plain JSON in a heredoc and some string interpolation, but I’ve found it to be much simpler to actually use the policy document data source.&lt;/p&gt;
&lt;h3 id=&quot;source-vs-override&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#source-vs-override&quot; aria-label=&quot;source vs override permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Source vs. Override&lt;/h3&gt;
&lt;p&gt;The difference between &lt;code class=&quot;language-text&quot;&gt;source_json&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;override_json&lt;/code&gt; is a question of which of the two policies you want to take priority. When using &lt;code class=&quot;language-text&quot;&gt;source_json&lt;/code&gt;, the source is imported, and the current policy document will override anything in the source with a matching statement ID. When using &lt;code class=&quot;language-text&quot;&gt;override_json&lt;/code&gt;, the current policy document is overridden by the imported policy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that statement IDs (sid) have to match in order to actually override any statements. Otherwise they will be merged.&lt;/p&gt;
&lt;h2 id=&quot;examples&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#examples&quot; aria-label=&quot;examples permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Examples&lt;/h2&gt;
&lt;p&gt;Given the following policy document, let’s look at a practical example of &lt;code class=&quot;language-text&quot;&gt;source_json&lt;/code&gt; versus &lt;code class=&quot;language-text&quot;&gt;override_json&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;hcl&quot;&gt;&lt;pre class=&quot;language-hcl&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data &lt;span class=&quot;token type variable&quot;&gt;&quot;aws_iam_policy_document&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Allows reading from all buckets&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;statement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;sid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;s3:GetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Allow put object in &quot;some-bucket&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;statement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;sid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2&quot;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;s3:PutObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::some-bucket/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;using-source_json&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-source_json&quot; aria-label=&quot;using source_json permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using source_json&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;hcl&quot;&gt;&lt;pre class=&quot;language-hcl&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data &lt;span class=&quot;token type variable&quot;&gt;&quot;aws_iam_policy_document&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;source_json&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; data.aws_iam_policy_document.a.json&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Allows reading from a specific bucket&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;statement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;sid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;s3:GetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::some-bucket/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Allows put object in &quot;a-different-bucket&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;statement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;sid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3&quot;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;s3:PutObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::a-different-bucket/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Final output for &quot;b&quot; is GetObject only for &quot;some-bucket&quot;, but PutObject on both &quot;some-bucket&quot; and &quot;a-different-bucket&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id=&quot;using-override_json&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#using-override_json&quot; aria-label=&quot;using override_json permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Using override_json&lt;/h3&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;hcl&quot;&gt;&lt;pre class=&quot;language-hcl&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;data &lt;span class=&quot;token type variable&quot;&gt;&quot;aws_iam_policy_document&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token property&quot;&gt;override_json&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; data.aws_iam_policy_document.a.json&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Allows reading from a specific bucket&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;statement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;sid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1&quot;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;s3:GetObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::some-bucket/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# Allows put object in &quot;a-different-bucket&quot;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;statement&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;sid&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;3&quot;&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;actions&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;s3:PutObject&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;resources&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;arn:aws:s3:::a-different-bucket/*&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Final output for &quot;b&quot; is GetObject for all buckets, and PutObject on both &quot;some-bucket&quot; and &quot;a-different-bucket&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href=&quot;https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html#source_json&quot;&gt;Terraform Docs&lt;/a&gt; for more information.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Rotating Docker Logs — Keeping your overlay folder small]]></title><description><![CDATA[TL;DR Learn from my mistakes. If you are using the default json-file driver, configure  and  options to have Docker automatically rotate and…]]></description><link>https://blog.quigley.codes/rotating-docker-logs/</link><guid isPermaLink="false">https://blog.quigley.codes/rotating-docker-logs/</guid><pubDate>Tue, 14 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;tldr&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tldr&quot; aria-label=&quot;tldr permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Learn from my mistakes. If you are using the default json-file driver, configure &lt;code class=&quot;language-text&quot;&gt;max-file&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;max-size&lt;/code&gt; options to have Docker automatically rotate and remove old logs.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-problem&quot; aria-label=&quot;the problem permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Problem&lt;/h2&gt;
&lt;p&gt;4:30 pm. Time to go home, figure something out for dinner, relax and — — THE BUILDS ARE FAILING. Classic.&lt;/p&gt;
&lt;p&gt;Can’t push or pull to our self-hosted registry. The container is running, so why would it not be able to read/write to the disk unless…the disk is full?&lt;/p&gt;
&lt;p&gt;After some quick digging, turns out the Docker overlay folder is big. Like almost 200 GB big. But a quick glance shows that we only have 4 images and a few small volumes, so why would that overlay folder be so big?&lt;/p&gt;
&lt;p&gt;The answer: logs. a LOT of logs.&lt;/p&gt;
&lt;h2 id=&quot;the-fix&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-fix&quot; aria-label=&quot;the fix permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Fix&lt;/h2&gt;
&lt;p&gt;By default, Docker uses the json-file log driver and saves those logs in the overlay folder. Docker doesn’t limit the size of the files or how many log files there can be for a single container. If you continue to run that container, the log file will grow as long as it has drive space to do so. Thankfully, it’s pretty easy to set these limits.&lt;/p&gt;
&lt;p&gt;If you are running from the CLI, your option looks like:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This sets a maximum of five log files with a max size of 10 Mb each. So at most 50 Mb of logs for that container. Tune those numbers as you see fit.&lt;/p&gt;
&lt;p&gt;If you are using docker-compose, your options should look like:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;my-app&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; my&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;app&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;latest
    &lt;span class=&quot;token key atrule&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;json-file&quot;&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;max-file&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;max-size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 10m&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also configure this as a default in your daemon settings &lt;a href=&quot;https://docs.docker.com/config/containers/logging/configure/#configure-the-logging-driver-for-a-container&quot;&gt;https://docs.docker.com/config/containers/logging/configure/#configure-the-logging-driver-for-a-container&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[MongoDB Atlas Is Awesome]]></title><description><![CDATA[MongoDB is really fast and easy to get setup with, and therefore is a favorite for many developers who want to get a running start into…]]></description><link>https://blog.quigley.codes/mongodb-atlas-is-awesome/</link><guid isPermaLink="false">https://blog.quigley.codes/mongodb-atlas-is-awesome/</guid><pubDate>Mon, 28 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;MongoDB is really fast and easy to get setup with, and therefore is a favorite for many developers who want to get a running start into their new application. However, because of this, many developers don’t take the time to set up replica sets (that provide high availability (HA) and automatic failover) or role based access control (RBAC). For local development, this might not be necessary, but when working in a team environment, or whenever you have a publicly accessible MongoDB instance, these should be required. And there really is no excuse to NOT have it.&lt;/p&gt;
&lt;p&gt;Atlas is a service by the creators of MongoDB that provisions and creates a MongoDB cluster with a replica set, users with RBAC and encryption at the click of a button for free. It also provides metrics and alerts for your cluster. Now the free tier only gets you 512 MB of storage, but this should be plenty for your development environment. Once you get to production, upgrade that same cluster to handle the load of your production application. You might decide to setup your own production environment in order to avoid the premium cost, but for the rapidly working developer, the free tier is amazing.&lt;/p&gt;
&lt;p&gt;I just recently discovered Atlas, and I will never waste my time trying to setup my own development environment again. So far it has “just worked”, and when trying to develop quickly, that goes a long way.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Specifying npm Version in Dockerfile]]></title><description><![CDATA[TL;DR Details Each Node.js version ships with npm. Currently the LTS Node version (v6.11.2) ships with npm v3.10.10. But what if you want to…]]></description><link>https://blog.quigley.codes/specifying-npm-version-in-dockerfile/</link><guid isPermaLink="false">https://blog.quigley.codes/specifying-npm-version-in-dockerfile/</guid><pubDate>Mon, 21 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;tldr&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#tldr&quot; aria-label=&quot;tldr permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;TL;DR&lt;/h2&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; npm i npm&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; mv node_modules/npm /usr/local/lib/node_modules/npm&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; rm -rf /usr/local/lib/node_modules/npm&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;details&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#details&quot; aria-label=&quot;details permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Details&lt;/h2&gt;
&lt;p&gt;Each Node.js version ships with npm. Currently the LTS Node version (v6.11.2) ships with npm v3.10.10. But what if you want to use the latest features of npm 5.x.x with an older version of Node?&lt;/p&gt;
&lt;p&gt;Outside of a container, this is simple. You install the Node version that you want (use nvm to easily swap between them) and then specify npm version.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; npm@5.3.0 //specific version
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt;       //for latest&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Doing this inside a container, while possible, is a little bit trickier. You declare the version of Node you want to use with the “FROM” command.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; node:boron&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;But this comes with an old version of npm. If you try to upgrade as you normally would, you’ll run into an issue where the package “semver” can’t be found. The npm installation is bad. The solution:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;dockerfile&quot;&gt;&lt;pre class=&quot;language-dockerfile&quot;&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; npm install npm@5.3.0&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; rm -rf /usr/local/lib/node_modules/npm&lt;/span&gt;
&lt;span class=&quot;token instruction&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;RUN&lt;/span&gt; mv node_modules/npm /usr/local/lib/node_modules/npm&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Install npm in the project, remove the global package, then move the local package to your global location. Now you have the Node version specified at the top, but the npm version you want, not the one bundled with Node.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Everything You Wanted To Know About package-lock.json But Were Too Afraid To Ask]]></title><description><![CDATA[Introduction So you’ve updated Node Package Manager (npm) to v5.x.x, and everything seems to be going fine. But wait, what’s this? A new…]]></description><link>https://blog.quigley.codes/everything-you-wanted-to-know-about-package-lock-json/</link><guid isPermaLink="false">https://blog.quigley.codes/everything-you-wanted-to-know-about-package-lock-json/</guid><pubDate>Fri, 11 Aug 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#introduction&quot; aria-label=&quot;introduction permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Introduction&lt;/h2&gt;
&lt;p&gt;So you’ve updated Node Package Manager (npm) to v5.x.x, and everything seems to be going fine. But wait, what’s this? A new file was created automatically. &lt;code class=&quot;language-text&quot;&gt;package-lock.json&lt;/code&gt;. If you open it, it looks sort of like the dependencies in package.json, but more verbose. You decide to ignore it and go along your way developing your project. Eventually, you run into problems with a dependency. It can’t be found or the wrong version seems to be installed. Most people just end up deleting the package-lock.json and running &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt;. So why even have it? What is it supposed to do? What does it actually do?&lt;/p&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#summary&quot; aria-label=&quot;summary permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;If you’re using npm ^5.x.x, by default a package-lock.json will be generated for you&lt;/li&gt;
&lt;li&gt;You should use package-lock to ensure a consistent install and compatible dependencies&lt;/li&gt;
&lt;li&gt;You SHOULD commit your package-lock to source control&lt;/li&gt;
&lt;li&gt;As of npm ^5.1.x, package.json is now able to trump package-lock.json, so you should experience much less of a headache&lt;/li&gt;
&lt;li&gt;No more deleting that package-lock just to run &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt; and regenerate it;&lt;/li&gt;
&lt;li&gt;Use semver if your app offers an API, and adhere to the rules of semver.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;background&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#background&quot; aria-label=&quot;background permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Background&lt;/h2&gt;
&lt;h3 id=&quot;semantic-versioning&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#semantic-versioning&quot; aria-label=&quot;semantic versioning permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Semantic Versioning&lt;/h3&gt;
&lt;p&gt;Before you can understand the package-lock and even package.json, you have to understand &lt;a href=&quot;http://semver.org/&quot;&gt;semantic versioning (semver)&lt;/a&gt;. It’s the genius behind npm, and what has made it even more successful. You can read more about how npm uses it &lt;a href=&quot;http://blog.npmjs.org/post/162134793605/why-use-semver&quot;&gt;here&lt;/a&gt;. In a nutshell, if you are building an application with which other applications interface, you should communicate how the changes that you make will affect the third party’s ability to interact with your application. This is done via semantic versioning. A version is made up of three parts: X,Y,Z where those are major, minor and patch versions respectively. An example would be 1.2.3, or major version 1, minor version 2, patch 3. A change in patch represents a bugfix that doesn’t break anything. A change in minor version represents a new functionality that doesn’t break anything. A change in major version represents a large change that breaks compatibility. If users don’t adapt to a major version change, stuff won’t work.&lt;/p&gt;
&lt;h3 id=&quot;managing-packages&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#managing-packages&quot; aria-label=&quot;managing packages permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Managing Packages&lt;/h3&gt;
&lt;p&gt;npm exists to make managing packages easy. Your projects might have hundreds of dependencies, each of those with a hundred others. To keep your mind away from dependency hell, npm was created so that with some simple commands, you could install and manage these dependencies and hardly ever have to think about them.&lt;/p&gt;
&lt;p&gt;When you install a package with npm (and save it), an entry is added to your package.json containing the package name, and the semver that should be used. npm supports some wildcards in this semver definition however. By default, npm installs the latest version, and prepends a caret e.g. “^1.2.12”. This signifies that at a minimum, version 1.2.12 should be used, but any version higher than that is OK, as long as it has the same major version, 1. Since minor and patch numbers only represent bugfixes and non-breaking additions, you should be safe to use any higher same-major version. Read more about semver wildcards and play with npm’s cool semver calculator &lt;a href=&quot;http://blog.npmjs.org/post/115305091285/introducing-the-npm-semantic-version-calculator&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;shared-projects&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#shared-projects&quot; aria-label=&quot;shared projects permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Shared Projects&lt;/h3&gt;
&lt;p&gt;The real benefit to having dependencies defined like this in package.json, is that anybody who has access to the package.json could create a dependency folder that contains the modules needed to run your application. But let’s take a look at a specific way where things might go wrong.&lt;/p&gt;
&lt;p&gt;Let’s say we create a new project that is going to use &lt;a href=&quot;https://expressjs.com/&quot;&gt;express&lt;/a&gt;. After running &lt;code class=&quot;language-text&quot;&gt;npm init&lt;/code&gt;, we install express: &lt;code class=&quot;language-text&quot;&gt;npm install express — save&lt;/code&gt;. At the time of writing, the latest express version is 4.15.4. So “express”: “^4.15.4” is added as a dependency within my package.json and that exact version is installed on my machine. Now maybe tomorrow, the maintainers of express release a bug fix, and so the latest version becomes 4.15.5. Then if someone were to want to contribute to my project, they would clone it, and run `npm install.’ Since 4.15.5 is a higher version with the same major version, that is installed for them. We both have express, but we have two different versions. Theoretically, they should still be compatible, but maybe that bugfix affected functionality that we are using, and our application would produce different results when run with express version 4.15.4 compared to 4.15.5.&lt;/p&gt;
&lt;h2 id=&quot;package-lock&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#package-lock&quot; aria-label=&quot;package lock permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Package-lock&lt;/h2&gt;
&lt;h3 id=&quot;the-goal&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-goal&quot; aria-label=&quot;the goal permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Goal&lt;/h3&gt;
&lt;p&gt;The purpose of the package-lock is to avoid the situation described above, where installing modules from the same package.json results in two different installs. Package-lock.json was added in npm version 5.x.x, so if you are using major version 5 or higher, you will see it generated unless you disabled it.&lt;/p&gt;
&lt;h3 id=&quot;the-format&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-format&quot; aria-label=&quot;the format permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Format&lt;/h3&gt;
&lt;p&gt;Package-lock is a large list of each dependency listed in your package.json, the specific version that should be installed, the location of the module (URI), a hash that verifies the integrity of the module, the list of packages it requires, and a list of dependencies. Let’s take a look at what the entry for express is:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;json&quot;&gt;&lt;pre class=&quot;language-json&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token property&quot;&gt;&quot;express&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;version&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;4.15.4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;resolved&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;https://registry.npmjs.org/express/-/express-4.15.4.tgz&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;integrity&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;requires&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;accepts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.3.3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;array-flatten&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.1.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;content-disposition&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.5.2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;content-type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;cookie&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.3.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;cookie-signature&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.6&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;debug&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2.6.8&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;depd&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.1.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;encodeurl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;escape-html&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;etag&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.8.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;finalhandler&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;fresh&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.5.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;merge-descriptors&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;methods&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.1.2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;on-finished&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;2.3.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;parseurl&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.3.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;path-to-regexp&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.1.7&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;proxy-addr&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.1.5&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;qs&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;6.5.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;range-parser&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.2.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;send&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.15.4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;serve-static&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.12.4&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;setprototypeof&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.3&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;statuses&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.3.1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;type-is&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.6.15&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;utils-merge&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token property&quot;&gt;&quot;vary&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;1.1.1&quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Equivalent entries can be found for every package listed in the “requires” section.&lt;/p&gt;
&lt;p&gt;The idea then becomes that instead of using package.json to resolve and install modules, npm will use the package-lock.json. Because the package-lock specifies a version, location and integrity hash for every module and each of its dependencies, the install it creates will be the same, every single time. It won’t matter what device you are on, or when in the future you install, it &lt;em&gt;should&lt;/em&gt; give you the same result every time, which is very useful.&lt;/p&gt;
&lt;h3 id=&quot;the-controversy&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#the-controversy&quot; aria-label=&quot;the controversy permalink&quot; class=&quot;autolink before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;The Controversy&lt;/h3&gt;
&lt;p&gt;So if package-lock is supposed to solve a common problem, why are the top search results for it (other than npm documentation) all about disabling it or questioning the role that it plays?&lt;/p&gt;
&lt;p&gt;Before npm 5.x.x, package.json was the source of truth for a project. What lived in package.json was law. npm users liked this model and grew very accustomed to maintaining their package file. However, when package-lock was first introduced, it acted contrary to how many people expected it to. Given a pre-existing package and package-lock, a change to the package.json (what many users considered the source of truth) was not reflected in the package-lock.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: Package A, version 1.0.0 is in the package and package-lock. In package.json, A is manually edited to version 1.1.0. If a user who considers package.json to be the source of truth runs &lt;code class=&quot;language-text&quot;&gt;npm install&lt;/code&gt;, they would expect version 1.1.0 to be installed. However, version 1.0.0 is installed, despite the fact that v1.1.0 is listed is the package.json.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: A module does not exist in the package-lock, but it does exist in the package.json. As a user who looks to package.json as the source of truth, I would expect for my module to be installed. However since the module is not present in package-lock, it isn’t installed, and my code fails because it cannot find the module.&lt;/p&gt;
&lt;p&gt;Much of the time, because they couldn’t figure out why their dependencies weren’t being installed correctly, users either deleted package-lock and reinstalled, or would disable the package-lock altogether.&lt;/p&gt;
&lt;p&gt;This conflict between expect and real behavior sparked a very &lt;a href=&quot;https://github.com/npm/npm/issues/16866&quot;&gt;interesting issue thread&lt;/a&gt; in the npm repo. Some people thought that the package.json should be the source of truth, some people thought that since package-lock is what npm uses to create the install, that should be considered the source of truth. The resolution to this controversy lies in npm &lt;a href=&quot;https://github.com/npm/npm/pull/17508&quot;&gt;PR #17508&lt;/a&gt;. Npm maintainers added a change that causes package.json to overrule the package-lock if package.json has been updated. Now in both above scenarios, the packages that a user would expect to be installed are installed correctly. This change was released as a part of npm v5.1.0, which went live on July 5th, 2017.&lt;/p&gt;</content:encoded></item></channel></rss>