<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Denilson Nastacio on Medium]]></title>
        <description><![CDATA[Stories by Denilson Nastacio on Medium]]></description>
        <link>https://medium.com/@dnastacio?source=rss-271712995c6e------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*gYfjkkt98FR6QcHLA79vJw.png</url>
            <title>Stories by Denilson Nastacio on Medium</title>
            <link>https://medium.com/@dnastacio?source=rss-271712995c6e------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 10 Nov 2026 05:50:20 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@dnastacio/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Accident-Proofing Argo CD Deployments]]></title>
            <link>https://dnastacio.medium.com/argo-cd-prevent-delete-6b55eff21bf3?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/6b55eff21bf3</guid>
            <category><![CDATA[argo-cd]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[gitops]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Tue, 02 Sep 2025 11:40:42 GMT</pubDate>
            <atom:updated>2025-09-06T14:24:07.487Z</atom:updated>
            <content:encoded><![CDATA[<h4>Pressing the Wrong Button Should Not Erase Your Cloud</h4><figure><img alt="Dominos falling in a cascade, with each domino successively larger than the previous one, until the last one hits a computer rack." src="https://cdn-images-1.medium.com/max/1024/1*XGabyGSTTNnVPQvz6hXZeg.png" /></figure><h3>GitOps Principle vs. Practice: The Cost of Accidental Deletions</h3><p>This article explores the Argo CD mechanisms that help prevent accidental deletion of costly system resources.</p><p>A declarative system with a single source of truth is a core principle of any GitOps practice.</p><p>But we live in a world of cascading dependencies, inhabited by <a href="https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/">CustomResourceDefinitions</a>, <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/operator/">Kubernetes Operators</a>, and IaaS abstractions such as <a href="https://www.crossplane.io/">CrossPlane</a>.</p><p>In that world, Kubernetes resources represent far more than entries in an <a href="https://kubernetes.io/docs/concepts/architecture/#etcd">etcd database</a>. They can be as complex as a PostgreSQL instance, as load-bearing as an S3 bucket storing terabytes of audit logs, or as foundational as a Kubernetes cluster.</p><h3>Argo CD and Synchronization Policies</h3><p>On top of that complex world, Argo CD introduces additional abstractions to represent the grouping of those resources:</p><ul><li><a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#applications">Applications</a> are collections of Kubernetes resources deployed to a cluster.</li><li><a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/">ApplicationSets</a> represent collections of Applications.</li></ul><p>When you combine all those layers, the accidental deletion of resources in a Git repository has the potential for triggering cascading deletions across the infrastructure, listed below in ascending order of impact:</p><ol><li>Delete a custom resource representing an IaaS resource, such as an S3 bucket? There goes the S3 bucket and all of its data.</li><li>Delete a <a href="https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#delete-a-customresourcedefinition">CustomResourceDefinition</a>? There goes <em>all</em> Kubernetes resources matching the definition, along with all corresponding resources in the infrastructure.</li><li>Delete an Argo CD Application? There goes every managed resource in that Application. If one of the resources is a CustomResourceDefinition, you can do the math with the previous item.</li><li>Delete an Argo CD ApplicationSet? There goes every Application generated from the ApplicationSet.</li></ol><p>The following sections cover the Argo CD mechanisms for preventing troubled Git merges from accidentally deprovisioning large swaths of your infrastructure.</p><p>These mechanisms range from requiring human confirmation to directives instructing Argo CD to ignore deletion requests.</p><p>It is important to note that vendors may also offer their own protection mechanisms, such as <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#reclaiming">Kubernetes reclaim policies for persistent volumes</a> and CrossPlane’s deletion policy for “Cluster” resources.</p><h4>1. ApplicationSet syncPolicy: Preventing Application deletions</h4><p>An ApplicationSet owns the Application resources it <a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Generators/">generates</a>.</p><p>The <a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Controlling-Resource-Modification/#managed-applications-modification-policies">default policy</a> is governed by the ApplicationSet <a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Controlling-Resource-Modification/#managed-applications-modification-policies">“syncPolicy”</a> field. The default value for application synchronization (sync) adheres to the principle of a single source of truth:</p><ol><li>If the ApplicationSet is deleted, all generated Applications are deleted.</li><li>If the generator no longer generates one of the applications it previously generated, that Application resource is deleted.</li></ol><p>Something as simple as a typo in the target revision in a Git generator may result in an empty set of matching Applications. The default Argo CD configuration may cause the deletion of all Applications generated from that ApplicationSet, which in turn triggers a cascading deletion of all resources created downstream from that ApplicationSet.</p><p>If an ApplicationSet contains Applications representing expensive resources, that may be a costly mistake, so you may want to consider customizing the applicationsSync parameter of such ApplicationSets.</p><p>These are the options and respective explanations:</p><pre>apiVersion: argoproj.io/v1alpha1<br>kind: ApplicationSet<br>...<br>spec:<br>  syncPolicy:<br>    # (default) Applications strictly reflect the output of the generator.<br>    # applicationsSync: sync<br><br>    # Prevents ApplicationSet controller from modifying or deleting Applications<br>    applicationsSync: create-only<br>    <br>    # Prevents ApplicationSet controller from deleting Applications. Update is allowed<br>    # applicationsSync: create-update<br><br>    # Prevents ApplicationSet controller from modifying Applications. Delete is allowed.<br>    # applicationsSync: create-delete</pre><p><strong>Note</strong>: The applicationsSync setting is only observed in Argo CD installations that are configured to accept policy overrides in the ApplicationSets. <a href="https://argo-cd.readthedocs.io/en/stable/operator-manual/applicationset/Controlling-Resource-Modification/#managed-applications-modification-policies">See this Argo CD document page for more details.</a></p><p><strong>Reference</strong>: <a href="https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/applicationset-specification/">https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/applicationset-specification/</a></p><h4>2. ApplicationSet preserveResourcesOnDeletion: Preventing Application resource deletions</h4><p>Overriding ApplicationSet applicationsSync parameters may lead to confusion about which Applications are still valid. After all, you may lose track of which Application resources are still being generated and which ones are orphaned by an applicationSync policy of create-update.</p><p>In such cases, you may prefer to have Argo CD delete the Application resources but use a non-cascading deletion policy for those Applications. In other words, you can instruct the applicationset controller to remove the Application resource from the cluster without applying the cascading deletion to all resources managed by that Application.</p><pre>apiVersion: argoproj.io/v1alpha1<br>kind: ApplicationSet<br>...<br>spec:<br>    # Prevent an Application&#39;s child resources from being deleted when the parent Application is deleted<br>    preserveResourcesOnDeletion: true</pre><p><strong>Reference</strong>: <a href="https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/applicationset-specification/">https://argo-cd.readthedocs.io/en/latest/operator-manual/applicationset/applicationset-specification/</a></p><h4>3. Application non-cascading deletion</h4><p>An Application resource may be created directly in a cluster, without being generated by an ApplicationSet.</p><p>There are valid reasons for wanting an Application resource removed from a cluster without triggering the deletion of resources contained in the Application.</p><p>In those circumstances, you can use the cascade=false parameter in the command-line interface or the Non-cascading option when deleting the application from the Argo CD user interface.</p><pre>argocd app delete APPNAME --cascade=false</pre><p><strong>Reference</strong>: <a href="https://argo-cd.readthedocs.io/en/latest/user-guide/app_deletion/">https://argo-cd.readthedocs.io/en/latest/user-guide/app_deletion/</a></p><h4>4. Application syncPolicy prune: Preventing mass pruning of resources</h4><p>Total deletion of an Application, covered in the previous sections, is only one of the ways an expensive resource may be deleted. There are cases where accidental deletion originates from the deletion of an individual resource in the Git repository.</p><p>In such cases, the resources deleted from the source Git repository may be removed from the system during the next synchronization operation.</p><p>By default, the pruning policy for resources is set to false, which marks an unusual deviation from the principle of a single source of truth. In other words, by default, Argo CD does not delete resources from a cluster when the resource is deleted from the source Git repository.</p><p>Regardless of its default value, this pruning policy can be overridden by setting it to true. I wanted to highlight this as a separate section in this article to establish the context for the following sections.</p><pre>spec:<br>  syncPolicy:<br>    automated:<br>      ...<br>      prune: true       # Specifies if resources should be pruned during auto-syncing ( false by default ).<br>      ...</pre><p><strong>Reference</strong>: <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/#automatic-pruning">https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/#automatic-pruning</a></p><h4>5. Resource Prune sync-option: Prevent individual pruning of resources</h4><p>Assuming an Application pruning policy is set to true, there may be cases where you still want to prevent specific resources from being deleted from the system after they are removed from the source Git repository.</p><p>In those cases, you can use the Prune annotation in the resource, like this:</p><pre>apiVersion: your_resource_group<br>kind: your_resource_type<br>metadata:<br>  annotations:<br>    argocd.argoproj.io/sync-options: Prune=false|confirm</pre><p><strong>Note 1</strong>: You can also set this synchronization policy for an entire class of resources at <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/diffing/#system-level-configuration">the server level</a>.<br><strong>Note 2</strong>: The confirm option was introduced in Argo CD 2.14.</p><p><strong>Reference</strong>: <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/sync-options/#no-prune-resources">https://argo-cd.readthedocs.io/en/stable/user-guide/sync-options/#no-prune-resources</a></p><h4>6. Resource Delete sync-option: Prevent individual deletion of resources</h4><p>The “Delete” option can add an extra layer of protection by preventing the resource deletion when the parent Application is deleted.</p><pre>apiVersion: your_resource_group<br>kind: your_resource_type<br>metadata:<br>  annotations:<br>    argocd.argoproj.io/sync-options: Delete=false|confirm</pre><p><strong>Note</strong>: The confirm option was introduced in Argo CD 2.14.</p><p><strong>Reference</strong>: <a href="https://argo-cd.readthedocs.io/en/latest/user-guide/sync-options/#no-resource-deletion">https://argo-cd.readthedocs.io/en/latest/user-guide/sync-options/#no-resource-deletion</a></p><h4>AppProject syncWindows: Honorable Mention</h4><p>Per Argo CD documentation for <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/sync_windows/">AppProject synchronization windows</a>:</p><blockquote>Sync windows are configurable windows of time where syncs will either be blocked or allowed. These are defined by a kind, which can be either allow or deny, a schedule in cron format and a duration along with one or more of either applications, namespaces and clusters.</blockquote><p>With synchronization windows in place, system administrators can retain automated sync policies at the Application level, trusting that changes to the system due to Application changes will only happen at designated times and on designated systems.</p><p>In other words, this feature does not prevent accidental deletions, but may give system administrators additional time to examine diff changes and spot undesirable changes before the maintenance window starts.</p><h3>Summary</h3><p>A healthy GitOps practice requires some thinking about which resources can be managed according to a strict principle of a single source of truth.</p><p>The more resources you can manage that way, the less manual intervention you will need to clean up orphaned resources or manage drift between Git repos and the target environments.</p><p>If your GitOps practice is based on Argo CD, you can use this article as a guide to make informed decisions on where to implement the deviations and how to implement them.</p><p>The following table summarizes the different sections, their scope, and the pros and cons of adopting each approach:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5ac94d6a22cdd03af97a981eeda0fa35/href">https://medium.com/media/5ac94d6a22cdd03af97a981eeda0fa35/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6b55eff21bf3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Balancing Capacity and Cost for Kubernetes Clusters]]></title>
            <link>https://dnastacio.medium.com/kubernetes-cluster-capacity-d96d0d82b380?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/d96d0d82b380</guid>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[cloud-computing]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Mon, 31 Mar 2025 22:36:16 GMT</pubDate>
            <atom:updated>2025-06-15T15:56:04.578Z</atom:updated>
            <content:encoded><![CDATA[<h4><strong>Infinite Choices, but Which Is the Right One?</strong></h4><figure><img alt="A wide-frame pencil sketch of a robotic forklift inside a vast, grid-lined data center with few computer racks. The computer racks dovetail with each other as pieces of a puzzle. The forklift is tiny in comparison to the room." src="https://cdn-images-1.medium.com/max/1024/1*vUzjPd6O1juoxKqKUVd9Sw.png" /></figure><p>Many services may become unused and forgotten in some corner of your Cloud provider bill.</p><p>Not Kubernetes.</p><p>Kubernetes hides its resource waste in plain sight, under a cloak of abstracted layers and compartments. From physical limits <a href="https://en.wikipedia.org/wiki/19-inch_rack">tracing their lineage to the early 1900s</a> to a d<a href="https://dnastacio.medium.com/kubernetes-resources-1a1fa1e72dcf?source=friends_link&amp;sk=0ae9728422d149d00e0761f438bbd019">izzying array of resource allocation techniques</a>, it is virtually impossible to understand all nuances of how workloads are distributed across the environment.</p><p>In IT, there are three ways of dealing with problems in things we don’t understand:</p><ol><li><strong>Learn more about those things</strong>. Learning more is the theme of this article. The article does not cover <em>everything</em>, but it addresses the most common blind spots. Knowing what to avoid and why also helps one focus one’s observations about the system.</li><li><strong>Reboot it</strong>. Whether restarting a pod, draining a node, or restarting a compute instance, “reboot it” is the <a href="https://lonesysadmin.net/2011/10/19/cargo-cult-system-administration/">Cargo Cult</a> variation of resource allocation. In Kubernetes, this type of solution is often an illusion: a pod causing problems on a node will cause the same problems in its new hosting node.</li><li><strong>Increase capacity</strong>. There are classes of problems that may require more capacity, but many other problems that <em>just happen</em> to be resolved with more capacity. For example, suppose a pod with an undeclared memory utilization of 32 GB keeps crashing the nodes on which the pod is scheduled. A system administrator unaware of the <a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/">Kubernetes resource allocation model</a> may decide to reallocate the entire node pool with an extra 32GB for each node.</li></ol><p>While the “reboot” solution is simply a time-wasting distraction, the guesswork in resource allocation is an insidious shortcut, promoting thoughtless waste to a system requirement.</p><h3>Kubernetes Waste is Structural</h3><p>Virtualizing resources in production systems rely on workload owners specifying how many resources they may need.</p><p>Once again, Kubernetes is unique in that regard.</p><p>In Kubernetes, resource owners must specify the minimum resources they need (resource requests) and the maximum they can possibly use (resource limits.) And that is before we even start talking about <a href="https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/">affinity between pods and nodes</a>.</p><p>Lost in that confusing mix, people tend to over-allocate resources to shield their workloads from resource starvation.</p><p>It is not unusual for a Kubernetes cluster to run with an allocated capacity several times larger than the workload usage within the cluster.</p><p>But how to avoid over-allocation?</p><ul><li>Should you set cluster capacity a <strong>few percent above the workload resource requests</strong> and hope that the capacity buffer is enough to handle eventual spikes?</li><li>Should you set cluster capacity <strong>to meet the sum of resource limits for all workloads</strong> and watch the bulk of your IT budget being spent on pre-allocated capacity?</li></ul><figure><img alt="2D chart with cluster CPU and memory as the axis. The choices with capacity below workload requests are on the bottom left of the chart. That area of the chart has the label “instability.” On the upper and right-most portions of the chart are the choices with capacity above the workload limits. That area is labeled “waste”. The better cluster size choices are in the region between those two." src="https://cdn-images-1.medium.com/max/1024/1*fw0gehM3xWntxrXKMLngwA.png" /><figcaption>Figure 1 — The “sensible zone” for a Kubernetes cluster is where the overall cluster capacity is sufficient to meet the minimum requirements for all workloads, with enough spare capacity to deal with eventual spikes in demand. If fixed capacity is required, the cluster capacity should be set slightly above the combined limits of all workloads.</figcaption></figure><p>Indeed, we can auto-scale everything to try and allocate capacity on demand. At the top of the auto-scaling hierarchy, cluster auto-scaling takes care of running the minimum number of nodes, but there is still the question of individual node capacity.</p><p>The compute instances underneath those nodes come in pre-packaged sizes with fixed ratios between CPU and memory. Dynamically creating a new node with the wrong size is better than always running that same node, but it is still wasteful.</p><p>System administrators must find the ideal node size capable of running all workloads while avoiding surprises such as Cloud provider bills going up instead of down.</p><p>Avoiding those surprises requires a keen sense of where the typical blind spots lie, which brings us to the following sections.</p><h3>Blind Spot #1. Limits Are Often Hidden, Rarely Abstracted</h3><p>A running Kubernetes cluster sits atop a tall software and hardware stack, with each layer having its own capacity constraints and limits.</p><p>Limits lurking deep in that stack are a perennial source of <a href="https://nastacio.github.io/technote/technote-k8s-node-drain/">seemingly mysterious messages indicating that pods cannot be scheduled on a lightly loaded node</a>.</p><p>Those limits can be set at the operating system or the hardware level. As a software example, the operating system running a cluster node may have a maximum number of processes that can be concurrently open. For a hardware example, there may be a fixed number of PCIe slots in the computing device, which limits the number of storage volumes that can be mounted to a compute instance.</p><p>Few people will know <em>all</em> limits, but anyone managing Kubernetes clusters for a living should be familiar with these three:</p><ol><li><strong>Kubernetes limits</strong>. Kubernetes distributions have limits such as the maximum number of pods per node or the maximum number of nodes per cluster. Additionally, these limits are often different than those listed in the <a href="https://kubernetes.io/docs/setup/best-practices/cluster-large/">opensource documentation</a>, such as those for <a href="https://docs.openshift.com/rosa/rosa_planning/rosa-limits-scalability.html">ROSA Limits and Scalability</a></li><li><strong>Compute Instance limits</strong>. Kubernetes nodes are compute instances with an operating system and various processes layered on top. A task as simple as requesting a persistent volume in Kubernetes may bounce into compute instance limits for how many storage volumes can be attached to the instance.</li><li><strong>Infrastructure/account constraints</strong>. Cloud environments are virtually infinite in terms of capacity, but there are account-level limits that crop up when you least expect them. For example, you may not have problems creating the first few dozen clusters in your account. Then, the next request may fail because the cluster may need a new network gateway, and some cloud providers impose account limits on those¹.</li></ol><figure><img alt="A wide-frame pencil sketch of a robotic forklift inside a vast, grid-lined data center with few computer racks. The computer racks dovetail with each other as pieces of a puzzle. The forklift is tiny in comparison to the room. There are small wall-like obstacles around the forklift, labeled “Kubernetes Limits,” “Account Limits,” and “Instance Limits”" src="https://cdn-images-1.medium.com/max/1024/1*rc4PkpAnqwmZC3nFguU9vw.png" /></figure><p><strong>Takeaway</strong>: Read through your cloud provider documents about the limits in these three abstraction layers (Kubernetes, compute instance, and IaaS account.)</p><h3>Blind Spot #2: Burstable and BestEffort workloads</h3><p>Planning is only as good as the quality of the data going into the planning.</p><p>You cannot decide on the best size for compute instances when you don’t know how much the workloads will need.</p><p>Containers inside a pod may have any combination of resource requests and limits, with different combinations of CPU and memory reservations defining the quality of service for the parent pod as follows:</p><ul><li>Every container in the pod has both resource request and limit set, and for each container, request and limit have the same value: <strong>Guaranteed</strong>.</li><li>Resource request or limit not set in at least one of the containers in the pod: <strong>BestEffort</strong>.</li><li>All other pods not in the two previous buckets: <strong>Burstable</strong>.</li></ul><p>BestEffort and Burstable pods do not tell the cluster exactly how much CPU and memory they plan on using. In some cases, it may be a minor omission, such as <a href="https://medium.com/@dnastacio/why-you-should-keep-using-cpu-limits-on-kubernetes-60c4e50dfc61">not specifying CPU limits</a>. Still, in other cases it may be a cluster-wrecking omission, such as not specifying memory requests.</p><p>Below is my scale of minor to significant ommissions in how workloads declare their resource needs, starting with the most severe:</p><ol><li>No memory requests</li><li>No memory limits</li><li>No CPU requests</li><li>No ephemeral storage requests</li><li>No CPU limits</li><li>No ephemeral storage limits</li></ol><p>There may be some debate at the bottom of the list, but not at the top.</p><p>In the worst case, workloads without any memory declaration (resources or limits) may crash several nodes in rapid succession, so you need to be at least aware of their existence.</p><figure><img alt="A wide-frame pencil sketch of a tiny forklift inside a vast, grid-lined data center with few computer racks. The forklift is wobbling under the weight of a large crate with a hazardous sign on its side." src="https://cdn-images-1.medium.com/max/1024/1*XVkmclq8j5NXcWTKFRrf3w.png" /></figure><p>There are many open-source and commercial tools that can analyze the historical resource usage of workloads in a cluster. These tools can identify workloads that may be underperforming due to a lack of resources and, more importantly, those that can destabilize other workloads.</p><p>For larger environments, some of these tools can continuously monitor resource utilization and create optimization plans for setting workload resource requests and limits. For smaller use cases, one can run a simple kubectl command like <a href="https://stackoverflow.com/a/73190962/996026">this</a> or something more sophisticated, like Robusta&#39;s <a href="https://github.com/robusta-dev/krr">Kubernetes Resource Recommender</a>.</p><p>Regardless of your chosen tool, you must understand how Kubernetes resource management works and scales across all dimensions. I wrote <a href="https://dnastacio.medium.com/kubernetes-resources-1a1fa1e72dcf?source=friends_link&amp;sk=0ae9728422d149d00e0761f438bbd019">a comprehensive primer on Kubernetes scaling technologies</a>.</p><p><strong>Takeaway</strong>: Always identify all your Burstable and BestEffort workloads, then decide how much risk you are willing to take. There is no point in discussing budgets or ideal cluster node sizes when a significant share of workloads can simply start using cluster resources without notice or an upper limit.</p><h3>Blind Spot #3: Overcome by Daemons</h3><p>No matter the instance size, a fixed portion of the instance is <a href="https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/">reserved</a> for the <a href="https://kubernetes.io/docs/concepts/overview/components/#node-components">processes that make a node work</a> within a larger Kubernetes cluster.</p><p>While those reservations can take up 1% or 2% of a node’s memory and CPU — somewhat more for storage — <a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/"><strong>DaemonSets</strong></a> can take far more.</p><p>DaemonSets are typically used to run copies of pods on all (or some) nodes, augmenting the node capabilities with functions such as enforcement of security policies, log collection, observability, and storage.</p><p>A query to Prometheus, such as the one below, can show the memory resource requests for all DaemonSet pods across all nodes in a cluster — replace “memory” with “cpu” in the query to see memory requests:</p><pre>sum by (node, daemonset) (<br> kube_pod_container_resource_requests{resource=&quot;memory&quot;}<br> * on(pod) group_left(owner_name) kube_pod_owner{owner_kind=&quot;DaemonSet&quot;}<br>)</pre><p>These DaemonSets may get added gradually over time, and without asking the right questions about how many resources they will need, one can be blindsided by how little of each new node’s capacity remains usable by customer workloads.</p><figure><img alt="Diagram showing four Kubernetes nodes. Nodes are split into two sections. One of the sections is fully populated with DaemonSets, while the other is sparsely populated with workload pods." src="https://cdn-images-1.medium.com/max/1024/1*vyJrOopN4lnKm6Tk3lf4Nw.png" /><figcaption>Figure 2 — Daemonset workloads manage or extend the node capabilities. They consume fixed resources on a node regardless of customer workloads and effectively reduce the allocatable capacity of a node.</figcaption></figure><p><strong>Takeaway</strong>: Kubernetes DaemonSets can use considerable node capacity, especially when running on smaller compute instance sizes. Choose CPU and memory utilization thresholds for DaemonSets, then alert the operations team when that threshold is crossed.</p><h3>Blind Spot #4: Bigger Instances, Bigger Root Volumes</h3><p>While I argued in the previous section that smallish instance sizes can be wasteful, using larger instance sizes carries a different type of risk: storage limits.</p><p>As instance sizes increase, so does the number of pods per node.</p><p>Running more pods per node requires more disk activity, which brings us to the node root volume where that activity occurs. That root volume is where Kubernetes stores things like cached images and <a href="https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/">ephemeral volumes</a>.</p><p>More pods mean higher demands in capacity, throughput, and transactions per second (IOPS). Of those three metrics, capacity is the easiest to exceed but also the easiest to observe — “disk full” messages have a way of making themselves known sooner rather than later. Throughput and IOPS tend to be the blind spots within the blind spot, with most shops not fully equipped to monitor or troubleshoot those problems.</p><blockquote><em>So, if I double my instance size, should I double the capacity, throughput, and IOPS for root volumes?</em></blockquote><p>In short, yes.</p><p>There is a word of caution here about whether your Kubernetes distribution exposes those settings to system administrators. For example, as of the writing of this article, <a href="https://aws.amazon.com/rosa/">ROSA</a> allows the choice of disk size but does not allow the choice of throughput and IOPS reservations, so system administrators may have to locate the corresponding volumes in their AWS account to set those limits manually.</p><p>The last blindspot within the blindspot for this section is <em>cost</em>.</p><p><strong>Cloud providers do not charge linearly for reservations</strong>. For example, AWS currently does not charge for volume reservations of up to 125 MB/s and 3000 IOPS when using <a href="https://aws.amazon.com/ebs/general-purpose/">general purpose volumes</a>. However, if your larger compute instances require reservations above those free-of-charge limits, you will have new financial costs to consider.</p><p><strong>Takeaway</strong>: Consider node root volumes’ three performance limits (capacity, throughput, and IOPS). Before choosing larger node sizes, you need to know whether you can increase those reservations and what their cost will be.</p><h3>Blind Spot #5: Cheaper Instances, Fewer Volumes</h3><p>Cloud providers do not optimize <em>all</em> compute instance sizes and families for containerized workloads. I often wonder if they even worry about instance sizes for Kubernetes.</p><p>As you choose larger instance sizes, the hardware limits in a typical server rack may become the limiting factor in the maximum size for those instances.</p><p>For example, as of the writing of this article, AWS EC2 has <a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volume_limits.html#shared-limit:~:text=Most%20Nitro%20instances%20support%20a%20maximum%20of%2028%20attachments.">a limit of 28 volumes for its older instance generations</a> <em>regardless of instance size</em>. As storage volumes are used to back persistent volumes, those 28 persistent volumes must be sufficient for the storage requirements from all pods scheduled in that node.</p><p>On the other hand, and still using AWS as an example, the more recent (and more expensive) <a href="https://docs.aws.amazon.com/ec2/latest/instancetypes/instance-type-names.html">instance series</a>, such as 7 and 8, have volume limits that increase with instance size, making them more suitable for running Kubernetes workloads that require persistent volumes.</p><p><strong>Takeaway</strong>: If your workloads require persistent volumes, read your cloud provider documentation and specs on storage limits. Then, assess whether your candidate instance types have enough “slots” for each node’s expected number of persistent volumes.</p><h3>Blind Spot #6: Have You Talked to the Procurement People?</h3><p>Technical folks (myself included) can be too quick to pull numbers from Cloud provider calculators and think they know what a compute instance costs.</p><p>For large companies, the real numbers are written in a contract negotiated for months between the company and the cloud provider. Those negotiated numbers are very different than those visible in external calculators.</p><p>The blind spot is that some of these discounted numbers <em>may only apply to specific combinations of instance sizes and regions</em>.</p><p>The rationale is that a cloud provider may be more willing to offer deeper discounts on a smallish 2x8 compute instance than a larger 64x256 instance. Those smaller instances can be more easily shoehorned in the unused crevices of a server blade on a rack — where they would go unused — while the larger instance may require an entire server blade.</p><p>Another related blind spot is that some discounted prices involve savings plans that require <strong>fixed reservation</strong> (or even prepayment) of capacity over a long period — months or years. Reducing wasted capacity reservation for your Kubernetes clusters may send account-wide utilization below that fixed reservation. Without a contract renegotiation on the minimum utilization, there may be no reductions in your Cloud provider bill.</p><p>Regardless of specifics about the discounted prices in that contract, initiating a contractual change before the contract ends is the equivalent of entertaining a new move right after unpacking the last box in your new house or apartment.</p><p><strong>Takeaway</strong>: Before making capacity allocation decisions for your fleet of Kubernetes clusters, ensure you understand the <em>actual</em> cost of your options. You don’t want to find out your next Cloud bill went up <em>after</em> you spent considerable resources resizing all node pools in the fleet.</p><h3>Summary</h3><p>Reducing the total operation cost for a fleet of Kubernetes clusters is an optimization problem in a constrained space.</p><p>As with all math optimization problems, one must know their objective functions, decision variables, and constraints.</p><p>In plain English, one must know what happens to costs when the system settings change and which changes lead to unwanted results.</p><p>If individual nodes have the “wrong” resource allocation for the cluster workloads, even the best node auto-scaler algorithms and resource optimization tooling can only do so much.</p><p>Meeting workload objectives is the primary goal, but the total cost of ownership cuts directly into profits, so always <strong>consider instance pricing</strong> when making decisions. Depending on the workload, something like a <a href="https://medium.com/@dnastacio/running-knative-services-on-aws-spot-instances-5b73202e89dc">dedicated pool of spot instances</a> can be a sensible solution at a fraction of the cost.</p><p>And finally, <strong>aim for continuous improvements rather than ideal allocation</strong>. Simple changes can achieve considerable gains, while other optimizations may require more extensive performance analysis and reassessment of reservations at the workload level.</p><figure><img alt="A wide-frame pencil sketch of a tiny forklift inside a vast, grid-lined data center with several rows efficiently and tightly packed with computer racks. Everything looks neat and organized." src="https://cdn-images-1.medium.com/max/1024/1*fp7ds2auaIZdWnSZtTH1oQ.png" /></figure><h4>Footnotes</h4><p>1. Sometimes, soft limits are set to avoid runaway resource allocation, and your cloud administrator can quickly increase them. Sometimes, hard limits require escalation or redesigning the entire system.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d96d0d82b380" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Space, Nuclear Power, New Worlds, and LLMs]]></title>
            <link>https://dnastacio.medium.com/space-nuclear-llms-6fd38194c619?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/6fd38194c619</guid>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[space]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software]]></category>
            <category><![CDATA[cloud]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Sat, 09 Nov 2024 18:44:19 GMT</pubDate>
            <atom:updated>2025-09-14T20:15:55.302Z</atom:updated>
            <content:encoded><![CDATA[<h4>The Unserious Economics of an AGI Revolution</h4><figure><img alt="First-person perspective with the horizon line in the background. On the left, a man works in the field with a rake. On the right, a NASA space shuttle rocket stands in the distance on a takeoff pad with two nuclear power cooling towers." src="https://cdn-images-1.medium.com/max/1024/1*7elss45Da8ZHPBoEyLOYgg.png" /></figure><p>Let’s talk about revolution — the industrial kind.</p><p>I am not an economist, but I understand systems. When one thing changes, everything around it, from people to processes, changes to adapt.</p><p>We keep hearing about the impending moment when humanity achieves Artificial General Intelligence (AGI) and Artificial Superintelligence (ASI), entering a period of prosperity and enlightenment devoid of poverty and disease.</p><p>However, humanity has been steadily progressing in economic growth, cultural enrichment, and advances in global health for millennia without AGI or ASI. Anticipating the continuation of that progress is not much of a prediction.</p><p>Several LLM advocates may argue this time is different because we have not seen anything like what is coming, begging the question of how much they have learned about technological progress in the past 60 years.</p><p>Spend a few hours learning about the last industrial revolution — the digital one in the 1960s — and it becomes clear that AGI and ASI would only create evolutionary automation plays in the long wake of those revolutionary waves.</p><p>I’ll explain.</p><h3><strong>Large Economic Models</strong></h3><p>Large Language Models (LLM) are AGI’s current favorite building block, and they excel in predicting the next word in a sentence.</p><p>They can be used in isolation or as the foundation for applications such as OpenAI’s ChatGPT or Anthropic’s Claude.</p><p>These enhanced LLMs can go beyond predicting words, having the ability to infer and follow steps from written instructions. On a side note, I think <a href="https://machinelearning.apple.com/research/gsm-symbolic">Apple’s recent paper on limitations of LLM reasoning</a> failed to explore that aspect, though I still agree <a href="https://en.wikipedia.org/wiki/Knowledge_representation_and_reasoning">machine reasoning</a> is far from being achieved.</p><p>LLMs are impressive feats of engineering in either isolated or combined forms, but industrial revolutions require dramatic changes in industrial processes, which in turn require new forms of thinking.</p><p>That is where LLM-based technologies fall short.</p><p>Artificial or natural, language processing is neither novel nor scarce. A new industrial revolution is not being held at bay by the lack of people or machines that can process text.</p><p>Machines generating emails or scientific slop are more likely to produce heat than value.</p><p>Before we can predict the revolutionary impact of AGI and ASI technologies in our economic systems, we must understand the structure beneath those systems.</p><p>While major economic theories may have been proven flawed in light of new developments — and I may be proven very wrong in the future — those theories were still directionally accurate.</p><p>For example, the <a href="https://www.investopedia.com/terms/l/labor-theory-of-value.asp">labor theories of value</a> prevalent in the 18th century anchored the value of goods to the number of hours spent producing those goods. Those theories were laid to waste during the <a href="https://www.history.com/news/second-industrial-revolution-advances">2nd industrial revolution</a>, but engineering effort (which can be measured in hours) and energy utilization (a direct measure of work) still play a significant role in determining the value of goods.</p><p>On the opposite side of still-relevant theories, revolutions create new lines of sight to previously impossible economic concepts. A great example is the creation of the Internet, which made <a href="https://en.wikipedia.org/wiki/Network_effect">network effects</a> possible and supported the creation of the <a href="https://en.wikipedia.org/wiki/Platform_economy">platform economy</a>.</p><p>Either through old or new theories, the problem for AI revolutionaries is not one of predicting the future but one of understanding the economics of why <a href="https://www.bbc.com/future/article/20190712-apollo-in-50-numbers-the-cost#:~:text=Was%20the%20%2425bn%20spent%20putting%20men%20on%20the%20Moon%20money%20well%20spent%3F%20Not%20according%20to%20American%20tax%20payers%20in%201967.">society may not always value technological advancement above all else</a>.</p><p>If we want a perspective on the true meaning of the word “unprecedented” we need a brief history recap.</p><h3>Liftoff — 1960-1979 — Where No Human Had Gone Before</h3><p>In the 1960s, humanity witnessed the emergence of large-scale <a href="https://lab.cccb.org/en/arthur-c-clarke-any-sufficiently-advanced-technology-is-indistinguishable-from-magic/">technological magic</a> for the first time. Governments were pulling gigawatts of energy from <a href="https://www.iaea.org/sites/default/files/publications/magazines/bulletin/bull29-3/29304781925.pdf">rocks</a> and <a href="https://arstechnica.com/information-technology/2014/04/50-years-ago-ibm-created-mainframe-that-helped-bring-men-to-the-moon/">corporations were modeling worlds</a> using <a href="https://www.asml.com/en/technology/all-about-microchips/microchip-basics">tiny bricks of processed sand</a>.</p><p>Microchip-based computer systems <a href="https://hostingcanada.org/invention-of-microchips-and-their-use-in-the-space-program">guided us through the most important mission in history</a>. Humanity was <a href="https://www.axios.com/2019/07/20/how-nasa-moon-missions-names">racing chariots with the gods</a> and from 1969 to 1972, the Moon became <a href="https://science.nasa.gov/moon/missions/">Earth’s backyard</a>.</p><p>By 1971, Russian landers and probes had <a href="https://en.wikipedia.org/wiki/Mars_2">touched Mars</a> and <a href="https://en.wikipedia.org/wiki/Venera_7">Venus</a>.</p><p>Nuclear technology <a href="https://microsites.jfklibrary.org/cmc/oct16/">threatened the world</a> but was also on track to replace fossil fuels for industrial applications.</p><p>When combined, nuclear-powered probes and microchips opened the doors for <a href="https://www.energy.gov/articles/history-nuclear-power-space">deep space exploration</a>.</p><p>In 1977, <a href="https://www.jpl.nasa.gov/news/nasas-voyager-will-do-more-science-with-new-power-strategy">humanity started its journey toward the outer reaches of our solar system</a> with concrete plans for <a href="https://science.nasa.gov/mission/voyager/voyager-golden-record-overview/">making first contact with interstellar civilizations</a>.</p><figure><img alt="Schematic diagram showing the solar system with the various planetary orbits and the current location of the Voyager 1, Voyager 2, Pioneer 10, and Pioneer 11 spacecrafts approaching the limit of the Heliosphere" src="https://cdn-images-1.medium.com/max/768/1*gtKAR5rHWKhctmzcpFDb-Q.png" /><figcaption>Credit: NASA/JPL-Caltech — <a href="https://science.nasa.gov/gallery/voyager-ilustrations/">Voyager Illustrations</a></figcaption></figure><p>From the software side, we created <a href="https://en.wikipedia.org/wiki/COBOL">programming languages</a> and <a href="https://en.wikipedia.org/wiki/History_of_Unix#1970s">operating systems</a> that power the core of the business world to this day.</p><p>In the ensuing decades, our popular culture pointed at <a href="https://en.wikipedia.org/wiki/The_Jetsons">flying cars</a> and <a href="https://en.wikipedia.org/wiki/Star_Trek">traveling to the stars</a>.</p><p>From the infinitesimal to the infinite, there were no limits.</p><p>Between <a href="https://en.wikipedia.org/wiki/Vietnam_War">war</a> and <a href="https://en.wikipedia.org/wiki/Woodstock">peace</a>, our world would never be the same.</p><h3>Ascent — 1980–1999 — The Internet Booster Burn</h3><p>Deploying new reactors was expensive and time-consuming; by 1980, nuclear energy amounted to a mere 2% of global energy production. As a result, the world economy entered the 1980s reeling in the aftermath of the <a href="https://en.wikipedia.org/wiki/1979_oil_crisis">1979 oil embargo</a>.</p><p>But no matter, <a href="https://www.usg.edu/galileo/skills/unit07/internet07_02.phtml">the 1980s also gave us the birth of the Internet</a> (1983), <a href="https://en.wikipedia.org/wiki/IBM_Personal_Computer">IBM PCs</a> (1981), Microsoft Windows (1985,) and even the first seeds of <a href="https://en.wikipedia.org/wiki/Quantum_computing">quantum computing</a> technology.</p><p>The 1990s gave us the <a href="https://home.cern/science/computing/birth-web/short-history-web">world-wide web</a> and <a href="https://en.wikipedia.org/wiki/History_of_Linux">Linux</a> (1993). Later in that decade, we also had the first commercial <a href="https://en.wikipedia.org/wiki/Bluetooth">Bluetooth</a> and <a href="https://en.wikipedia.org/wiki/Wi-Fi#:~:text=The%20first%20version%20of%20the,IEEE%20802.11%20products%20are%20sold.">WiFi</a> devices.</p><p>Personal computers, wireless connectivity, a planet-wide network, and a (then) small company named <a href="https://about.google/intl/ALL_us/our-story/">Google</a> brought it all together.</p><p>By the end of the decade, humankind took its second giant leap.</p><p>We were no <a href="https://www.scienceandmediamuseum.org.uk/objects-and-stories/moon-to-living-room-apollo-11-broadcast">longer connected virtually through a shared experience</a>. We were connected, full stop.</p><p>We transitioned from making history to <a href="https://dlmconversion.com/blog/the-history-of-blogging/#:~:text=Then%2C%20in%201999%2C%20the%20term,early%20blogs%20were%20political%20blogs.">making stories</a>. Moon landings and dreams of space colonization became distant memories. We became an old couple watching family photos, filling the void by looking inward.</p><p>Without communication floodgates between industry and consumers, the Internet fueled unrelenting economic growth, punctuated by Alan Greenspan’s <a href="https://www.investopedia.com/terms/i/irrationalexuberance.asp#:~:text=Irrational%20exuberance%20refers%20to%20investor,Banking%20in%20a%20Democratic%20Society.%22">“irrational exuberance” speech</a> in 1996.</p><p>Our space dreams gave way to a pragmatism of space stations and low-orbit flights. We ramped up the <a href="https://en.wikipedia.org/wiki/Space_Shuttle_program">Space Shuttle Program</a> with its <a href="https://en.wikipedia.org/wiki/STS-1">first crewed flight</a> in 1981 and launched the <a href="https://en.wikipedia.org/wiki/International_Space_Station">International Space Station program</a> in 1993.</p><p>On the energy front, the world grappled with the <a href="https://en.wikipedia.org/wiki/Chernobyl_disaster">Chernobyl explosion</a> (April of 1986), raising the specter of mass contamination of the entire European continent and reviving the <a href="https://en.wikipedia.org/wiki/Three_Mile_Island_accident">public anxiety about the safety of nuclear power plants</a>.</p><p>Protests led to moratoriums and immediate halts in orders for new reactors.</p><p>Installed capacity continued to grow but at a much slower pace, and decades of breathless growth in nuclear output came to an end.</p><figure><img alt="Chart over the years showing progression of operational nuclear reactors worldwide, with rapid ascent from 1954 to 1996 and then nearly flat progression until present day." src="https://cdn-images-1.medium.com/max/1000/1*Xojum8agBDs8tNa7F_-68A.png" /><figcaption>Source: Statista’s “Number of operational nuclear reactors worldwide from 1954 to 2023”</figcaption></figure><p>The possibilities were still infinite, but we seemed content with rediscovering the world from our living rooms.</p><h3>Reentry — 2000–2012 — Flight Turbulence and Hard Landing</h3><p>Those years were marked by higher highs and lower lows.</p><p>The early 2000s were a nightmare on all fronts, from economy to technology.</p><p>In March 2000, the global markets peaked right before the popping of the <a href="https://en.wikipedia.org/wiki/Dot-com_bubble">dot-com bubble</a>, triggering a seemingly endless free fall of all major indexes.</p><p>Those indexes would lose over 70% of their value by the end of 2002.</p><p>In between the highs and lows, we witnessed the <a href="https://en.wikipedia.org/wiki/September_11_attacks">literal collapse of the global seat of economic power</a> on September 11th of 2001.</p><figure><img alt="Timeline chart of Nasdaq index, with a peak of 5048 on March 10th, 2000 and a long draw-out ascent back to original levels in 2015." src="https://cdn-images-1.medium.com/max/1024/1*yi24Vzr2FDhAvDW0z8aFgA.png" /><figcaption>Source: <a href="https://www.nasdaq.com/market-activity/index/comp/historical">Nasdaq Composite Index Historical Data</a></figcaption></figure><p>In the skies, <a href="https://en.wikipedia.org/wiki/Space_Shuttle_Columbia_disaster">the Columbia Space Shuttle</a> disintegrated on atmospheric reentry (February of 2003,) reliving the traumatic events of <a href="https://en.wikipedia.org/wiki/Space_Shuttle_Challenger_disaster">space shuttle Challenger’s explosion during liftoff in 1986</a>.</p><p>We could not catch a break.</p><p>On the energy front, gas fracking and shale oil extraction were breaking — and shaking — new ground. Excess production and lower prices put significant pressure on deploying new reactors.</p><p>Incidentally, the <a href="https://www.livescience.com/39110-japan-2011-earthquake-tsunami-facts.html"><em>entire</em> planet shook</a> in March of 2011 with the <a href="https://en.wikipedia.org/wiki/2011_T%C5%8Dhoku_earthquake_and_tsunami">Tohoku earthquake</a> and the tsunamic aftermath that engulfed the coast of Japan.</p><p>With Fukushima reactors still melting under receding ocean waters, weary German officials made the landmark decision to <a href="https://www.base.bund.de/EN/ns/nuclear-phase-out/nuclear-phase-out_node.html">phase out Germany’s nuclear reactors</a>, joined by Switzerland in a <a href="https://en.wikipedia.org/wiki/Nuclear_power_in_Switzerland#:~:text=Switzerland%20plans%20to%20phase%20out,19.14%20TWh%20for%20the%20nation.">similar fashion</a>.</p><p>Nuclear power generation would never again break its <a href="https://ourworldindata.org/nuclear-energy">all-time high of 2006</a>.</p><p>Back to the economy, the markets remained unable to generate real value for several years and resorted to fake valuations, inflating a real estate bubble that culminated with the <a href="https://www.federalreservehistory.org/essays/great-recession-and-its-aftermath">2007–2008 near destruction of the global economy</a>.</p><p>On July 21st, 2011, Space Shuttle Atlantis landed at NASA’s Kennedy Space Center in Florida, marking the end of the Space Shuttle Program. With SpaceX’s finances and first orbital flights on shaky ground for most of the 2000s, space exploration turned into space research, constrained to resupply missions to the ISS.</p><p>On the technology front, with the launch of Facebook (2004), YouTube (2005), and the delivery of the first iPhones (in 2007), we had the historical equivalent of the second invention of the press. While the physical presses created the large-scale ability to reproduce content for the masses, these technologies gave the <em>masses</em> the means to produce and distribute their own content.</p><p>The possibilities were still infinite, but we were more distracted than ever, and the cultural and industrial revolutions of the 1960s were finally over.</p><p>There were two extremely bright spots:</p><ol><li>NASA solidified its shift from hovers to rovers, following Sojourner’s pathfinding mission to Mars with <a href="https://science.nasa.gov/mission/mer-spirit/">Spirit</a> (January of 2004,) <a href="https://science.nasa.gov/mission/mer-opportunity/">Opportunity</a> (January of 2004,) and <a href="https://science.nasa.gov/mission/msl-curiosity/">Curiosity</a> (August of 2012.) <a href="https://en.wikipedia.org/wiki/Mars_Orbiter_Mission">India</a>, <a href="https://www.esa.int/Science_Exploration/Space_Science/Mars_Express">EU</a>, <a href="https://en.wikipedia.org/wiki/Trace_Gas_Orbiter">Russia</a>, <a href="https://en.wikipedia.org/wiki/Tianwen-1">China</a>, and <a href="https://en.wikipedia.org/wiki/Emirates_Mars_Mission">UAE</a> joined USA and the Soviet Union in successfully delivering orbiters and rovers to Mars orbit and soil.</li><li>Throughout the 2010s, <a href="https://en.wikipedia.org/wiki/List_of_quantum_processors">several manufacturers released the first wave of commercially available Quantum computers</a>. In time, these mind-bending machines are the only computing technology with the potential to rival the advent of microchips.</li></ol><figure><img alt="Picture of a rover on Mars surface, against a backdrop of a plains area with adjacent hills." src="https://cdn-images-1.medium.com/max/1024/1*v9MR7vLWdWiOlFe6ZvQ4gg.png" /></figure><h3>2012–2020 — IT’s Mission to the Clouds</h3><p>I wrote this section as a separate chapter because we tech folks still had to make one final push in the long wake of the 1960s revolutionary winds.</p><p>This cycle is a stark lesson in the economics of supply and demand, acting as a cautionary tale about why we are overestimating the demand for LLM-based technologies.</p><p>With space colonization and fossil fuel replacements sputtering in the early 2010s, computer technology was still going, with <a href="https://en.wikipedia.org/wiki/Moore%27s_law">Moore’s Law</a> in full effect.</p><p>By 2011, <a href="https://a16z.com/why-software-is-eating-the-world/">software was eating the world</a>, but the hardware was crowding us out.</p><p>Thanks to a combination of RFID, ever-cheaper WiFi routers, and a slew of IoT devices, computers were everywhere.</p><p>Those computers everywhere became a bit of a problem because we ran out of two critical resources:</p><ol><li><strong>Physical space</strong>. We were overrun by computer cabinets, racks, power supplies, and cables.</li><li><strong>People</strong>. We didn’t have enough people to manage those servers.</li></ol><p>Every small office and shop had a fleet of small towers spread from front to back. Unsightly metal boxes were laid down in improvised corners, tethered to an entanglement of cables connecting desks and rows of shelves.</p><p>In software development, we created parallel hierarchies between seniority and hardware ownership. At the top of that hierarchy, senior developers held the questionable distinction of managing a computing sprawl of workstations, mid-range servers under their desks, and often, high-powered test servers hosted in a secured area in the building.</p><p>We had IT people running around with carts and cables, performing various forms of inventory, maintenance, and repairs.</p><figure><img alt="A 16:9 widescreen black-and-white cartoon-style image illustrating a software development office from the early 2000s. The office has stick-figure senior developers at their desks surrounded by a ‘computing sprawl’ of desktop computers, mid-range servers under their desks, and large, high-powered test servers in a secure area nearby." src="https://cdn-images-1.medium.com/max/1024/1*IXJL1WsiBvWYEI93WGsMUA.png" /></figure><p>Cloud computing started to take root at the center of the technology industry because it solved the first problem (physical space) and helped with the second one (people). Economies of scale and an imperative of market capture created an entire industry of <a href="https://en.wikipedia.org/wiki/Freemium">freemium</a> service offerings backed by an unsustainable reliance on open-source quasi-products.</p><p>But even so, organizations began questioning the cost of running their operations and looking for ways to spend less on their cloud accounts, hardware, and personnel.</p><p>IT budgets went out of control, and jargon started shifting toward expressions like “business value,” “consolidation,” “time to market,” “mining existing data,” and many other terms indicating we had entered the “Town Planning” phase of the <a href="https://orghacking.com/pioneers-settlers-town-planners-wardley-9dcd3709cde7">“Pioneer, Settler, Town Planning”</a> cycle prescribed by Simon Wardley.</p><p>With limited growth caused by stiff competition and market cannibalization from hyperscalers, middleware providers accurately sensed the end of the decades-long market-capture cycle, prompting a series of defensive moves and monetization plays, from <a href="https://www.mongodb.com/legal/licensing/server-side-public-license/faq">MongoDB in 2018</a> to <a href="https://www.confluent.io/blog/license-changes-confluent-platform/">Confluent’s Kafka in 2018</a> to <a href="https://www.elastic.co/blog/why-license-change-aws">Elastic in 2021</a>. As more recent examples, we had <a href="https://www.hashicorp.com/blog/hashicorp-adopts-business-source-license">HashiCorp’s Terraform in 2023</a>, <a href="https://redis.io/blog/redis-adopts-dual-source-available-licensing/">Redis Labs</a> and, as a variation on the theme, <a href="https://wordpress.org/news/2024/09/wp-engine-banned/">WordPress’ fiasco with the WP Engine ban</a>.</p><p>We held the keys to the virtual universe but the possibilities were no longer infinite.</p><p>Society, industry, and governments started questioning the price tag, much like they questioned the escalating prices of exploring the physical universe.</p><p>LLM-based technologies, however useful, are still just one of the many moving parts in the same overextended business case for the virtual universe.</p><h3>The LLM Ballast</h3><p>With these historic arcs in the rearview mirror, we can revisit the claims of an LLM revolution around the corner.</p><p>Even if we can get to scientific-research levels of AGI and ASI — <a href="https://garymarcus.substack.com/p/confirmed-llms-have-indeed-reached">a reality-defying <em>if</em></a> — we have not been short of ideas.</p><p>Before LLMs, and by several measures from <a href="https://www.weforum.org/agenda/2022/12/innovation-patent-filings-intellectual-property-ip-applications/">patent applications</a> to <a href="https://www.researchgate.net/figure/The-number-of-papers-over-time-The-total-number-of-papers-has-surged-exponentially-over_fig1_333487946">research papers</a>, the generation of new ideas has already reached renaissance levels of creativity and innovation. LLM advocates may point at AI’s <a href="https://arxiv.org/abs/2409.04109">ability to generate more novel-sounding paper titles</a>, which only reinforces the point that LLMs are very good with words.</p><p>From an economic perspective, replicating the exponential gains of the third industrial revolution requires technologies that significantly advance the productive processes in the real world, which in turn requires new forms of production and new energy sources.</p><p>The tech industry, however, has been trying too hard to extend its reach with a self-referential model in which the physical world is subordinate to the virtual one, first, with <a href="https://www.investopedia.com/nfts-and-the-environment-5220221">NFTs</a> and now with LLMs.</p><p>And look, for all the doom and gloom of a nuclear-power industry that had seemingly lost the battle against renewable energy sources like solar and wind, the irony of a nuclear power renaissance <a href="https://www.cio.com/article/3487339/ai-to-go-nuclear-data-center-deals-say-its-inevitable.html">driven by AI energy demand</a> is not lost on me.</p><p>Setting aside the nuclear silver lining of our IT clouds, the economics of sending energy from the real world to build AI castles in the nether are terrible, backed only by the unsustainable math of market capture.</p><h3>The Real World is the Real World</h3><p>We may confuse our momentary fascination with electronic distractions for actual demand. However, the complex reality of our biological evolution remains a basic foundation of any economic and productive system.</p><p>Every systemic attempt at taking humanity deeper into virtual worlds, from 3D TVs to <a href="https://secondlife.com/">simulations of the physical world</a> and immersive entertainment, has quickly plateaued at relatively disappointing numbers.</p><p>Case in point, the market for <a href="https://www.futuremarketinsights.com/reports/3d-glasses-market">VR googles</a> is about 20% of the <a href="https://www.grandviewresearch.com/industry-analysis/earphone-and-headphone-market">market for earphones</a>. And no, it is not the price points.</p><p>In “<a href="https://nastacio.github.io/essay/artificial-empathy/">The Artificial Empathy of Generative AI</a>,” I wrote about generative AI hitting the same dissonant chord with humans. In hindsight, I missed an essential point about the value of human interaction going beyond language and into the expectation of being the subject of attention from other human beings.</p><p>While I love LLM technology and have found <a href="https://nastacio.github.io/essay/kubenstein-part-1/">potential usages for it</a>, the economic foundations of an LLM revolution are shakily deposited atop improbable reversals in the dynamics of energy consumption and human evolution.</p><p>More than generated words, revolutions need enthusiasm and creativity.</p><p>That is why I think the next industrial revolution will be one of significant developments in <a href="https://en.wikipedia.org/wiki/Nuclear_fusion">energy generation</a> and <a href="https://www.mtu.edu/materials/what/">materials engineering</a>. And because Earth’s atmosphere may be ill-equipped to dissipate energy generation at those scales, an eventual colony on the surface of Mars or the Moon may be the catalyst we need.</p><p>We may be decades or even centuries away from such a future.</p><figure><img alt="Drawing of a astronaut standing against an empty field on Mars surface, with massive ships looming over the field and a futurist truck to their left and a very distant range of mountains in the background" src="https://cdn-images-1.medium.com/max/1024/1*wVWaropja60UtnlqWnJQzw.png" /></figure><p>In fact, I hope it <em>does</em> take long, just like computers took decades to shrink from office-sized machinery to miniaturized marvels.</p><p>A prolonged revolution means the technological imperatives of creativity and sustainability required to support those colonies would impact multiple generations of builders and aspiring engineers.</p><p>With the observed excitement over SpaceX’s recent successes with crewed flights and reusable boosters, one can only imagine the planet-wide euphoria of witnessing the first humans setting foot on Mars.</p><p>Whether on Mars or the Moon, a terraforming program would transform industry, society, and culture. Massive feats of engineering streaking the skies, from planes to rockets, have always inspired our collective attention like nothing else.</p><p>Looking up from our phones, we may finally wake up from our slumber and stop being distracted by machines that can imitate our past.</p><p>Intelligence?</p><p>We already have a surplus.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6fd38194c619" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Argo CD Synchronization Strategies Versus Kubernetes Merge Strategies]]></title>
            <link>https://dnastacio.medium.com/argo-cd-apply-replace-a8ab0a795772?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/a8ab0a795772</guid>
            <category><![CDATA[argo-cd]]></category>
            <category><![CDATA[gitops]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Thu, 18 Jul 2024 21:21:37 GMT</pubDate>
            <atom:updated>2024-07-18T21:45:17.520Z</atom:updated>
            <content:encoded><![CDATA[<h4>The Default Argo CD Synchronization Strategy Is Still the Best, but It May Blindside You</h4><p>We have a GitOps repository that deploys the <a href="https://github.com/grafana/helm-charts">Grafana Helm chart</a> and a few data sources introduced as secrets via <a href="https://github.com/grafana/helm-charts/blob/main/charts/grafana/README.md#sidecar-for-datasources">sidecar datasources</a>.</p><p>The structure of the secrets requires a string value key to contain the data source definition. That key name has no special significance as long as it is matched in the sidecar pod.</p><p>For example, here is a snippet exemplifying one of such secrets:</p><pre>apiVersion: v1<br>kind: Secret<br>metadata:<br>  name: grafana-datasource<br>  labels:<br>    grafana_datasource: &#39;true&#39;<br>stringData:<br>  # The name of this key can be anything<br>  object.yaml: |-<br>    apiVersion: 1<br>    datasources:<br>    - name: My datasource<br>  ...</pre><h3>Kubectl Apply versus Key Maps</h3><p>We use Argo CD as our GitOps framework, which uses the equivalent of the “<a href="https://kubernetes.io/docs/reference/kubectl/generated/kubectl_apply/">kubectl apply</a>” command unless instructed otherwise.</p><p>You can override that default behavior, instructing Argo CD to <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/sync-options/#replace-resource-instead-of-applying-changes">replace resources instead of applying them</a>.</p><p>In one particular update to the repository, after making multiple changes to the Secret, including the URL of the data source, we decided to replace the key name inside the data source secret — for reasons outside the context of this entry — so the new resource <strong>in the repository</strong> looked like this:</p><pre># Desired resource contents, pre-Argo CD sync<br>---<br>apiVersion: v1<br>kind: Secret<br>metadata:<br>  name: grafana-datasource<br>  labels:<br>    grafana_datasource: &#39;true&#39;<br>stringData:<br>  # We changed the key name from &quot;object.yaml&quot; to &quot;prometheus.yaml&quot;<br>  prometheus.yaml: |-<br>    apiVersion: 1<br>    datasources:<br>    - name: Prometheus datasource<br>  ...</pre><p>We initiated the synchronization, and Argo CD completed it successfully, with no resources indicated as out-of-sync. In other words, the Secret had a nice green checkmark next to it.</p><figure><img alt="Argo CD reporting the secret being synchronized successfully" src="https://cdn-images-1.medium.com/max/1024/0*boqa8Jf-KW4ToQ05.png" /></figure><p>However, Grafana still presented the old data source URL in the UI, which posed a bit of a mystery and triggered a round of troubleshooting and investigation.</p><p>Later, we learned that we still needed to restart the Grafana pods and clear out a couple of persistent volumes, but what intrigued us while troubleshooting the issue is that the live secret <strong>in the cluster</strong> now had the <em>two</em> keys, old and new:</p><pre># Live resource in the cluster, post Argo CD sync<br>---<br>apiVersion: v1<br>kind: Secret<br>metadata:<br>  name: grafana-datasource<br>  labels:<br>    grafana_datasource: &#39;true&#39;<br>stringData:<br>  # Old secret data key, no longer in the Git repository<br>  object.yaml: |-<br>    apiVersion: 1<br>    datasources:<br>    - name: My datasource<br>  ...<br>  # New secret data key. The only one in the Git repository<br>  prometheus.yaml: |-<br>    apiVersion: 1<br>    datasources:<br>    - name: Prometheus datasource<br>  ...</pre><p>As mentioned earlier, Argo CD was perfectly happy to show the resource as synchronized.</p><p>The mystery ended once we went back to Kubernetes documentation to understand the <a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/">Kubernetes algorithm for processing “kubectl apply” requests</a>.</p><p>In essence, “kubectl apply” merges the input resource (the new Secret in this example) with the live resource (the Secret already created in the cluster), using <a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-different-types-of-fields-are-merged">different strategies for different types of fields</a>.</p><blockquote><em>- primitive</em>: A field of type string, integer, or boolean. For example, image and replicas are primitive fields. <strong>Action</strong>: Replace.</blockquote><blockquote><em>- map</em>, also called object: A field of type map or a complex type that contains subfields. For example, labels, annotations, spec and metadata are all maps. <strong>Action</strong>: Merge elements or subfields.</blockquote><blockquote><em>- list</em>: A field containing a list of items that can be either primitive types or maps. For example, containers, ports, and args are lists. <strong>Action</strong>: Varies.</blockquote><p>Since we changed a field name on a map, the expected behavior is “Merge” rather than “Replace.”</p><p>Mystery solved.</p><h3>Different Content, No Drift?</h3><p>I mentioned earlier that Argo CD synchronization was completed successfully and showed a green check “Synced” icon next to the resource.</p><p>It turns out that Argo CD did a great job considering the Kubernetes specification for “kubectl apply,” even though the literal content of the Secret in the live system was not the same as the content of the Secret in the git repository.</p><figure><img alt="Screenshot of Argo CD UI showing two seemingly different versions of a resource as being synced." src="https://cdn-images-1.medium.com/max/1024/0*j9XO5bSLIJIwvmT5.png" /></figure><p>In other words, Argo CD only cared that the Secret data map had a key with the desired name (“prometheus.yaml”) and ignored the extraneous key (“object.yaml”).</p><p>Well done, Argo CD.</p><h3>The Solution</h3><p>Our use case called for that Secret in the cluster to be identical to the one in the Git repository, so we annotated the resource, instructing Argo CD to replace the resource (equivalent to invoking “kubectl replace”) instead of using the default “kubectl apply” behavior:</p><pre># New resource contents in the Git repository<br>---<br>apiVersion: v1<br>kind: Secret<br>metadata:<br>  annotations:<br>    # Instruct Argo CD to replace the live resource<br>    argocd.argoproj.io/sync-options: Replace=true<br>  name: grafana-datasource<br>  labels:<br>    grafana_datasource: &#39;true&#39;<br>stringData:<br>  prometheus.yaml: |-<br>    apiVersion: 1<br>    datasources:<br>    - name: Prometheus datasource<br>  ...</pre><h3>“I heard you. I still don’t believe you.”</h3><p>Renaming keys on a Kubernetes resource is not the most common of operations, so a few people dealing with this situation wanted to run a small example using the kubectl CLI before they were ready to believe their eyes.</p><p>If you are also skeptical or if you need some backing to explain the issue to other people without having an entire Argo CD setup on hand, here is the snippet using only the CLI:</p><pre>cat &lt;&lt;EOF | kubectl apply -f -<br>---<br>apiVersion: v1<br>kind: Secret<br>metadata:<br>  name: apply-merge-example<br>  namespace: default<br>stringData:<br>  object.yaml: |<br>    apiVersion: 1<br>EOF<br><br>cat &lt;&lt;EOF | kubectl apply -f -<br>---<br>apiVersion: v1<br>kind: Secret<br>metadata:<br>  name:  apply-merge-example<br>  namespace: default<br>stringData:<br>  prometheus.yaml: |<br>    apiVersion: 1<br>EOF</pre><p>Now you can execute the following command to list the contents of the secret:</p><pre>kubectl get Secret apply-merge-example -n default -o yaml</pre><p>You will see the output with the two keys in the Secret:</p><pre>apiVersion: v1<br>data:<br>  object.yaml: ...<br>  prometheus.yaml: ...<br>kind: Secret<br>metadata:<br>  annotations:<br>    kubectl.kubernetes.io/last-applied-configuration: | ...<br>  name: apply-merge-example<br>  namespace: default<br>type: Opaque</pre><h3>Conclusion</h3><p>Ultimately, the mystery stemmed from me letting my guard down with Argo CD’s great choice of default behavior for synchronization operations.</p><p>Using “Apply” strategies is the right approach for most situations. It allows you to co-manage resource contents with other sources — a <a href="https://kubernetes.io/docs/reference/using-api/server-side-apply/">necessity in the Kubernetes ecosystem</a> — while also effectively producing results that are indistinguishable from the “replace” behavior — unless you are making certain types of changes to lists and maps (like the one we did).</p><p>Case in point, it was not the default “apply” behavior that caused our configuration problem. However, I can imagine different situations where an extraneous map key in a Secret or ConfigMap could cause problems, such as being processed by poorly written code that assumed the Secret had a single key or by code that used introspection of map keys to drive further actions.</p><p>I also acknowledge that the “replace” strategy poses problems in some cases. There may be cases where you don’t want Argo CD to come in and delete resource contents created by other sources. So, make sure you are not adding “replace” annotations to resources potentially co-managed by different sources (or, worse, manually).</p><p>Regardless of how you configure the synchronization strategy for Argo CD, either in the entire application or in individual resources, it pays to brush up on <a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#how-different-types-of-fields-are-merged">Kubernetes merge strategies</a> and carefully consider when to use the synchronization method most adequate to the use case at hand.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a8ab0a795772" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Conflicted Economics of Prompt Engineering in Software Development]]></title>
            <link>https://dnastacio.medium.com/economics-prompt-engineering-2aebc03acb58?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/2aebc03acb58</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[artificial-intelligence]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Tue, 11 Jun 2024 00:58:27 GMT</pubDate>
            <atom:updated>2024-07-18T18:39:41.038Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ihZBebV2MpJ3OpkpHC9hyQ.png" /></figure><p><em>“If you are nothing without this suit, then you shouldn’t have it.”</em> — Tony Stark</p><p>With <a href="https://www.promptingguide.ai/">prompt engineering</a> entering the professional vocabulary and the arrival of <a href="https://www.redhat.com/en/topics/ai/what-are-foundation-models#:~:text=Use%20cases,a%20wide%20variety%20of%20tasks.">foundation models</a> trained in programming languages, software engineers did not take long to look into prompt-assisted code generation.</p><p>As a software engineer with well-rounded experience in architecture, design, operations, and programming, I can see cause for enthusiasm for applying AI in software development — something I will cover in a follow-up story.</p><p>However, positive economics depend on how much effort I need to put into that explanation and the quality of the resulting answer.</p><p>Some problems are localized to small tasks; they are simple to describe and have trivial solutions. Their resolution is covered in training models to the point of <a href="https://en.wikipedia.org/wiki/Overfitting">overfitting</a>.</p><p>Other issues involve complex relationships to different parts of the system, are hard to recognize, and their solutions include trade-offs that evoke explanations starting with “it depends.”</p><p>For those problems, anecdotal evidence reveals AI <a href="https://en.wikipedia.org/wiki/Hallucination_(artificial_intelligence)">hallucination</a> and failure rates that, produced by a human, would evoke the words “human resources,” “performance improvement plan,” or even “urine test.”</p><p>Since the story got impossibly long, I split it into two parts:</p><ul><li><strong>Part 1 (this story): The economics of writing code</strong>. Here, I look at the short and long-term economics of solving non-trivial software engineering problems, using a real-world case study to compare the performance of a generative AI code assistant against the traditional, unassisted method.</li><li><strong>Part 2: The economics of creating and operating large systems</strong>. In this story, I will cover why we are missing out by focusing AI training efforts on coding assistance (where humans already excel) instead of the natural language surrounding the technical aspects of creating and operating an entire system.</li></ul><h3>Training for the Hard Problems</h3><p>The principle of training AI on complex problems is still the same: show the AI enough examples to infer patterns and predict outcomes for situations similar to those where the data was collected.</p><p>When a programmer asks for a <em>“Python function that reads the contents of a URL”</em> to an AI model trained on <a href="https://en.wikipedia.org/wiki/GitHub_Copilot">159 gigabytes of Python code source from 54 million GitHub repositories</a>, we know a nearly identical solution is in that training set, right next to comments that are an almost perfect match to the wording of that request.</p><p>If that abundance of training material was not enough, the training data also contains several public-domain articles covering basic topics, in no small part because they are easier to write and consume.</p><p>But what happens when you work on a programming language that is not one of the most used programming languages in the world or use combinations of components glued together with bespoke, confidential source code written inside your organization?</p><p>In those situations, there is certainly less material to train the AI, introducing gaps in the training data and, consequently, reduced quality in prompt results — I will illustrate that point with a case study in the following section. Additionally, when dealing with copyrighted or access-controlled source code, some content may have to be left outside the training data, further increasing the gaps in domain coverage and decreasing the quality of the answers.</p><p>This is the point in the discussion where someone raises their hand and asks:</p><blockquote>Have you tried tuning a foundation model?</blockquote><p>Yes, <strong>fine-tuning a foundation model</strong> is a popular solution to adapting a trained AI model to the distinct characteristics of a specific training set. Fine-tuning a model, an activity where you start from a larger AI model and show it examples that are closer to the ones in your organization, costs a tiny fraction - think thousandths - of the cost of training a model from scratch.</p><p>Spending a tiny fraction of the cost while getting better results sounds like great economics, but keep in mind the starting point for those savings is in the realm of <a href="https://en.wikipedia.org/wiki/GPT-4#:~:text=Sam%20Altman%20stated%20that%20the,was%20more%20than%20%24100%20million.">tens of millions of dollars</a> and <a href="https://x.com/EpochAIResearch/status/1795870450079142126">growing 4–5x every year</a>.</p><p>That bargain price tag may still run in thousands of dollars <em>per month</em> in compute-costs alone.</p><blockquote>“Non-sense. I can use a local LLM and train it on a couple of GPUs I bought on eBay and get the whole thing done for the price of a good dinner.”</blockquote><p>The first part of the rebuttal is true — you can train or fine-tune a local LLM — but it is that second part that separates an inconsequential weekend project from actual software engineering.</p><p>The economics of fine-tuning a public foundation model are terrible.</p><p>Going from a prototype to a hosted solution can take as much as <a href="https://dnastacio.medium.com/how-to-outperform-a-10x-developer-fa1132807934">27 times the effort</a> spent on the prototype. Once that prototype is done, you have to factor in hosting costs, where you either rent compute power from a cloud provider or host your own hardware, then contend with the reality that fine-tuning is a means of improving the language portion of the model but not so much a way of adding knowledge to the final system.</p><p>After all, not even all examples in the world fully cover every possible function signature or CLI command, so you have to look at <a href="https://research.ibm.com/blog/retrieval-augmented-generation-RAG">RAG patterns (Retrieval-Augmented Generation</a>) to inject that knowledge into each prompt, which in turn means you will need a database, a query engine, and some time fine-tuning those augmentations to each prompt sent to the AI model.</p><p>And if you are serious about using that fine-tuned model augmented with a RAG system, you will need to develop a <a href="https://www.ibm.com/topics/machine-learning-pipeline">Machine Learning Pipeline</a> around that solution. While designing that pipeline, you must decide on metrics to track the model performance, methods to collect those metrics, create processes for responding to feedback, and more processes for rolling out updates.</p><p>If that is not enough, you may also need to experiment with <a href="https://x.com/akshay_pachaar/status/1799781859750240545">alternative fine-tuning methods</a> to decide on the best approach for your effort.</p><figure><img alt="Modern black and white image style resembling a construction blueprint but containing flow charts with dozens of nodes stemming from a raised circular structure at the center of the blueprint. There are a handful of technical drawing instruments scattered around the sheet, including a compass, a protractor, and straight edges." src="https://cdn-images-1.medium.com/max/1024/1*tSAuxO2HcfYdi56iRjs1gw.png" /></figure><p>The economics of muscling through that entire effort are those of a research project, with heavy upskilling on new technology and the added engineering effort of building and operating the final solution. And to cap the entire argument against the economics of training a localized model, there is <a href="https://www.linkedin.com/posts/emollick_remember-bloomberggpt-which-was-a-specially-activity-7150359287024795648-65rD/">always a chance the next version of that same starting foundation model will outperform your entire investment</a>.</p><p>Assuming you are convinced that rolling out and operating your own model at the small scale of localized deployment is a lousy business, let’s look at a real example of using a code-generation assistant based on public foundation models — I used three different AIs throughout the exercise to ensure the results were consistent.</p><h3>Case Study: Single Sign-On Configuration</h3><p>This section is based on a recent real example where I had to package two components of a more extensive solution for an air-gapped environment (no direct connection to the Internet for security and regulatory purposes.)</p><p>I needed to configure an instance of HashiCorp Vault on a Kubernetes cluster to secure logins using an OIDC Client hosted on Keycloak. If you are not very technical, HashiCorp Vault is a service for managing secrets, and Keycloak is a service for managing access to other systems. In this solution, we want to use Keycloak to authorize who can access the secrets on Vault.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v7WJC-oU5jk_c3gI9Q7V9Q.png" /><figcaption>Component diagram of interactions between HashiCorp Vault and Keycloak in a single sign-on scenario</figcaption></figure><p>As a “hard problem,” this integration has a programming element combined with packaging and configuration aspects.</p><p>Securing access to Vault with an external access manager is not a rare system combination, but <a href="https://developer.hashicorp.com/vault/api-docs/auth">Vault can work with a dozen different authentication tools</a>, including the public hosted offerings from the largest Cloud providers, so there is considerably less public content about using Keycloak than for those other alternatives.</p><p>When working on such a problem, I loosely follow the following steps, a framework I will later use to evaluate the AI’s performance.</p><ol><li>Look for the documentation for both products.</li><li>Locate APIs and command-line interfaces.</li><li>Read through functions and parameters.</li><li>Map functions and parameters to the larger problem.</li><li>Draft an initial solution on a notepad (or blank page in a code editor.)</li><li>Iterate over the draft side-by-side with documentation.</li><li>Create a program to automate the instructions.</li><li>Write the documentation or notes for the component.</li><li>If I consider the solution generally usable, write a public blog or technote.</li></ol><p>Phew! That seems like a lot of work, right? Time to ask an AI:</p><blockquote><em>How do I configure Keycloak OIDC as an authentication method for HashiCorp Vault? Provide reference URLs after you give me the instructions.</em></blockquote><p>The AI printed two pages worth of instructions, which were helpful and landed me in the middle of step 5 (draft an initial solution.)</p><p>Attempts to use the solution as drafted failed for several reasons, which is expected at that stage. However, unexpected issues forced me to backtrack to the earlier steps in the process.</p><p>The first problem was Vault complaining about not trusting the custom certificate in the URL for the <a href="https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints">Keycloak OIDC discovery endpoint</a>.</p><p>I modified the initial prompt to indicate the Keycloak server used a custom certificate. Still, the AI seemingly ignored the alteration and did not produce any change in the responses. Assuming further clarifications would be equally ignored, I prompted the AI directly about how it would address the error message. The AI redeemed itself by showing an updated command with the correct parameter.</p><p>Next, while validating the solution and finally logging into Vault with a user stored in Keycloak, I noticed the Vault UI showing a numeric identifier for the user instead of the user’s email or full name. More than being friendlier to users, a recognizable name is also an extra layer of security in case the user has access to multiple accounts with different privileges (common in system operations.)</p><p>One could debate the importance of making that change, but I explained the problem in plain text to the AI, hoping for a solution. The AI generated another update for one of the commands, which did not produce the results I requested. At that point, I reverted to my usual step-by-step system and read through the command parameters.</p><p>The failed solution was because the parameter offered by the AI (&quot;oidc_claim_mappings”) did not exist. The correct parameter name should be “claim_mappings”. Pause to note that while one would expect the Vault command-line interface to complain about the non-existent parameter, it did not.</p><p>At that stage, whatever time I had gained skipping the first four steps before drafting the initial solution was lost, and then some. As the joke goes: <em>“One hour of debugging can save you five minutes of reading the documentation.”</em></p><p>I iterated over the draft following the documentation (“step 6”) and reverted to asking for the AI’s assistance with step 7 (“create a program to automate the instructions.”)</p><p>In that step, I asked the AI to generate a shell script automating the steps related to Keycloak, and it produced a respectable series of shell script commands based on low-level utilities such as “curl” and “jq.” On the less respectable side, the AI hardcoded all URLs and placeholders for credentials in the script, which would be terrible form for a human developer.</p><p>There was, however, a <strong>more severe and less visible problem</strong>: Keycloak already has an <a href="https://www.keycloak.org/docs/latest/server_admin/index.html#the-admin-cli">administrative CLI</a>. Using direct access to REST endpoints with “curl” and processing JSON responses with “jq” worked but resulted in code that not only was harder to read (and maintain) but would also be sensitive to any future changes to the product APIs.</p><p>From an economics perspective, this module would have to be rewritten and retested when people discovered the glaring mistake, which would probably coincide with the first API change in Keycloak. There would also be reputational consequences (for me) in missing the existence of an entire administrative CLI while writing the code.</p><p>I played along with AI, not calling out the existence of that CLI. Curiously, the AI eventually switched its implementation strategy and offered a solution using the appropriate CLI without acknowledging it had been suggesting an incorrect approach in the preceding prompts.</p><p>With all the running bits completed, the AI’s assistance in step 8 (writing the documentation) impressed me the most.</p><p>I used the following prompt:</p><blockquote>Write the step-by-step instructions for the following problem, grouping the information in sections titled “Overview,” “Prerequisites,” “Steps,” “Validation,” “Troubleshooting,” and “References.”</blockquote><blockquote>I want the result in markdown format that I can use on a README.md file.</blockquote><blockquote>On each step, add a “Command reference” link to the original documentation page describing the commands.</blockquote><blockquote>Here is the problem:</blockquote><blockquote>How do I configure Keycloak as an authentication method for HashiCorp Vault?</blockquote><blockquote>My Keycloak server is running on <a href="https://keycloak.server.com">https://keycloak.server.com</a>, using a custom certificate. The Realm name is “example”.</blockquote><blockquote>The Vault server is running on <a href="https://vault.server.com">https://vault.server.com</a></blockquote><p>I received an almost complete technical article in response. It had issues like a prerequisite section missing references to the product documentation pages and the same hallucinations seen in earlier steps. However, the AI assist addressed a common pain point for me and many other software developers: writing documentation at the end of a creative session, where the brain is wired to create solutions and not so much to explain the final solution — oh, and tired, too.</p><p>You can read <a href="https://gist.github.com/nastacio/87c6347c1ca5c627770a25f5bf745170#file-ai-draft-to-prompt-for-instructions">the (lightly edited) version of the response</a>. In full disclosure, I had to fix several bits of markdown for the URL links, but that only took a couple of minutes.</p><h3>AI or Traditional Method. Who Won?</h3><p>In this section, I break down each step in my usual process, calling out a “win” for the AI or “human method” in each step and then adding some commentary about each conclusion.</p><p><strong>Step 1. Look up the documentation for both products</strong></p><p><strong>Win: AI</strong></p><p>The AI gave me a usable link for each part of the process, embedded in the instructions, and with less friction than running a web search.</p><p>Web searches surfaced helpful blog entries and Stack Overflow links, but I had to vet through several entries (and ads), open the pages to skim through them, and then click a few links in the product websites to find the document sections I needed.</p><p>It is worth noting the traditional process has advantages in the long run — I’ll come to them later — but I am looking strictly at time spent and immediate results.</p><p><strong>Step 2. Locate APIs and command-line interfaces</strong></p><p><strong>Win: AI</strong></p><p>Similar to the previous step, asking for links in the context of the actual problem produced good results, with the advantage of having them embedded in the instructions close to the steps where the APIs and CLIs were being used.</p><p>I had to spend extra time writing down the problem for the AI than I would typically spend writing my search criteria, but that was not extra time relative to the entire activity.</p><p><strong>Step 3. Read through functions and parameters</strong></p><p><strong>Win: Human Method</strong></p><p>Reading manuals and understanding the technologies involved in the problem is a fundamental aspect of producing a workable solution with the lowest cost of ownership in the long run.</p><p>AI drafts may be acceptable on a disposable prototype but inexcusable on an actual product. The AI cannot create a semantic network of the product documentation in our brains or its own circuits, as evidenced by the hallucination of the “oidc_claims_mapping” parameter or the temporary blindspot surrounding the Keycloak administrative CLI.</p><p><strong>Step 4. Map functions and parameters to the problem</strong></p><p><strong>Win: Human method</strong></p><p>The AI drafts surfaced some parameters in the drafted solution, but those parameters were only a fraction of the whole. Reading through the documentation gave me a much better perspective on assessing the quality of the original AI draft and other alternatives and considerations for adapting the solution to a production system.</p><p>Understanding the overall range of configurations in the underlying technologies is the only way to judge whether the solution will be stable and have the lowest cost of operations in a production system.</p><p><strong>Step 5. Draft a solution on a notepad (or blank code editor page)</strong></p><p><strong>Win: AI</strong></p><p>After all iterations, the initial draft contained 90% of the final solution, an outstanding effort from a single-sentence prompt.</p><p>Using the traditional method of looking up examples through web searches would surface all the building blocks required to create such draft. Still, the AI could string them together much faster and generate what was <a href="https://gist.github.com/nastacio/87c6347c1ca5c627770a25f5bf745170">basically a technical article with steps to solve the problem</a>.</p><p><strong>Step 6. Iterate over the draft side-by-side with documentation</strong></p><p><strong>Win: Human Method</strong></p><p>I took over from the AI and did the iterations, partially because it could not improve upon its (admittedly solid) first draft but mainly because I lost trust in the AI’s accuracy after troubleshooting the hallucinated parameter for the Vault CLI and the scare with the temporary blindspot with the Keycloak CLI.</p><p>This experience matches what I heard and read from other senior engineers about how AI chats tend to plateau and even derail once you start to add more details about your request.</p><p><strong>Step 7. Create a program to automate the instructions</strong></p><p><strong>Win: Human Method</strong></p><p>Setting aside the initial AI blunder of ignoring the Keycloak administrative CLI, I liked how the AI was able to create a shell scripting boilerplate using the “getopt” command.</p><p>However, writing over a copy of an existing shell script in our project would have been more efficient due to their fit to our coding standards (such as copyright statements, naming conventions, message formatting, error handling, and others.)</p><p><strong>Step 8. Write down the final instructions in a markdown file</strong></p><p><strong>Win: AI</strong></p><p>The original write-up in step “5” felt like the skeleton of a technical article.</p><p>It is worth noting the AI had difficulty honoring my request to write the output in markdown format, switching back mid-text to its rich-text rendering format, no matter how specific I tried to be about the entire output using the markdown format.</p><p>Also, the AI “plateaued” in improving the quality of answers against refined prompts, such as ignoring my different wordings of a request to embed links to the product documentation in the prerequisite section.</p><p>Those issues were, however, minor relative to the overall content.</p><p>As long as one understands they should not spend too much time trying to keep refining prompts in an attempt to get the final version of the instructions, the AI saves time relative to starting from a blank page.</p><p><strong>Step 9. Write a public blog or technote.</strong></p><p><strong>Did not attempt</strong></p><p>I think the solution may be of general interest — for an admittedly niche audience — but I simply did not have the time. If I did have the time, I would still prefer to write it myself with the editorial assistance of an AI rather than defer the writing to the AI entirely.</p><p>With AIs able to write technical articles on the fly, I cannot imagine anyone willing to read through the result of someone else’s prompt rather than prompting an AI to write something bespoke to their particular problem.</p><h3>The Short-Term (potential) Gains Are Appealing</h3><p>In the <strong>short term</strong>, with four wins for each side and some loose counting of the overall time spent in the activity, I declared a tie on the economics of enlisting a generative coding AI to my workflow.</p><p>Different case studies with different technologies may swing the balance towards net gains or losses, depending on how well the training data covers the domain.</p><p>My exercise used a somewhat well-established product — Keycloak is a <a href="https://www.cncf.io/blog/2023/04/11/keycloak-joins-cncf-as-an-incubating-project/#:~:text=Keycloak%20was%20created%20by%20Bill%20Burke%20and%20Stian%20Thorgersen%20in%202014.">CNCF incubation project</a> — and the de-facto standard for secrets management, so I am assuming good, if not extensive, coverage in the training data.</p><p>The AI initially missed a severe blindspot and hallucinated a few parameters. However, it made up for its mistakes in the natural language areas of identifying useful documents and writing documentation drafts.</p><p>Outside this assessment, the AI also routinely excels in the initial drafts for the short Python-based functions I tend to use in side tasks, such as analyzing the contents of our Git repositories, typically requiring only a few editorial changes.</p><p>I think focusing the tool’s usage on ancillary, simple tasks is the sweet spot for AI assistants. However, my enthusiasm for it is more of the incremental type — such as when I first mastered a data pivot in Excel — than the kind where I would consider quitting my job and starting a software company staffed with inexpensive robot developers.</p><h3>The Long-Term Losses Can Be Devastating</h3><p>In the <strong>long term</strong>, the entire debate about the gains and losses of prompt-based programming ignores a crucial byproduct of the problem-solving cycle: gaining knowledge.</p><p>There is a formative aspect in solving problems using traditional methods of investigation, discovery, abstraction, programming solutions, and validating the resulting code.</p><p>While investigating the building blocks for a solution, we are creating an entire domain model of those concepts, full of boundaries and trade-offs between things that work well under different circumstances.</p><p>Receiving an answer to a question will never make our brains tread the same steps of processing and assembling the building blocks of that answer. In that sense, quicker results committed to a code repository come at the expense of not building skills and maturing talent at the same pace.</p><p>That is a frightening trade-off backed by ambitious assumptions that AI capabilities grow faster than we erode ours.</p><p>For how long will use cases ending in <em>”make sure the results [of a prompt] are correct”</em> still be valid in a system where asking for those results becomes the norm and we collectively atrophy the skills required to arrive at those same results?</p><p>Some technology enthusiasts make the case for generative AIs being a great learning tool. Still, I often hear those arguments from senior people learning yet another skill — backed by their substantial knowledge of multiple domains — rather than from those starting their careers.</p><p>Other rebuttals resort to a question turned argument: <em>“Would you rather code in Assembly, then?”</em>. Can people not see the distinction between adopting a higher abstraction language layer versus a cognitive process favoring interrogation over abstraction and reasoning?</p><p>There is also little acknowledgment that asking for help, a skill at the core of prompt-based coding, is an <a href="https://dnastacio.medium.com/three-steps-to-solve-your-problems-in-tech-2169d2145de3">evolved skill</a> in itself.</p><p>The general messaging may be of <a href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/gen-ai-a-cognitive-industrial-revolution">industrial revolution</a>, but <strong>industrial revolutions unlock untapped resources, which is not the case here</strong>.</p><p>Generative AI, at its core, taps into <em>existing resources</em> already explored and consumed in different ways, relying on <a href="https://dev.to/polterguy/will-stackoverflow-survive-ai-420e">contentious mining of public-domain resources</a> at the source and on use-cases cementing existing expertise at the point of delivery.</p><p>Along the way, the whole process endangers the early stages of the talent pipeline and threatens <a href="https://zephoria.medium.com/deskilling-on-the-job-bbd71a74a435">deskilling</a> the very pool of content authors generating the raw material the AI depends on.</p><p>There has to be a better way.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2aebc03acb58" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Map to Where You Are Needed in Tech]]></title>
            <link>https://dnastacio.medium.com/pioneers-settlers-town-planners-sw-dev-d408a3c3fe2b?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/d408a3c3fe2b</guid>
            <category><![CDATA[careers]]></category>
            <category><![CDATA[software]]></category>
            <category><![CDATA[business]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[leadership]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Tue, 12 Mar 2024 23:02:21 GMT</pubDate>
            <atom:updated>2025-01-18T14:36:50.718Z</atom:updated>
            <content:encoded><![CDATA[<h4>Understand Change. Predict The Future.</h4><figure><img alt="AI Prompt: An explorer arriving at a densely populated big city dressed in the style of a software developer is seen from the perspective of someone standing behind the explorer. Use a drawing style." src="https://cdn-images-1.medium.com/max/1024/1*MhcxnAGY9Pqkf7Q03c-xlg.png" /><figcaption><em>AI-Generated image by DALL·E</em></figcaption></figure><p>The inspiration for this story started with another one, by <a href="https://medium.com/u/6ae4c389b6bf">David Caudill</a>, titled <a href="https://davidkcaudill.medium.com/maybe-getting-rid-of-your-qa-team-was-bad-actually-52c408bd048b">Maybe Getting Rid of Your QA Team was Bad, Actually</a>.</p><p>In that story, David takes the reader through a worrisome progression where organizations lose sight of quality over time and, in the process, progressively devalue the importance of QA engineering roles.</p><p>QA or not, there is a common theme of people observing fundamental changes in corporate priorities and wondering if their organization still has a place for them.</p><p>To use a traveling metaphor, unexpected changes in direction and surfaces can be disorienting and even hazardous.</p><h3>The Map of Change</h3><p>Tricky roads require maps, and when you need maps for anything that is not an actual road, look no further than <a href="https://en.wikipedia.org/wiki/Wardley_map">Simon Wardley’s maps</a>.</p><p>If you have never heard of “Wardley maps,” it is the best-kept secret this side of a business management school and a reliable way of understanding the landscape of any topic, whether you are looking at an emerging market or trying to figure out where the next career opportunities are heading.</p><p>In one particular map, loosely titled <a href="https://orghacking.com/pioneers-settlers-town-planners-wardley-9dcd3709cde7">“Pioneers, Settlers and Town Planners”</a>, Simon describes the flow of evolution and change within organizations.</p><figure><img alt="Simon Wardley map for change flows in an organization. It is split into three main columns: Pioneers, Settlers, and Town Planners. There is a left-to-right arrow at the bottom, titled “Evolution” and labeled from the left with “Genesis,” “Custom Built,” “Product (+rental),” and “Commodity (+utility)." src="https://cdn-images-1.medium.com/max/1024/0*c5ev6ospWj4InN5J" /></figure><p>Understand that model, and you will start recognizing orderly flows where you would typically see random events and decisions.</p><p>In that model, there are three stereotypes for how organizations, small teams, and individuals fit into the change flows:</p><ul><li><strong>Pioneers</strong> deal with rare opportunities in ill-defined areas, with a high risk of failure and high future value in case of success.</li><li><strong>Settlers</strong> deal with growing markets, high profitability, and the need for adaptability to changing conditions in those markets.</li><li><strong>Town Planners</strong> deal with well-defined, already established areas. They focus on delivering high volume with discipline in process and cost controls.</li></ul><p>For the remainder of this story, I will refer to Simon’s model after the stereotypes’ initials: <strong>PST</strong>.</p><h3>Ugly Ducklings and Egos</h3><p>Like in the story of the <a href="https://en.wikipedia.org/wiki/The_Ugly_Duckling">ugly duckling</a>, <em>even the most competent individual will underperform in the wrong setting</em>.</p><p>While every large organization has a set distribution of resources across the three pillars of the PST model, individuals can only be excellent in one pillar at a time.</p><p>For example, someone tasked with writing a prototype for a new market should not be asked to observe rigid standards of DevSecOps discipline.</p><p>Conversely, a QA engineer who is excellent at creating automated processes and structured guidance for a growing product — aligned with a “settler” role — may struggle to contribute value in a research organization with shorter project spans and higher failure rates.</p><p>A few readers will try to make the case that an individual can be simultaneously excellent in two adjacent pillars, such as “Settler” and “Town Planner.” Before making that argument, however, they should make sure their example was not someone moving Kanban cards on a board while people worked on their email backlog — been there.</p><p>Unlike in the Danish fairy tale, a poor fit between individual tendencies and PST pillars runs deeper than the length of a feather or the shape of a beak.</p><p>How deep?</p><p>Take it from <a href="https://hiimjoke.medium.com/">Jörg Heitkötter</a>, who while remarking on an <a href="https://orghacking.com/pioneers-settlers-town-planners-wardley-9dcd3709cde7">article about Simon Wardley maps</a>, pushed right across the lines of <a href="https://www.simplypsychology.org/naturevsnurture.html">Nature over Nurture</a>, and contrasted personal interests against the dimensions of the PST model:</p><blockquote>Ego vs. Company interest</blockquote><blockquote>It occurs to me that one interesting “feature” of pioneers, settlers, and town planners has not been stated or investigated in the model yet:</blockquote><blockquote>Pioneers tend to have an ego they put over the company; at the other end of the spectrum, Town planners tend to put the company over their ego and do what’s best for the company, while Settlers tend to be in equilibrium with regard to ego vs. company interests.</blockquote><blockquote>This might be helpful for HR people or managers to identify the right members for their teams, sorting out the fake Pioneers/Settlers/Town planners from the real ones.</blockquote><p>This topic of personal and corporate interest opened my eyes to better ways of identifying and relating to a handful of team dynamics I would consider troubling otherwise.</p><p>What opened my eyes was the realization that shifting from one pillar to another may entail a change <em>in personal values</em> and in how individuals relate to their institutions. When people say they are not sure they can adapt to a different PST pillar, they may be balking at changing their entire outlook in life.</p><h3>The Fractal of Change</h3><p>The pattern of PST roles of change in an organization repeats itself in smaller parts, down to the individuals in that organization, forming a <a href="https://en.wikipedia.org/wiki/Fractal">fractal dimension</a>. In other words, a smaller part of an organization primarily focused on one pillar, such as research, still needs to apportion its resources in a PST framework.</p><p>Naturally, each pillar still needs to focus and specialize in its primary function, but within each pillar, smaller change flows require attention, too.</p><p>Balancing that allocation across all levels is the recipe for sustained success.</p><p>Neglect the exploration of the new and innovation stalls. Neglect the elaboration of a promising activity and growth stalls. Ignore the day-to-day work management, and long-term success becomes impossible.</p><p>That goes for individuals, too.</p><figure><img alt="Fractal diagram, starting with three blocks labeled, from left to right: Planner, Settler, Town Planner. Each block contains a smaller diagram with the same three blocks, and each smaller block contains a smaller diagram with the same three blocks." src="https://cdn-images-1.medium.com/max/1024/1*GgcGFletIaTOJOfxJ0JXXw.png" /><figcaption><em>Fractal of change: On a smaller scale, each role presents opportunities for another continuum of change containing the same roles.</em></figcaption></figure><p>Balance it right, and the pioneering side of an enterprise may reveal new paths that eventually transform the entire business.</p><p>Look no further than my favorite example of sustained business transformation: Nintendo.</p><p>Nintendo has a <a href="https://en.wikipedia.org/wiki/History_of_Nintendo">tumultuous history</a> spanning over 100 years, starting as a playing card company in the late 19th century.</p><p>Nintendo was successful for decades, then struggled, then partnered with Disney in the 1950s, found success again, and went back to struggling in the 1960s.</p><p>At some point during that struggle, Nintendo tried everything in sight to get out of the slump, from manufacturing food to vacuum cleaners and toys.</p><p>And how did Nintendo transition out of stagnation in the 1960s?</p><p>Through the creativity of a <a href="https://en.wikipedia.org/wiki/History_of_Nintendo#1966%E2%80%931972:_Toy_company_and_new_ventures">maintenance engineer turned product designer</a>:</p><blockquote>In 1966, Yamauchi [Nintendo’s President at the time], upon visiting one of the company’s […] factories, noticed an extending arm-shaped toy, which had been made by one of its maintenance engineers, Gunpei Yokoi, for fun. Yamauchi ordered Yokoi to develop it as a proper product for the Christmas rush. Released as the Ultra Hand, it became one of Nintendo’s earliest toy blockbusters, selling over hundreds of thousands units. […] Yokoi was soon moved from maintenance duty to product development.</blockquote><blockquote>Due to his electrical engineering background, it soon became apparent that Yokoi was quite adept at developing electronic toys. These devices had a much higher novelty value than traditional toys, allowing Nintendo to charge a higher price margin for each product. Yokoi went on to develop many other toys, including the Ten Billion Barrel puzzle, a baseball throwing machine called the Ultra Machine, and a Love Tester.</blockquote><p>Fun fact: <a href="https://www.shacknews.com/article/137704/nintendo-ntdoy-playing-card-revenue-fy-2024">Nintendo still makes playing cards</a>.</p><h3>When Change Requires Theft</h3><p>Earlier in this story, you may have noticed the “stealing” references between roles in the PST model, with settlers stealing from pioneers, town planners stealing from settlers, and pioneers borrowing components from town planning resources.</p><p>It may not sound good, but it makes perfect sense.</p><p>As pioneers find something with growth potential, it is time for settlers to make that growth happen. That transition is never smooth because settlers may appropriate the tools and techniques and even deprive pioneers of the credit. Look no further than the contentious debate on Elon Musk being a pioneer or a settler in the founding of <a href="https://en.wikipedia.org/wiki/Tesla,_Inc">Tesla Motors</a>.</p><p>As a business reaches a certain status and becomes a commercial success, it is natural to “industrialize” the money-making sectors of that business, multiplying the profits per unit across more units. The search for differentiation and adaptation, a vital aspect of the settler routine, is the enemy of efficiencies and maximum gains.</p><p>And when everything is organized for maximum efficiency to the detriment of all else, it is time for the organization to carve out resources to form an expeditionary force of pioneers.</p><p>The circle of change is complete, and once again, the same goes for individuals:</p><ul><li><em>“That idea was mine”</em> precedes the hard truth that the pioneer behind it was content to have the idea and not explore it.</li><li><em>“They stopped investing in our project”</em> precedes the reality that the project peaked a couple of years ago.</li><li><em>“Some people get to have fun exploring new things”</em> negates the reality that new ideas and opportunities keep the organization adaptable to changes in the environment.</li></ul><p>Once again, the <em>same goes for individuals</em>, who may overstay in a productive role where their skills are a perfect fit for their project needs. In that stagnant arrangement, everything they know is useful to the project, their importance grows, and their careers advance.</p><p>As projects and products inevitably reach a plateau and start to decline, successful software developers may suddenly find themselves at the top of the wrong hill.</p><p>They miss their exit turn.</p><h3>Master of Journeys, not Destinations</h3><p>To bring the theory full circle toward practice, let’s use the dispirited trek of our QA colleagues in the story opening. Organizations focusing heavily on town planning activities need quality control more than quality assurance.</p><p>Conversely, portions of the organization pioneering new technologies may not have much output to worry about quality controls or assurances. Awareness of the territory tells QA engineers to seek roles in growth areas where quality matters and the nature of what is measured is constantly changing.</p><p>Yes, I am saying QA engineers, at their core, are settlers.</p><p>But can a settler-at-heart thrive in town planning? Yes, it is a fractal of change, remember?</p><p>As the business looks to streamline processes, often through automation, there is still room for <em>_fewer_</em> individuals to develop new techniques to optimize the processes.</p><p><strong>A Case Study in Adaptation</strong></p><p>As a concrete example, let’s say you work in the QA activities for a mature product line. You then automate a process that simulates chaos in the environment running the product code. The simulation would include things such as turning off network firewall rules, restarting VMs, killing processes, and such.</p><p>Since these simulators already exist, building a new process around them is a “settler” principle (reusing existing technology developed by pioneers). And the new process can be applied to an organization in “town planning” mode, introducing a low-cost approach that can be embedded into other quality control pipelines.</p><p>Take that idea a step further; you can pair up with an SRE team to embed that new process into the early stages of a SaaS pipeline. Now, we have the potential to notify software developers about the high-availability characteristics of their code changes in the context of their pull requests.</p><p>Take that potential even further, and such technology can create chaos in a production environment and gauge its resiliency in the face of actual outages.</p><p>Is that pioneering?</p><p>Not really; Netflix <a href="https://netflixtechblog.com/chaos-engineering-upgraded-878d341f15fa">did it</a> some nine years ago. Remember, settlers steal from pioneers — and I am not talking about stealing credit, just the output.</p><p><strong>There is Always a Path</strong></p><p>If you are not a software developer but feel like software developers get all the credit, the way forward is to inject more coding into your work.</p><p>For example, if you are a <strong>technical writer</strong> and your product has an API, create a better way of validating code samples in documentation examples. If the product only has a graphical user interface, find a way to use LLMs to generate documentation pages while a bot monitors users iterating with the product interface. There is (almost) always a way.</p><p>And if you are an <strong>SRE</strong>, we are living through a golden age of opportunity for AI-assisted operations, with LLMs increasingly showing potential in helping people formulate commands during critsits or perform basic <a href="https://itnext.io/kubenstein-a-gpt-powered-kubernetes-administrator-a8334f413d6f">troubleshooting assessments</a>.</p><h3>Keep Moving, Keep Building</h3><p>On a smaller scale, because the map of change flows is a fractal of smaller PST models, even being in the “wrong” PST pillar for your working style does not mean a life sentence of devaluation and disgruntlement:</p><ul><li>Even the most pioneering teams need some order.</li><li>Even the fastest-growing businesses need standardization and stability to avoid chaos.</li><li>Even the most profitable mature business can use innovation in smaller uncharted processes.</li></ul><p>While these smaller actions can make you more valuable to your organization — and happier, too — the moral of the story is that when the only constant is change, becoming a specialist in navigating change is a core competence to succeed in our profession.</p><p>And now you have a map, too.</p><p>As long as you are willing to keep moving, your present situation is just a stop on the way to where the organization needs you.</p><p>If commerce downtown is too crowded or life as a shopkeeper is not for you, there is always money to be made transporting goods across town limits or erecting new buildings.</p><p>If something doesn’t exist, create it.</p><p>If it exists and is valuable, build upon it.</p><p>If something works, keep doing it, but keep looking for the next thing.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d408a3c3fe2b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Ultimate Guide for Making the Best Career Choices in Tech]]></title>
            <link>https://dnastacio.medium.com/hierarchy-of-career-priorities-c18768d32598?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/c18768d32598</guid>
            <category><![CDATA[careers]]></category>
            <category><![CDATA[software]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[leadership]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Thu, 04 Jan 2024 14:25:11 GMT</pubDate>
            <atom:updated>2024-01-10T20:16:44.798Z</atom:updated>
            <content:encoded><![CDATA[<h4>Finding Your Purpose Is the Goal. Making the Right Choices Is the Path.</h4><figure><img alt="Drawing of a pyramid in the desert, with a software developer sitting at a workstation facing the pyramid. The pyramid has five layers labeled from bottom to the top, as follows: Employability, Compensation, Growth Path, Well-Being, and Meaning." src="https://cdn-images-1.medium.com/max/1024/1*8tp3caPQO7klijrsv2JDlw.png" /></figure><p><em>“How hard can it be to find a new Java developer?”</em></p><p>I was asked this question by our engineering director, frustrated with my lack of progress in finding a new software developer for our project.</p><p>By then, I had interviewed several candidates and concluded they would not be successful in the role.</p><p>Our team found a good fit a couple of weeks after the nudge, so I never had to explain the real reason why I did not recommend the previous candidates.</p><p>It was us, not them.</p><p>My reservation, which I helped the candidates understand, is that while they could meet the immediate requirements of the project — we would be fortunate to have them aboard — working with our technology stack was not an optimal choice <em>for them</em> in the long run.</p><p>With enough time passed and that entire project no longer active, I can explain my assessment using a structured framework.</p><p>In this story, I explain that framework and share a couple of personal anecdotes illustrating why it is relevant whether you are starting or well underway in your professional career.</p><h3>The Framework: Hierarchy of Career Priorities</h3><p>Let’s start with an adaptation of <a href="https://www.simplypsychology.org/maslow.html">Maslow’s Hierarchy of Needs</a>, which I’ll call the “<em>Hierarchy of Career Priorities</em>.”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZLzaMZA89qtef6Es69vP4g.png" /><figcaption><em>Hierarchy of Career Priorities: an adaptation of Maslow’s social theory of “Hierarchy of Needs.</em>”</figcaption></figure><p>Like in Maslow’s theory of layers of priorities before reaching a state of self-actualization — where one has the continuous desire to become the most they can be — my framework for career success works in the same way, with analogous layers as follows:</p><ol><li><strong>Employability</strong>. This foundational layer matches Maslow’s “Physiological Needs” layer. It represents the basic requirements for entering the workforce, including relevant education, training, degrees, and skills demanded by the job market.</li><li><strong>Compensation and Stability</strong>. This layer represents having a steady job, adequate compensation matching the required time and skills to do the job, and a supportive work environment.</li><li><strong>Growth and Development</strong>. This layer involves continuous learning, skill enhancement, and professional development. In this layer, a job allows and <em>requires</em> professionals to develop their skills to perform the role and retain their future employability. The layer also includes the <em>viability and growth trends of the project’s business case</em>.</li><li><strong>Work-Life Balance and Well-Being</strong>. This layer is about balancing work and personal life, supporting the employee’s overall well-being. This layer focuses on maintaining a healthy work-life balance, managing stress, and prioritizing mental and physical health.</li><li><strong>Purpose and Meaning</strong>. The pinnacle of the “Hierarchy of Career Priorities,” where individuals seek purpose and meaning in their chosen careers. This layer involves aligning personal values with the professional career, making a positive impact, and finding fulfillment beyond material and external rewards.</li></ol><p>Ideally, employment choices should favor a good alignment of these layers. It is impossible to align them perfectly at all times, but awareness of eventual imbalances allows one to correct them sooner rather than later.</p><p>Here are a few common examples of such imbalances:</p><ul><li>A generous compensation package incentivizing people to sacrifice their well-being with long work weeks and stressful air travel routines.</li><li>Overstaying in a role with a stagnant “growth and development” layer.</li><li>Becoming overly skilled in an aging technology stack, trading growth in the current job for employability in the broader job marketplace.</li></ul><p>I’ll reference this framework throughout the following sections, listing some of the most important lessons I learned about success and failure throughout my career.</p><h3>Lesson #1: Technology Stacks Define Employability</h3><p>This lesson is more of a blind spot for project managers and HR leaders than for software developers.</p><p>The advice of <a href="https://darshakrana.medium.com/the-best-career-advice-i-ever-received-learn-or-earn-or-quit-3750c7c3be8f"><em>“Learn or Earn”</em></a> works when you are starting in your career, but it morphs to <em>“Learn or Don’t Earn”</em> as you progress.</p><p>Within the last 40 years, the software industry went from co-dependent relationships of job-for-life using a few on-prem technology stacks to one of <a href="https://customers.ai/articles/employee-tenure-in-tech-companies">impossibly short tenures</a>, leading employers to <a href="https://www.linkedin.com/pulse/job-hopping-bad-get-hired-by-linkedin-news/">reconsider “job hopping” as a negative trait</a>.</p><p>As a result, successful employees used to lifelong tenures now have to anticipate technology trends and grapple with the reality of becoming obsolete while standing still.</p><p>Note I am not passing a personal judgment on any technology. I am just reflecting on hiring practices in general, where employers increasingly use automation to match candidate resumes to opportunities.</p><p>HR folks may point to periodic formal training to stay current with trends while working with aging technology. However, there is a realization among software developers and employers that skills not practiced on the job dissipate quickly between forgetfulness and irrelevance.</p><p>As an example, when an employer needs someone with five years of experience in React, their vetting process will most certainly discard a resume showcasing a long experience in <a href="https://www.oracle.com/java/technologies/javaserverfaces.html">JavaServer Faces</a> even if it contains a bullet point about a React class taken a couple of years ago. Conversely, any company using JavaServer Faces as their primary UI framework <em>today</em> will most likely struggle to attract new talent to their fold.</p><p>For those reasons, and acknowledging this may be a difficult realization for employers: From a continued employability perspective, <strong><em>a product technology stack is the most crucial factor for employees</em></strong>.</p><p>Yes, <a href="https://thomasgriffin.com/people-quit-bosses/">a bad boss can make one quit</a>, but even the best of bosses will struggle to recruit people to work with a technology stack with dwindling demand in the job market.</p><p>While I understand product managers and organizations not being keen on rearchitecting or rewriting portions of the technology stack for employability reasons, they should consider a periodic conversation with HR leaders, trying to understand what effect their projects may have on the future employability of their staff.</p><h3>Lesson #2: Three Years as the Period of Obsolescence</h3><p>Technology stacks may stay relevant for a long time. Look no further than the enduring staying power of programming languages like COBOL or hardware technology like mainframes.</p><p>However, not <em>all</em> technology stacks stay relevant.</p><p>For everything else not powering the business core of the modern world, three years is a magic period where new technology can suddenly fall out of favor with the technical community.</p><p>If you are deciding on the next step of your career or the next hot technology to learn, skip the temptation of chasing what is popular today and look at what is trending towards popularity within the next three years.</p><p>Note that &quot;three years&quot; is primarily an empirical observation.</p><p>To illustrate that observation, let&#39;s start with the progression in the adoption of programming languages for the past decade, measured indirectly by GitHub&#39;s analysis of its user activity:</p><figure><img alt="Adoption rankings for the top-10 programming languages since 2014" src="https://cdn-images-1.medium.com/max/1024/1*KYcE4izI9mPBHLNqs_xuRA.png" /><figcaption><em>Credit to GitHub’s article </em><a href="https://github.blog/2023-11-08-the-state-of-open-source-and-ai/"><em>“The state of the Octoverse 2023</em></a></figcaption></figure><p>Why use programming languages as a proxy for technology stacks? Because the adoption of programming languages correlates with shifts in the technology landscape, such as Ruby’s fortunes being tied to the popular <a href="https://en.wikipedia.org/wiki/Ruby_on_Rails">Rails framework</a>, COBOL adoption relying exclusively on the mainframe ecosystem, and C# being the programming language of choice for the .Net platform.</p><p>In three years, between 2015 and 2018, the Ruby programming language fell sharply through the rankings, from spot number 5 to number 10, fading behind <a href="https://thenewstack.io/typescript-getting-popular/">Typescript’s growing popularity</a> as a superset of the reigning champion in programming language’s popularity: JavaScript.</p><p>Incidentally, in an equal span of 3 years, between 2017 and 2020, Typescript sky-rocketed from number 10 to number 4.</p><p>And look at what happens to PHP, a stalwart of employability holding out against the proliferation of web-development frameworks all the way to 2019, when it started dropping quickly through the ranks from number #4 to #7 by 2022.</p><p>If you were starting your career today, mastering any programming language that is not mainstream within your field of interest is a liability for future employment prospects.</p><p>By “mainstream,” I mean choices such as Javascript for front-end development, Python for machine learning, and Go for systems development. You may disagree with my specific examples — for example, choosing Rust over Go — but the principle remains.</p><p>If you prioritize employability, find the moving center of the mainstream and aim for it.</p><p>The following section will cover the risk of overshooting that target.</p><h3>Lesson #3: Watch Out for That Bleeding Edge</h3><p>Anyone who regularly rode a bus has learned to make a critical judgment call.</p><p>That call happens when you are late walking up to the stop and can see from a distance that the bus is already loading the passengers. In that moment, you must decide whether to sprint toward the stop or wait for the next bus.</p><p>You also learn that chasing an already moving bus is rarely worth it.</p><p>While looking at future trends, keeping an eye on employability over hype is essential. I don’t mean people should ignore new trends — jumping on them can be rewarding in itself — but I would not advise people to go all in into those trends without a hedge on the “Growth and Development” layer being advanced in other ways, such as high-visibility or leadership positions.</p><p>Be advised that there is a lot of course-correcting and damage control to manage that edge while the users try to build worlds atop the moving blade. In other words, work-life balance tends to suffer.</p><p>My cautionary tale here comes from first-hand experience during the cut-throat years between 2013 and 2015 — another three-year span — where <a href="https://blogs.vmware.com/opensource/2020/06/25/the-past-present-and-future-of-cloud-foundry-part-1/">Cloud Foundry</a> and Docker initially defined and dominated the container orchestration world.</p><p>My employer teamed up with <a href="https://en.wikipedia.org/wiki/Pivotal_Software">the creator of Cloud Foundry</a> and launched its public offering in early 2014. Known as Bluemix, that offering quickly became the world’s largest Cloud Foundry deployment, with over one million users. By many accounts, it was an unmistakable success.</p><p>I joined that project from the onset as its production engineering lead, coming straight from a role as the technical leader for three software development teams. It was a wide lateral jump, so it was also a big gamble.</p><figure><img alt="Pyramid diagram with five layers, from top to bottom: “Employability,” “Compensation and Stability,” “Growth and Development,” “Work-Life Balance and Well-Being,” “Purpose and Meaning.” The “Employability,” “Compensation and Stability,” and “Growth and Development” layers have a slot machine next to them. The layer for “Compensation and Stability” has a checkmark next to it, while the “Work-Life Balance and Well-Being” layer has a fail symbol next to it." src="https://cdn-images-1.medium.com/max/1024/1*Zy5aNGZSfsFqA5Fc18Cjtw.png" /></figure><p>There was one planet-scale obstacle in my jumping arc.</p><p>Later that year, our company also made a parallel investment in a <a href="https://www.ibm.com/products/kubernetes-service">new offering</a> based on an open-source project with a funny Greek name. Google released Kubernetes early in 2014 as an orchestrator of Cloud workloads. It had the pedigree of underpinning the mind-bending scale of Google’s own workloads.</p><p>With a billion-dollar investment and an all-star line-up of talent and developer advocates behind Kubernetes, the competition was over before it even started.</p><p>In the relatively short span of three years, Cloud Foundry and Docker Enterprise had lost all momentum in new deployments. Existing customers spent years grappling with the costly reality of re-platforming their workloads, retooling their CI/CD pipelines, and retraining their employees into a new world of Kubernetes clusters.</p><p>For me, it was not a wrong career move in absolute terms. I met people from different backgrounds, and the grueling demands of the on-call schedule for something at that scale meant a considerable compensation increase. And even after all these years, I am convinced that <a href="https://dnastacio.medium.com/how-to-outperform-a-10x-developer-fa1132807934">every software developer should rotate through operations</a> for a few years.</p><p>Still, by the end of that transition, my Cloud Foundry skills were worthless in the job market.</p><h3>Lesson #4: Beware the Highly Specialized Domain Projects</h3><p>This lesson comes from the project I joined immediately after my Cloud Foundry stint. It is also the project mentioned earlier in this story, where we struggled to fill out a software development position.</p><p>The product was a hosted offering for healthcare providers in the oncology field. From a technology perspective, there was a strong focus on bioinformatics and natural language processing.</p><p>The most significant appeal for me was the opportunity to work with lab scientists and actual medical doctors. Applying NLP to help oncologists find alternative, life-saving care for cancer patients fulfilled the “Meaning and Purpose” layer in ways that no other project in my career ever had.</p><p>However, the technology stack was entering the three-year period where it would quickly fade behind the times, especially for a SaaS offering.</p><ul><li>Hosting? Everything ran on VMs. There was not a container in sight.</li><li>Programming language? Java.</li><li>Persistence layer? DB2.</li><li>UI? AngularJS.</li><li>Task management and source-code control? <a href="https://jazz.net/library/article/87559">Jazz</a>.</li><li>CI? Ant and Jenkins.</li><li>CD? Largely manual, with multi-hour planned maintenance windows.</li></ul><p>With the unforgivable exception of using the aging Ant framework over <a href="https://maven.apache.org/">Maven</a> in the CI layer, everything else would have been a solid choice a couple of years before the project was commissioned.</p><p>In short, the choices were perfectly sensible, well-executed, and cost-effective. Decisions to stick with stack components were sound from a business perspective, but as an experienced software developer, this stack was the highway to skills obsolescence.</p><p>A small yet significant example is the usage of the Jazz source-code control. The year I joined the project was also the year our company formed its <a href="https://www.prnewswire.com/news-releases/ibm-and-github-form-strategic-partnership-to-offer-first-github-enterprise-service-in-dedicated-and-local-hybrid-cloud-300223775.html">strategic partnership with GitHub</a>, paving the way to replace Jazz with GitHub repositories for internal projects. Our project never migrated from Jazz because it made no business sense to forklift all code and build processes to a new source code control system, let alone retrain all developers to use Git.</p><p>Still, from the perspective of software developers, the “employability” value of Jazz skills trended toward irrelevance in the ensuing years, almost in inverse proportion to the value of Git, GitHub, and GitLab skills.</p><p>Moving to a more relevant example, querying all the alterations in a genetic sample stored in a database did not require a software developer to understand cancer biology. It required good communication with the actual cancer biologists on the team, explaining the immediate table structure representing the data and figuring out which attributes on a table represented those unique alterations.</p><p>At the same time, the database world was witnessing the expansion of job market demand for skills in MongoDB — the poster child of NoSQL databases — <a href="https://cassandra.apache.org/">Cassandra</a>, <a href="https://neo4j.com/">Neo4J</a>, Apache <a href="https://spark.apache.org/">Spark</a>, and <a href="https://hadoop.apache.org/">Hadoop</a>.</p><p>And while Java was — and remains — a desirable skill in the job market, people working with the project backend watched Python slowly take over as the primary programming language for anything related to machine learning and natural language processing. If that was not sufficient, Facebook and Google released <a href="https://pytorch.org/">PyTorch</a> and <a href="https://www.tensorflow.org/">TensorFlow</a> in rapid succession, increasing the pace of skills obsolescence for those working on machine learning problems in Java.</p><p>In a couple of years, our technology stack went from sensible to something no one would consider for a new project in the same domain.</p><figure><img alt="Pyramid diagram with five layers, from top to bottom: “Employability,” “Compensation and Stability,” “Growth and Development,” “Work-Life Balance and Well-Being,” “Purpose and Meaning.”. The layers of “Employability” and “Growth and Development” have fail symbols next to them." src="https://cdn-images-1.medium.com/max/1024/1*n-onUUaDwPOPlRhaHJfBnw.png" /></figure><p>Ultimately, <em>that</em> is why we struggled to find new software developers while, at the same time, the sciences team managed to recruit increasingly more impressive talent.</p><p>Even without this story’s career framework clear in my head at the time, I would be open with candidates about the trade-offs between the unique opportunity of working in a specialized domain and the negative impact on their long-term growth and development.</p><p>Some candidates had a specific interest in the bioinformatics and NLP components of the project. Since we were not hiring for those areas, I was equally open about eventual work on those components being strictly dependent on changes to their job roles and, therefore, not guaranteed.</p><p>I still <a href="https://sourcepatch.blogspot.com/search/label/clinical_trials">cherish the experience</a>, but here is the painful reality for software developers working with undifferentiated technology in a highly specialized domain: domain experts are essential; software developers are not.</p><p>That reality would be punctuated three years into the project when it became clear that demand would not translate to meaningful financial results.</p><p>The team was considerably downsized to stretch its budget runway while hoping for a turnaround. Anyone not working directly with bioinformatics or machine learning — most of its career software developers — was asked to find other opportunities with the company, myself included.</p><h3>Lesson #5: There Is Always Time Until There Isn’t</h3><p>Back to the bus-riding analogy, there is something worse than missing a bus: boarding the wrong one.</p><p>My cautionary tale in this story is that even though I was clear in my objective of shifting to Cloud-based software development for several years, in between a failed start with Cloud Foundry and an attractive side-step into the world of life sciences, six years went by in what today feels like the blink of an eye.</p><p>For someone mid-career, six years is a dangerously long detour.</p><p>It took me a new job and another three years to catch the Kubernetes bus and take a seat, becoming skilled on the platform and acknowledged as someone who could <a href="https://medium.com/@dnastacio/the-art-and-science-of-probing-a-kubernetes-container-db1f16539080">advise other developers</a> and <a href="https://dnastacio.medium.com/running-knative-services-on-aws-spot-instances-5b73202e89dc">system administrators</a>.</p><p>Nine years had passed.</p><figure><img alt="Sticky-figure drawing of person looking down a deep hole, from where a software developer works in front of a laptop on a desk." src="https://cdn-images-1.medium.com/max/1024/1*DUwl0rdCIP38EHq7vOh-KQ.png" /></figure><p>For someone starting fresh from college today, six years traveling in the wrong direction is a career-defining interval.</p><p>Many will point out that the “wrong direction” is relative and that having a diverse background before starting a software development role later in life is possible, even <a href="https://www.infoq.com/articles/great-engineer-needs-liberal-arts/">desirable</a>.</p><p>I do not disagree. In fact, one of my <a href="https://mrfeinberg.com/">favorite software developers</a> has a degree in Literature and spent over a decade playing various musical instruments at shows before starting a successful career in software development.</p><p>However, once one gets in the groove of a career path in tech, indulging in career detours and missing consequential technology shifts can often derail their progress for quite a while.</p><p>Yes, we always have time, but career steps are measured in years, and the margin for recovery decreases with each passing year.</p><h3>Conclusion</h3><p>My best career advice to software developer professionals, well, any professional, is to continuously monitor their career progression against the layers of their “Hierarchy of Career Priorities.”</p><p>There are no wrong career paths, but there are certainly careless steps. Something as simple as placing an “up” or “down” arrow next to each layer in the pyramid can go a long way toward helping one make the best decision about staying in their current role or moving to a new one.</p><p>With awareness, one may optimize for one or more layers, such as choosing a higher compensation over a more interesting job or sacrificing their work-life balance for faster progress toward their life goals.</p><p>One may also skip hierarchy layers altogether, such as deciding to work for a dream non-profit with virtually no compensation or betting on a startup gig with compensation tied to the uncertain guarantee of the company’s success.</p><p>However, those imbalances tend to catch up with the natural order of priorities in the pyramid. The imbalances manifest in different ways, such as depression induced by lack of meaning on the job, burnout from long stretches of 80-hour work weeks, or deteriorating employability due to working with obsolete technology stacks.</p><p>And dream jobs may not be that satisfying when one is constantly awakened from the dream by unexpected bills or stressing out with personal finances between irregular paychecks.</p><p>No matter the chosen path, having a framework to evaluate your career is your best tool for making judgment calls, whether extending a bet on a risky choice or bailing out when a job becomes a potential liability to your career prospects.</p><p>That framework is also invaluable for companies gauging their attractiveness to prospective candidates, especially when technologies can shift faster than projects can respond to those changes.</p><p>And finally, keep aiming for purpose and meaning.</p><p>Be successful.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c18768d32598" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Three Steps to Solve All Your Problems in Tech]]></title>
            <link>https://dnastacio.medium.com/three-steps-to-solve-your-problems-in-tech-2169d2145de3?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/2169d2145de3</guid>
            <category><![CDATA[problem-solving]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[critical-thinking]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[leadership]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Sun, 26 Nov 2023 18:23:58 GMT</pubDate>
            <atom:updated>2023-12-04T22:03:14.753Z</atom:updated>
            <content:encoded><![CDATA[<h4><em>Where Clarity Leads, Solutions Find Their Way</em></h4><figure><img alt="Sticky figure style drawing of a person asking another person for help with a small puzzle." src="https://cdn-images-1.medium.com/max/1024/1*a5_kQJxutOSMfgtIvfKs2g.png" /></figure><p>We can describe most problems as <em>“Something is not working like it should.”</em></p><p>When things don’t work as expected, it is time to practice some form of <a href="https://en.wikipedia.org/wiki/Problem_solving">problem-solving</a>. For example, if we want to restore a system to a running state, we can try probing methods such as <a href="https://en.wikipedia.org/wiki/Root_cause_analysis">Root cause analysis</a> or <a href="https://en.wikipedia.org/wiki/Five_whys">Five Whys</a>. If the problem involves challenging requirements while developing a new product, we may favor an exploratory method such as <a href="https://en.wikipedia.org/wiki/Design_thinking">Design Thinking</a>.</p><p>And when it all fails and a problem exceeds our skills and resources, it may be time for the well-known problem-solving method of <a href="https://en.wikipedia.org/wiki/Help-seeking"><strong>help-seeking</strong></a>.</p><p>Asking for help is a familiar routine in a virtual world with an infinite supply of “somethings” that can fail or misbehave at any time, creating familiar challenges all around:</p><ul><li>Ask for help too early, and you risk wasting someone else’s time.</li><li>Ask for help too late, and you risk missing an important delivery date.</li></ul><p>It is in between those extremes that most organizations struggle to find balance.</p><p>Recognizing when to seek help and how to be ready to receive that help is the foundation of the help-seeking social contract, minimizing wasted time and maximizing collective progress.</p><h3>Sometimes, It Does Hurt to Ask</h3><p>One may argue that when the delivery dates are slipping or the <a href="https://www.atlassian.com/incident-management/kpis/sla-vs-slo-vs-sli">SLA</a> service credits are flying out of the window, it is always time to seek help. Right?</p><p>Not quite. We need to do some homework first.</p><p>Here is an example:</p><blockquote>Developer: “<strong>@channel</strong> My nginx server isn’t working. What could it be?”</blockquote><blockquote>Slack UI: “Uh, Chief, do you really want to alert 3284 people across 11 timezones?”</blockquote><blockquote>Developer: “Yes, Mr. Bot. This is the darkest hour. Wake them up. The whole lot.” &lt;clicks “Send”&gt;</blockquote><p>Twelve replies into a hailstorm of reprimands and lectures from the channel constabulary, someone finally breaks through the virtual mob: <em>“Is it accepting connections?”</em></p><p>The hapless developer answers <em>“No,”</em> confused by the question’s relevance because <em>“I already said it isn’t working!”</em> He awaits what must surely be a final solution in the following answer, but nothing happens. The helpful bystander is seemingly gone for the day. But fret not; the developer messages his local senior developer and repeats the original question.</p><p>With all forward momentum converted into heat, wear, and tear, the developer awaits the rescue. Sitting by the side of the virtual road — a terrible place to be — the developer rationalizes his situation, reminiscing about the advice received earlier in his career:</p><ul><li><em>“Don’t spend too much time on it. If you get stuck for more than an hour, reach out.”</em></li><li><em>“Don’t be afraid to ask for help. We are here to support each other.”</em></li></ul><p>Those are unquestionable truths, but they are of the guardrail kind. They focus on what should not happen but don’t guide people on how much time is too much nor set the bar for a question being perceived as too basic.</p><p>What our hypothetical-but-all-too-real developer needs are clear expectations and usable guidance that make problem resolution more accessible and attainable.</p><p>That is this story’s topic, divided into three simple steps.</p><h3>Step #1: Trust the Crowd. The Answers Are Out There</h3><p>There was a time when the developers building the product or the system were the only source of information.</p><p>Getting things to work was challenging enough, and making documents user or task-friendly was an afterthought. Access to other users was limited, as was the access to the product’s source code. Finding information about the system and existing problems was protracted and meticulous work.</p><p>That was a long time ago.</p><p>Except for bespoke systems built in-house by a handful of people, everything else nowadays is behind well-documented service APIs or available as open-sourced code. Access to information about products, libraries, and services in a modern Cloud environment is a solved problem. We can always gripe about some blind spot here and there, but the junior engineer of today is two web searches away from being <em>more</em> effective in solving their problems than a senior engineer of twenty years ago.</p><p>Beyond factual information answering simple <em>“what is”</em> and <em>“where can I find” </em>questions, public forums are treasure troves of information.</p><p>For all the complaints about the toxicity in web forums, muscle through the noise and you can find threads filled with valuable discussions. There, you will discover seemingly random people who post the correct answers to questions and debate the nuances of why incorrect answers are wrong and the range of situations where solutions will work. Hang around the comments section for an extra moment or two, and you can pick up on many other clues and related links to help solve the problem.</p><p>AI-powered bots like ChatGPT can also answer questions. However, I think the sanitized format of the answers does not offer the same rich learning experience of following one’s nose through web search results. After all, isolating positive signals from background noise is an invaluable problem-identification skill.</p><h3>Step #2: Keep Moving. Help Will Follow</h3><p>In nature, being stuck is a precursor to death. Conversely, in the virtual world, being stuck is a precursor to virtual death.</p><p>Lack of progress is depressing and demoralizing. It kills the spirit instead of the body. Yielding control over your progress to someone who can help restore that progress is a last resort to be used sparingly.</p><p>I am not writing this to shame people into not asking for help, but there are ways of asking for help <em>without</em> stopping while waiting for help.</p><p><em>“What if I really don’t know what to do? Should I be afraid to ask for help?”</em></p><figure><img alt="Help signal projected in the city skyline at night. A sticky figure man looks at it from a distance." src="https://cdn-images-1.medium.com/max/1024/1*LMW1VO3w1S_vAKKH0EY6kA.png" /></figure><p>No, you shouldn’t be afraid. The time to ask for help may come and will be covered in the next section, but you probably can do a couple more things to keep moving. How many times have you asked a question only to think of the answer a minute later? That is your brain working through the intricate lattices of <a href="https://www.khanacademy.org/science/health-and-medicine/executive-systems-of-the-brain/cognition-lesson/v/semantic-networks-and-spreading-activation">semantic networks and spreading activation</a>.</p><p>As you shift your focus from solving the problem to describing the problem, your brain fetches different schemas to convey the information from a different angle. Those different perspectives often give you a clear line of sight to the problem’s resolution.</p><p><em>“So, should I ask my question or not?”</em></p><p>While you can keep working the problem in your head talking to a <a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging">Feynman’s rubber duck</a>, having access to a large team channel or Internet forum offers a powerful alternative: sharing the problem and working steps with others <em>while you are still trying to solve the issue</em>.</p><p>To quote comedian and philosopher Chris Rock:</p><blockquote>“I used to have horrible cars that would always end up broken down on the highway. When I tried to flag someone down, nobody stopped. But if I pushed my own car, other drivers would get out and push with me. If you want help, help yourself.”</blockquote><p>You can bring that lesson to software development and systems operations by framing your problem in a public thread like this:</p><blockquote>“Hey, I am seeing the error message “XYZ” in this system. I am still working through it and will be posting my findings as a thread. Chime in if you have seen this message.”</blockquote><p>Assuming you took the first step to heart and the solution to your problem is not the first result of a web search, starting such a thread in plain view of channel participants brings in multiple benefits:</p><ol><li>You can keep moving because you have not yet exhausted your resources and options.</li><li>People can help you in their own time, so you are not interrupting their flow.</li><li>Other people interested in the topic can follow the thread.</li><li>Reframing the problem as something that can be shared with others can help you solve the problem</li></ol><p>If later you find the solution and the question is not too basic after all, then you can post the answer and other people hitting that problem in the future can find a ready-made solution.</p><p>With this step, you are not flagging cars down the road; you are stopping to help others push their broken cars. And because this is a virtual world with little distinction between footprints and the body leaving them behind, you may be helping others without knowing.</p><p>Personally, I am somewhat spoiled by working in a large company with large Slack channels. My searches in our internal workspaces turn up a helpful answer 95% of the time when I hit a new problem. They turn up a working solution in almost 80% of the cases. And for the remaining 20%, taking the failed search to the Internet brings the search-to-solution ratio to almost 100%.</p><p>One can still be highly dependent on others to complete their work, but one doesn’t need to be blocked waiting for help.</p><p>If you worked through the first two steps and still haven’t found a solution, it is time to ask someone to commit their time and resources to assist with the resolution. The following section shows how one can maximize their odds and minimize their losses (of time) by gathering a few facts ahead of time.</p><h3>Step #3: Gather Your Facts. It is Show (Me) Time</h3><p>As that hypothetical developer in the introduction should have realized, being ready to request assistance can make the difference between receiving a solution or another question.</p><p>A senior developer may be able to bridge the gap between what is provided and what is missing, but that is a wasteful process where precious time is spent on gathering facts that do not require any domain expertise. Just like we shouldn’t use a torque wrench as a breaker bar or a scalpel to open a plastic bag, we shouldn’t use an expert’s time to gather basic facts about the problem.</p><p><em>“OK. How much information about the problem is information enough?”</em></p><figure><img alt="Sticky figure drawing of a person explaining an error to another person. Both are thinking about a system diagram, but the diagrams imagined by each person are completely different." src="https://cdn-images-1.medium.com/max/1024/1*R8MD64ISs0x7Qt7mWsfrlw.png" /></figure><p>This is a question of context.</p><p>When you pose a problem to a colleague in the same project, you probably share a lot of contextual information about the project and any new issue — <em>“It is that same problem we saw last week.”</em> Conversely, a stranger maintaining an open-source project will need much more context about a problem you may face with their project. That is why reporting an issue with something like <a href="https://kubernetes.io/">Kubernetes.io</a> requires filling out a relatively thorough <a href="https://github.com/kubernetes/kubernetes/blob/master/.github/ISSUE_TEMPLATE/bug-report.yaml">form template</a> with several fields.</p><p>Following is a checklist I learned from a Critical Thinking coach many years ago, a couple of years into my first assignment as a team lead. I thought I was good at quantifying and qualifying problems until I met this coach, a retired manager in his mid-60s. He made a living by solving problems ranging from homeowner association disputes to CEO succession plans.</p><p><strong>The “What?”</strong></p><ul><li>What is the expected behavior of the product?</li><li>What is the observed behavior in the product?</li></ul><p><strong>The “Where?”</strong></p><ul><li>Does the reported problem happen to all units of the product?</li><li>Does the reported problem affect the entire product or just portions of it? If so, describe the parts of the product.</li><li>Does the reported problem happen in all locations where the product is used?</li><li>Does the reported problem occur in combination with other issues?</li></ul><p><strong>The “When?”</strong></p><ul><li>When did the problem start? If you don’t know, make it clear you don’t know and state when you first observed it.</li><li>What is the frequency? Continuous, cyclic, or random?</li><li>Is the problem specific to the phase in the product life cycle?</li><li>Is the symptom stable or worsening?</li></ul><p>Returning to the initial example in this article, when that anxious developer asked, <em>“My nginx server isn’t working. What could it be?”, </em>can you spot everything that is wrong with it?</p><p>In other words, could you expand the description to a point where an expert without familiarity with that system would not have to ask clarifying questions?</p><p>Going through the checklist, here are a few examples of questions I would be asking about the problem:</p><ul><li><em>“What is the expected behavior of the product?”</em> — Obviously, we want the nginx server to be working, which entails … what? An nginx server can serve diverse purposes, such as reverse proxying, load balancing, and caching. There is room for more precision here, but let’s enter a state of “suspended curiosity” and assume the developer means every possible function available on a typical nginx configuration.</li><li><em>“What is the observed behavior in the product?”</em> — “Not working” is not a behavior. Is the server not starting? Is the server crashing after starting? Is the server rejecting connections? Is the server routing connections to the wrong handler? Is the server hanging while processing requests?</li><li><em>“Does the reported problem happen to all units of the product?”</em> — Are there other nginx servers with a similar configuration working? For example, is this problem only happening on a single instance in a pool of nginx servers where all other nginx servers are working without issue?</li><li><em>“Does the reported problem affect the entire product or just portions of it? If so, describe the parts of the product.”</em> This question goes back to the entire range of functions available on an nginx server. Is there any function that is working? For example, requests to a specific URL may return the expected results, but requests to other URLs hang indefinitely.</li><li><em>“Does the reported problem happen in all locations where the product is used?”</em> If this nginx server template is deployed to multiple Cloud regions, is the problem localized to one or more regions but not all?</li><li><em>“When did the problem start?”</em> Was it on a specific day where you have evidence of the functioning working on the day before? Was it immediately after a configuration change was applied to the environment? Note that this question may be the most difficult to answer because you may not have good observability practices placing the exact moment where the problem starts. In that case, report the first time you or someone noticed the problem.</li><li><em>“What is the frequency?”</em> Are all requests failing, or are some of them going through? If some of them are going through, is there any pattern, such as failures happening continuously for a couple of hours and then working without issue for a few days?</li><li><em>“Is the problem specific to the phase in the product life cycle?”</em> Does the problem only happen after the server was started for the first time after rebooting their hosting VM? Is the problem only happening after the server has been up for a week?</li><li><em>“Is the symptom stable or worsening?”</em> If the problem happens randomly, is the average rate of request failures going up? If the issue only occurs after the server has been up for several days, is that number of days coming down?</li></ul><figure><img alt="Sticky figure drawing of a person explaining an error to another person. Both are thinking of the same system diagram, and the person receiving the information seems to understand the problem." src="https://cdn-images-1.medium.com/max/1024/1*shEhwwittX2Cvh4D076weQ.png" /></figure><h3>Bonus Steps: The Team Side</h3><p>The previous steps covered the individual responsibility aspect of tackling situations where we feel like we could use a hand.</p><p>Flip sides on the help-seeking contract, and there are also measures that the leadership team can put in place, from managers to senior individual contributors:</p><ol><li>Incorporate some version of the problem identification steps in the previous sections into regular onboarding and training sessions, setting the tone and the bar for all team members.</li><li>Favor open-source libraries and components over home-grown bespoke systems. If you want individual team members to lean into crowd-sourced assistance, you need to widen that coverage by using the same technologies and speaking the same language as the crowd.</li><li>Promote and incentivize a culture of team collaboration. Push people toward communication in online forums and problem-tracking systems instead of private messages.</li><li>Organize regular public post-mortem events where software developers and operations people review interesting bugs and outages. An engaging puzzle is at the heart of every bug and outage — just look at <a href="https://github.com/danluu/post-mortems">these</a>.</li></ol><p>A culture of tackling problem identification and dissection head-on is a culture of agency, resiliency, and self-sufficiency. Mutual assistance is still part of the social contract, but it is evenly distributed across offline and online interactions so that people can keep moving — staying engaged and motivated — even if they could use an extra hand.</p><h3>Conclusion</h3><p>The simple steps in this article can help professionals across all experience levels raise their individual problem-solving and problem-reporting skills. With some practice, people struggling with seemingly trivial issues will get stuck less frequently, keeping their motivation and momentum through tasks that felt impossible.</p><p>On the other side of the social contract, senior engineers working on a team that consistently follows those steps spend less time addressing basic questions and less energy trying to fill the gaps in questions and requests. With more disposable time comes a renewed focus on meaningful interactions and real progress.</p><p>For organizations, the newfound self-sufficiency and precision become gains in productivity, quality, and morale.</p><p>The best part is that anyone can practice these steps in a matter of days and experience the benefits immediately in their next few assignments.</p><p>Whether you are looking for help too often or you want to help others in more meaningful ways, consider the problem solved.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2169d2145de3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kubenstein, a GPT-powered Kubernetes Administrator]]></title>
            <link>https://itnext.io/kubenstein-a-gpt-powered-kubernetes-administrator-a8334f413d6f?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/a8334f413d6f</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[chatgpt]]></category>
            <category><![CDATA[kubernetes]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Wed, 11 Oct 2023 11:02:03 GMT</pubDate>
            <atom:updated>2023-10-20T11:09:43.401Z</atom:updated>
            <content:encoded><![CDATA[<h4>But is it any good?</h4><figure><img alt="Diagram showing two parallel flowcharts. In the first flowchart, a person asks me for assistance troubleshooting their cluster, giving them one command at a time and waiting for them to answer. In the second flowchart, an application asks Kubenstein for assistance, with Kubenstein giving the application one command at a time and waiting for the command to complete." src="https://cdn-images-1.medium.com/max/1011/1*W31twSMv_IKCiSlwPHvqTg.png" /></figure><p><a href="https://github.com/nastacio/kubenstein"><strong>Kubenstein</strong></a> is a side-project named after a play on the words “Kubernetes” and “Frankenstein.”</p><p>I wrote it to experiment <em>beyond</em> the more straightforward use cases for GPT-powered assistance to Kubernetes administrators, such as in <strong>querying</strong> cluster resources or in <strong>interpreting errors in cluster messages.</strong></p><p>You can see examples of those scenarios in <strong>CLI extensions</strong> like <a href="https://k8sgpt.ai/">k8sgpt</a> project and <strong>UI integrations</strong> like <a href="https://github.com/robusta-dev/kubernetes-chatgpt-bot">Robustas’ Slack b</a>ot.</p><p>These are natural and valuable additions to existing tools, but Kubenstein goes beyond the sensible and the reasonable.</p><p>The following image shows an excerpt of a conversation between the Kubenstein application and its AI “brain.” The “lines” from Kubenstein back to the AI are the output of the commands suggested by the AI when executed against a target cluster.</p><figure><img alt="Screenshot of a fragment of conversation between Kubenstein and the AI." src="https://cdn-images-1.medium.com/max/1024/1*CrVusOtJBV5siVv7eTC4Fw.png" /></figure><h3>Beyond Language. Intelligence?</h3><p>LLMs can do a great job of natural language processing, deciphering the written commands from a system administrator and summarizing the collective human knowledge about an error message.</p><p>However, beyond language processing, I wanted to explore the possibilities of AIs following <a href="https://en.wikipedia.org/wiki/Script_theory">cognitive scripts</a>:</p><blockquote><em>…human behaviour largely falls into patterns called “scripts” because they function the way a written script does, by providing a program for action.</em></blockquote><p>I wondered whether I could tell Kubenstein how I perform a particular activity and let it attempt to replicate it. For that, I chose a familiar cognitive script for Kubernetes administrators: <em>assessing the cluster health during a troubleshooting session.</em></p><p>Anyone assessing the health of a cluster has their preferred way of going about it. Still, these assessments more or less involve serially inspecting layers of components and looking for errors.</p><p>Along the way, when they bump into errors, they start looking individually into each error for clues. It is never a fixed recipe because one never knows what they are about to find. Still, the outline, the cognitive script, shares many commonalities.</p><p>So I started to think:</p><p><em>“How would an AI perform as the </em><strong><em>driver</em></strong><em> of a troubleshooting session?”</em></p><p>That is right; I didn’t want assistance to be understood more easily or to analyze error messages more efficiently. I wanted something that could follow my mental process and <em>do the work</em>.</p><h3>Chat over Prompts</h3><p>The core goal for Kubenstein is to perform administrative actions without depending on human intervention. For the specific use case at hand, I wanted it to be able to run a troubleshooting session while following my cognitive script for that activity.</p><p>I did not want to throw errors at the AI to get guidance. I didn’t want to be in the middle of the interaction. I wanted Kubenstein to interface with the cluster on its own.</p><p>Kubenstein runs as a <a href="https://github.com/nastacio/kubenstein/blob/v1.0.0/chat.py">standalone Python application</a> on a terminal. It assumes the human administrator has already <a href="https://kubernetes.io/docs/reference/kubectl/">logged in to the cluster using the </a><a href="https://kubernetes.io/docs/reference/kubectl/">kubectl CLI</a> and that the CLI is available in the PATH environment of the terminal.</p><p>It also requires a connection to an AI, such as ChatGPT, to start a chat session with my cognitive script of the task.</p><p>During a troubleshooting session, Kubenstein iteratively requests the next input command from the AI, executes it against the target cluster, and then adds both the AI input and the command output to an array of messages representing the chat.</p><p>That process is repeated, with Kubenstein sending the ever-growing array of messages to the AI so that the AI understands the whole session context. The process ends once the AI responds with a message indicating it has completed the cognitive script.</p><p>In that sense, Kubenstein deviates from the current Kubernetes assistance approaches by mediating a <em>conversation</em> between the AI and the cluster.</p><p>Kubenstein does not attempt to make you faster while troubleshooting a problem; it tries to <em>be you</em>.</p><p>The starting point of that conversation is instructing the AI to act like the system administrator and informing it about the goal of assessing the health of a cluster, providing an outline of how to go about the whole process, and letting it run through the instructions.</p><p>For example, <a href="https://github.com/nastacio/kubenstein/blob/v1.0.0/prompts/troubleshoot-assess.txt">the initial assessment prompt</a> contains phrases like:</p><blockquote>You are a Kubernetes administrator asked to validate whether a cluster is running properly.</blockquote><p>And blocks of instructions like this:</p><blockquote>I want you to help me go through a checklist called “cluster health” step-by-step.</blockquote><blockquote>- Nodes<br>- Storage<br>- Routes<br>- Network traffic not getting blocked<br>- Pods<br>- Events</blockquote><p>More crucially, remember this is a chat session between the AI and the cluster; this is the most important instruction to the AI:</p><blockquote>It is extremely important that you give me a single command at a time and wait for me to execute the command and give you the output.</blockquote><p>The prompt proceeds to clarify what should happen once the AI encounters a problem:</p><blockquote>For each item in the checklist “cluster health”:</blockquote><blockquote>- Wait until you can process the output of a command before deciding what the next best command is.</blockquote><blockquote>- If the output indicates an error in the cluster, add that error to an error list named “error list” and proceed with the checks on the checklist “cluster health.”</blockquote><blockquote>- Once you complete giving me commands for the checklist “cluster health,” we should start troubleshooting the list named “error list.”</blockquote><p>You can read an <a href="https://gist.github.com/nastacio/42a25138413f9a2d61867ebe19b6b354"><strong>example of an entire assessment session here</strong></a>.</p><figure><img alt="Frankenstein monster sitting at a desk in front of a laptop and staring at the screen." src="https://cdn-images-1.medium.com/max/1024/1*NzgJuFGR3HkU6wpR-NeBNg.png" /></figure><h3>Learning As It Goes</h3><p>There is nothing in Kubenstein to try and train it about what to expect and how to react to what it finds, just like I wouldn’t know what to expect while troubleshooting a cluster.</p><p>Personally, if a command shows a problem in the cluster, I adjust to that response before typing the next command. If I make a mistake while typing a command and get an error message, I modify the command and iterate until I get it right.</p><p>So does Kubenstein.</p><p>I must admit there were several moments where I doubted a generative AI could make sense of a long and intricate set of instructions, let alone take the contents of a chat session into account in making corrections while keeping track of its larger goal.</p><p>To my surprise and encouragement, not only could the AI parse and go through the whole script, but the mistakes and course corrections made Kubenstein look surprisingly human.</p><p>I know; I wrote how <a href="./2023-04-27-artificial-empathy.md">AI outputs never look truly human</a>. Still, in the context of a troubleshooting session, where a chat session transcript is filled with technical terms, input commands, and CLI outputs, the most significant indication I was not reading the output from a session driven by a human administrator was an unflappable determination in getting things right.</p><p>To illustrate that point, while Kubenstein has no specific Kubernetes training, it has a few boundaries about the conversation length, such as AIs limiting the number of tokens in API calls and the fact their providers charge calls by number of tokens. Due to those limits, Kubenstein avoids adding command outputs with more than 500 tokens to the chat session, instead adding the <a href="https://github.com/nastacio/kubenstein/blob/v1.0.0/prompts/troubleshoot-output-too-long.txt">following message</a> into the conversation:</p><blockquote>The command you gave me returns too much output.</blockquote><blockquote>- Give me a version that filters out more content, such as selecting a specific namespace or returning resources that are not in a state normally associated with a healthy resource.</blockquote><blockquote>- If asking for logs, try and apply filters with the “grep” utility followed by the “tail” utility to return only the most recent entries.</blockquote><blockquote>- If you don’t have alternatives, then proceed to the next check.</blockquote><p>Whenever presented with a response indicating a problem with the command, the AI returned a response with an apology and a new attempt at a command, like this:</p><blockquote>Apologies for the inconvenience. Let’s try a more focused command to check the status of routes.</blockquote><blockquote>To filter the routes that are not in the “Accepted” state, please run the following command:</blockquote><blockquote><em>kubectl get routes --all-namespaces --field-selector &#39;status.state!=Accepted&#39;</em></blockquote><p>Keen Kubernetes administrators will notice this command has a bad field selector, which is not a problem for Kubenstein, as it feeds the resulting error message back into the chat session, prompting the AI to return this new attempt:</p><blockquote>Apologies for the incorrect command.</blockquote><blockquote>To check the status of all routes across all namespaces, please run the following command to retrieve the Routes resources:</blockquote><blockquote><em>kubectl get routes --all-namespaces</em></blockquote><blockquote>Please provide me with the output of the command.</blockquote><p>And while these self-corrections cost precious context length — and money — it is still somewhat disconcerting to witness an AI adjusting to a live situation without hand-coded error handling or training outside the chat context.</p><p>You can see a formatted example of a completed session <a href="https://gist.github.com/nastacio/42a25138413f9a2d61867ebe19b6b354">here</a>.</p><h3>A New Programming Paradigm</h3><p>Deferring most business logic to an online third party is a significant leap from traditional software development.</p><p>The visible part is evident, with plain-text cognitive scripts replacing code branches with clear execution paths. The consequences need some spelling out.</p><p>The <strong>traditional application is much shorter</strong> (the entire chat application for Kubenstein is around 200 lines of code). Still, you have to spend time encoding <a href="https://github.com/nastacio/kubenstein/tree/v1.0.0/prompts">plain English scripts</a>.</p><p>Iterating over cognitive scripts is initially <strong>more productive than writing traditional code</strong>, skipping the encoding of mental structures into a syntax-heavy programming language. However, those cognitive scripts do not have the precision of an actual programming language, so you have to <strong>account for being misunderstood</strong> and have some minor reinforcement prompts in place.</p><p>I also noticed <strong>inconsistency in the AI responses</strong>, where it suddenly started to go off script between identical conversations, requiring adjustments to the initial prompt and those smaller reinforcement prompts to remind the AI of the parameters of the initial task. For example, while I instructed the AI never to return commands with placeholders, there are a few moments where it does it anyway, so Kubenstein <strong>“reminds” the AI about its expectation</strong>.</p><p>Those <strong>short-loop runs</strong> from inside your favorite code editor? You no longer can step into the most crucial part of what the code is doing, and each run <strong>costs real dollars</strong>. I mean, fractions of real dollars, with the typical troubleshooting session through Kubenstein costing about US$0.05.</p><p>While it is easy to shrug off the prospect of running up your cloud bill by a handful of dollars per month, a single <strong>coding mistake involving an unbounded loop</strong> cost me US$2 in 30 minutes, a money drain only interrupted by an email from the provider alerting me about my account crossing its soft-limit for the month.</p><p>And even if you have a good handle on such mistakes and optimize your local runs, there is still the fact you are <strong>outsourcing your application “brain” to a third party</strong> and have little recourse if the vendor raises prices beyond the envelope of your business case. As one such example, OpenAI’s GPT-4 cost per 1K tokens is 10–20x more expensive than GPT-3.5 Turbo.</p><p>The risk mitigation for that outsourcing is simple and costly: <strong>validate that other competing AIs can process the same conversation</strong> and be ready to switch providers immediately. While at it, remember that not all AIs can process cognitive scripts. For example, I could not replicate Kubenstein using Google’s Bard AI.</p><p>And speaking of third-party providers, when the full potential of AI means cutting off humans from the loop, a fully automated Kubenstein can <strong>potentially damage the target cluster</strong> or <strong>leak sensitive information to the AI provider</strong>. Until some form of trust is developed in the system, that means <a href="https://github.com/nastacio/kubenstein/issues/1">adding human supervision into the loop</a>.</p><p>Conversely, you get <strong>functional coverage you could only dream of</strong> for a couple hundred lines of code. The application can handle use cases you have not considered because it can adapt to error messages <em>you have not seen before</em>.</p><figure><img alt="Drawing of a tiny Frankenstein monster walking towards the right edge of the screen." src="https://cdn-images-1.medium.com/max/234/1*DO9SQnIt29uDbU9wnCPd9Q.png" /></figure><h3>To Err Less Is Human. The Next Steps</h3><p>Part of me expected Kubenstein to be a flop, with the AI (GPT-3.5 Turbo) hallucinating nonsense within the first few minutes.</p><p>Before committing to writing an application, early sessions using the AI chat interface surprised me with its ability to recognize and follow complex cognitive scripts.</p><p>The early success gave way to slight deviations from localized instructions, such as providing me commands with placeholders or multiple commands in one response.</p><p>Also, any Kubernetes administrator looking at the <a href="https://gist.github.com/nastacio/42a25138413f9a2d61867ebe19b6b354">example transcript</a> mentioned in this story will spot consequential mistakes from Kubenstein in narrowing down the assessment to the default namespace and concluding the cluster was healthy without inspecting the full scope of what it had been asked to.</p><p>While I like the idea of not training the AI and not giving it examples, not to mention being excited about birthing a semi-competent system administrator with a mere 200 lines of code, it is clear that Kubenstein can benefit from more examples (via <a href="https://www.promptingguide.ai/techniques/rag">Retrieval Augmented Generation</a> perhaps?) and that the code base should grow somewhat to split and merge conversations to minimize the traffic — and attendant cost — between the application and the AI.</p><p>That cost aspect, both in time spent coding and money spent “thinking,” will probably be ever-present while creating new iterations of Kubenstein. I plan on keeping notes and writing more about it along the way.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a8334f413d6f" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/kubenstein-a-gpt-powered-kubernetes-administrator-a8334f413d6f">Kubenstein, a GPT-powered Kubernetes Administrator</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[No More Slack: Return to The Office]]></title>
            <link>https://dnastacio.medium.com/return-to-the-office-18d9ca4ebd37?source=rss-271712995c6e------2</link>
            <guid isPermaLink="false">https://medium.com/p/18d9ca4ebd37</guid>
            <category><![CDATA[tor]]></category>
            <category><![CDATA[culture]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Denilson Nastacio]]></dc:creator>
            <pubDate>Wed, 06 Sep 2023 02:06:53 GMT</pubDate>
            <atom:updated>2023-10-07T22:09:34.256Z</atom:updated>
            <content:encoded><![CDATA[<h4>You Never Know What You Had Until You Lose It</h4><figure><img alt="Perspective view of an office with three rows of desks with dozens of people looking at monitor screens." src="https://cdn-images-1.medium.com/max/1024/1*sKiytLcjg-5z3GepCvqaBQ.png" /><figcaption>Open space floor plan, by Denilson Nastacio</figcaption></figure><p>The <a href="https://www.who.int/news-room/speeches/item/who-director-general-s-opening-remarks-at-the-media-briefing---5-may-2023">pandemic is over</a> and it is time to return to normal.</p><p>And in the business world, that normal includes the traditional office.</p><p>But why?</p><p>Step away from conspiracy theories of power plays and real estate valuations, and you will find two simple reasons rooted in psychology and neuroscience:</p><ol><li>When things become hard to navigate, we tend to <a href="https://www.encyclopedia.com/psychology/dictionaries-thesauruses-pictures-and-press-releases/beyond-pleasure-principle">seek familiar surroundings</a>.</li><li><a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC9241447/">We don’t remember things the way they were</a>. We remember the way we felt about those things.</li></ol><p>What can be more challenging to navigate than improvised work arrangements imposed by death, panic, and lockdowns? Which period brings out the worst memories of recent times?</p><p>None of this means returning to a point in space will bring back those years, but like a crashed system, it is only human to revisit the past, hoping to find a stable snapshot and restore what was lost.</p><p>Speaking from my corner of the corporate world, in software development, we adapted better than most to the partial lockdowns, not the least because we normally excel in that <a href="https://dnastacio.medium.com/real-to-virtual-b2bacd2423c9">twilight between the virtual and the real</a>.</p><p>It was still improvised, and it was still a pandemic.</p><p>The flexibility of working from home paled compared to everything else lost between 2020 and 2022. Beyond the obvious death toll, there were also layoffs, school years, and <a href="https://www.kff.org/mental-health/issue-brief/the-implications-of-covid-19-for-mental-health-and-substance-use/#:~:text=Symptoms%20of%20anxiety%20and%20depression,compared%20to%20their%20male%20peers.">sanity</a>.</p><p>Then, 2022 brought about a rollercoaster of <a href="https://www.investopedia.com/terms/i/irrationalexuberance.asp">irrational exuberance</a> in hiring followed by more layoffs. At some point, anything pre-2020 started to look like a golden era.</p><p>There may be sound reasons for returning to traditional offices. Still, some arguments around engagement, networking, and mentorship are missing significant cultural and technological shifts underway before COVID-19 struck.</p><p>Before getting into those, let’s start with the giant elephant in the conference room.</p><h3>Slack: We Hardly Knew Ye</h3><p>The pandemic kickstarted an unprecedented experiment in the workforce worldwide, generating something I did not think we would see back in our (professional) lifetimes: <strong>slack.</strong></p><p>No, not the <a href="https://slack.com/">collaboration platform</a>; we saw plenty of that. I mean “slack” in terms of unassigned resource time in a project.</p><p>Suddenly, people were not commuting anymore. Taking the United States (of America, for those reading from abroad) as a reference, where the <a href="https://www.census.gov/newsroom/press-releases/2021/one-way-travel-time-to-work-rises.html">average one-way commute is a little shy of 30 minutes</a>, and assuming ten trips over five days a week for in-office work, we had an extra <em>five hours</em> in our hands every week.</p><p>Five hours no longer spent on something <a href="https://www.psychologytoday.com/us/blog/urban-survival/201501/commuting-the-stress-that-doesnt-pay">scientifically proven to be a significant stressor</a> on daily routines. Gone.</p><p>Shortly after the initial productivity shock of lockdowns, we realized the slack went beyond those five hours because we could shuffle our routine around <a href="https://en.wikipedia.org/wiki/Flow_%28psychology%29">flow states</a>.</p><p>Once school closures stopped being the norm, a share of the WFH population also experienced a newfound ability to outperform on tasks that required deep focus and concentration: Fewer unplanned interruptions!</p><p>More work done. More slack.</p><figure><img alt="Drawing of city street in perspective, lined with tall buildings on both sides and full of cars and street lights in the center." src="https://cdn-images-1.medium.com/max/1024/1*CeGe0miPHHYutW6y2E6Z2Q.png" /><figcaption>Downtown traffic hour, by Denilson Nastacio</figcaption></figure><p>And before we write off commute time as a shrug-worthy chore that can be filled with audiobooks and podcasts, we should get into the <em>math of disposable versus usable time</em>.</p><p>It is easy to rationalize the average five hours of commuting as a small percentage of a typical week, with 168 hours spread across seven 24-hour days, amounting to a mere 3% (5/168) of that total.</p><p>However, take weekends (48 hours,) work week sleep (40 hours,) and working hours (40?) from the denominator, and those five hours suddenly become 12.5% (5/40) of the total.</p><p>Continue that exercise, removing other fixed costs attending to unavoidable personal chores, reusing some data from the <a href="https://www.bls.gov/home.htm">U.S. Bureau of Labor Statistics</a>, and those <strong>hours start to represent anywhere from 20% to 50% of the leisure time for a working adult</strong>, depending on whether they have children and the children’s age.</p><p>So, while RTO may just be a return to a pre-pandemic normal, it is still a massive shock to present-day professional and personal routines.</p><p><strong>Net:</strong> There are concrete reasons to try and extract the benefits from in-person collaboration <em>from fewer days in the office.</em> Credit to <a href="https://www.levels.fyi/remote/">most RTO policies</a>, they seem to acknowledge that fact with hybrid arrangements of 2–3 days per week in the office.</p><h3>Uneven (Virtual) Reality</h3><p>In the tech world, for better or worse, we are conditioned not to hold on to processes or tools. Our past is an undesirable and uncompetitive space, littered with underpowered hardware, slow connections, and gray walls.</p><p>In tech, there is no normal. There is no familiar.</p><p>So, why return to the old ways? Why not work from home — or away from the office — all the time?</p><p>We often get lost debating issues of convenience and flexibility — because they still matter — but we don’t arrive anywhere because reality is not evenly distributed.</p><p>Sure, at least personally, the coffee at home is better, the hours more flexible, and the commute infinitely shorter.</p><p>That is not the case for everyone.</p><p>For every person <a href="https://www.angi.com/articles/home-office-costs.htm">fortunate enough to be able to afford a dedicated home office</a> unperturbed by kids in grade school, there may be someone taking a phone call ensconced in a broom closet while young children pay loud tribute to their Summer break.</p><p>For every seasoned professional who can <a href="https://medium.com/codex/visiting-an-office-really-is-a-time-wasting-exercise-c85d1836487">work more productively without interacting with others in person</a>, there is a junior engineer who could benefit from polishing their social bonafides and <a href="https://twitter.com/mipsytipsy/status/1693412071051002094">making essential connections</a> that will help them later in their careers.</p><p>We will not find common ground in the anecdotes. They line up dangerously close to demographic boundaries, where <a href="https://en.wikipedia.org/wiki/Here_be_dragons">here be dragons</a> and significantly different outlooks in life.</p><p>From the sidelines, we also have to contend with a growing mental health crisis, where <a href="https://www.forbes.com/sites/glebtsipursky/2023/07/21/the-mental-health-crisis-caused-by-the-return-to-office/?sh=107efa08414c">employers and employees need to be better prepared to navigate those conversations</a>.</p><p>I am threading a needle of <a href="https://en.wiktionary.org/wiki/bothsidesism">bothsideism</a> here, but that is the whole point.</p><p>This debate will not be won with a decisive data-driven knockout, mainly because the little data we have reveals a more nuanced picture, with <a href="https://www.mckinsey.com/industries/healthcare/our-insights/returning-to-work-keys-to-a-psychologically-safer-workplace">some segments of the office population reporting improved mental health post-RTO</a>.</p><p>So, the current point in time is inconclusive, but as the following section shows, those demographics are pointing in a clear direction.</p><h3>The (Generational) Point of No Return</h3><p><a href="https://theconversation.com/a-short-history-of-the-office-82000">RTO is a centuries-old cyclical phenomenon</a>.</p><p>In the long run, it is all about colocating the tools and materials required to do the work in a way that makes it possible and efficient, in that order.</p><p>Technology in software development moved in flash steps, steadily advancing through decades of exponential progress.</p><p>It is one thing to <em>adapt</em> to changes; it is another thing entirely different to experience the <em>formative years</em> of your career with a different reality.</p><p>In the early 80s, everything needed for software development was hugely expensive, large, and wired to the building — Say hello, fellow <a href="https://en.wikipedia.org/wiki/Generation_X">Gen Xers</a>.</p><p>Fast forward to the early 2010s, and remote work became possible and reasonably seamless right before <a href="https://en.wikipedia.org/wiki/Generation_Z">Gen Zers</a> started joining the workforce.</p><p>By then, broadband Internet access was fast enough to make Cloud computing accessible from a home office, collaboration tools were much better, and teams had (somewhat) learned to cooperate across geographies and timezones.</p><p>Widespread video-based cooperation did not become an enterprise reality until the late 2010s, with Zoom and WebEx — They started much earlier, but the large-scale enterprise readiness came later.</p><p>Why the recap?</p><p>Because direction matters more than the stops along the way.</p><p>The software developers starting their careers in those early remote-ready years are now in their late 20s and early 30s. <a href="https://www.zippia.com/software-engineer-jobs/demographics/#age-statistics">Statistically</a>, that remote-first generation of tech workers is still a minority, around 20% of the market.</p><p>But it is not only a significant minority. It is a fast-growing group, both in size and influence.</p><p><em>Within a decade, that share of the workforce forged in a new reality of unfettered access to information will cross the majority threshold, including the C-suite.</em></p><p>That generation of business leaders will be uniquely adept to a remote-first environment of sophisticated collaboration tools and be socially optimized for efficient cross-geo, cross-timezone cooperation.</p><p>While I also worry about the long-term effects of human communication over two-dimensional small screens, the near future is already pointing at <a href="https://blog.google/technology/research/project-starline/">virtual life-sized 3D interactions</a>.</p><p>Look forward just a little bit — years instead of decades — with the unlimited possibilities of reality augmentation powered by conversational AI, and in-person communication will inevitably become the less efficient, less fluid form of interaction.</p><p><strong>Net: </strong>Observe and learn the communication patterns and preferences of Millennials and Gen Zers before making the case for the best balance between face-to-face and online communication.</p><h3>Information Sharing Over Interactions</h3><p>If you need complex information that only a colleague has in their head, face-to-face interaction and easy access to a whiteboard is the standard to beat.</p><p>One must step away from that ideal scenario and consider the reality of geographically distributed teams anchored around collaboration tools.</p><ol><li><em>Essential information should not be in the heads of a single colleague. </em>Knowledge hoarding, intentional or not, is a form of holding people’s productivity back, and organizations should optimize for forms of communication where that arrangement is short-lived.</li><li><em>In-person communication kills knowledge accumulation</em>. Unless the person receiving the information proceeds to document what they learned, that means people in other offices will not have access to the privileged knowledge.</li><li><em>In-person communication excludes people in other time zones</em>. No matter how hard you try, capturing an in-person session that explores the <em>full range</em> of expression of the in-person medium is virtually impossible.</li></ol><p>We hear a lot about “remote first,” but what matters most is “online first.”</p><p>Before the Internet, we had to read manuals from cover to cover or struggle.</p><p>My first software development lab had a small library of technical books attached to it. The knowledge had to be in our heads, and <a href="https://www.cyberdefinitions.com/definitions/RTFM.html">RTFM</a> was the law of the land.</p><p>Today?</p><p>I can hit Stack Overflow and get my answer in seconds. And it is not only the answer. Spending a few extra minutes reading the comments section — the true gold of the Internet — surfaces all sorts of alternative solutions, with the where and how they would work better or worse.</p><p>As a result, I can operate at a higher cognitive level. We all can. For lower-level information, we only need to fetch some keywords from those higher-level contexts and put them in a search field.</p><p>As a side note, for narrower questions where we need a snippet of code, there is always generative AI, such as ChatGPT. They may hallucinate a parameter or two but are borderline magical with Python code and CLIs.</p><p>Could you ask those questions to someone sitting next to you? Yes.</p><p>Will it get better business results? <a href="https://twitter.com/dnastacio/status/1589639220372520960">Absolutely not</a>.</p><p><strong>Net: </strong>Focusing on the quality of one interaction obscures the focus on the frequency, nature, and quality of <em>all</em> interactions.</p><h3>Manage The Work First</h3><p>People’s productivity ebb and flow with the nature of the project, assignment, personal issues, availability, and so many variables.</p><p><em>“But how can you tell whether someone is delivering results?”</em></p><p>Not by looking at them.</p><p>I have never been a people’s manager, but I have plenty of experience as a technical leader. In that sense, I am used to defining a technical solution and breaking it down into the tasks required to deliver it.</p><p>That breakdown also includes an assessment of the task’s complexity and the potential time it would take if assigned to someone experienced enough to take on that task.</p><p>Managing the work is my only recourse to keep things on track.</p><p>Is the work clear? Is it understood? Is it assigned to someone with enough technical skill to execute it? Is it being completed to the project standards? Does it meet customer requirements? Is it late?</p><p>These are the questions I can ask.</p><p>Does someone understand work better than others? Is the task owner taking longer than I would consider a reasonable time? Does their work environment allow them to focus on the work? Are they working on the task as much as I think they could?</p><p>These are questions I cannot ask. I eventually learned I was better off that way. Not being a people manager, a technical leader needs different tools to get the most productivity from a team.</p><p>Incidentally, the best productivity lesson I ever learned on the topic started with reading Peter Drucker’s <a href="https://www.google.com/books/edition/Management_Challenges_for_the_21st_Centu/NpkJTf0lZhUC?hl=en">“Management Challenges for the 21st Century”</a> many years ago, from where I quote:</p><blockquote>In the knowledge economy, everyone is a volunteer […] Accept the fact that we have to treat almost anybody as a volunteer.</blockquote><p>While that may sound a little like letting everyone do whatever they want, or letting people not do anything at all, that mindset means you must define (and sometimes steer) the work toward things that attract people. It also means talking to people and asking them what interests them the most.</p><p>Personnel aspects can obviously ruin the business if left unattended, such as interpersonal conflicts, unmet career aspirations, life-changing events, compensation, and many others. Good people management still matters. And it matters more than ever if we will make the best out of hybrid office policies.</p><p><strong>Net:</strong> When it comes to productivity — and acknowledging <em>I am biased by my professional career choices — </em>managing the <em>work</em> is often more effective than managing the people doing it.</p><h3>Serendipity, You Say?</h3><p>Serendipity in forming ideas is often cited as an advantage of in-office collaboration.</p><p>Supporters often tell stories of how people have randomly bumped into each other on the way out of a cafeteria or coffee shop, struck up a conversation, and came up with great ideas.</p><p>Ignoring the effects of <a href="https://informationr.net/ir/25-4/isic2020/isic2001.html">personality traits in serendipity encounters</a>, which may be experienced in very different ways across the office-dwelling population, the flaw in the in-office serendipity theory comes down to numbers.</p><p>Access to information (and people) today is not only better than it was three decades ago, it <a href="https://link.springer.com/article/10.1007/s10115-021-01552-w">enables communication patterns that simply did not exist</a>.</p><p><em>The breadth of knowledge around the cafeteria or coffee shop is infinitesimally smaller than what is available online.</em></p><p>That is not a diss toward my nearby colleagues; I also include my knowledge in that pool. It is just a fact that the online world has a much larger and more diverse population than you can find in a single building.</p><p>Watching a few key channels in something like a corporate Slack or Teams workspace will always be more effective in mining (and generating) ideas than hoping to bump into a similar spark from someone living within driving distance of the building.</p><p>And those online exchanges are not low-quality interactions. They are rich, augmented with in-context lookups, and filled with links and referrals.</p><p>Yes, meeting the people on the other side of those chats in person would be fantastic, but that is beside the point, as we would not have met them in the first place.</p><p>Most of my favorite professional colleagues live hundreds, often thousands of miles from my office — I am sure some of yours, too — Some live in different countries. And I may never meet them in person.</p><p><strong>Net: </strong><a href="https://hbr.org/2011/02/make-serendipity-work">Create conditions for collaboration</a> first, actively encourage people to understand the <a href="https://medium.com/@ameet/the-four-kinds-of-luck-ea729970d71d">difference between intention and luck</a>, and then push people to look for serendipity in ways that work best for them. Then, periodically, find ways to gather those people in person, using group events and planned activities.</p><h3>We Are Here. Make It Count</h3><p>The current reality of how the workforce relates to the traditional office is mixed.</p><p>The future direction is not.</p><p>There is nothing wrong with wanting face-to-face, <a href="https://www.forbes.com/sites/lbsbusinessstrategyreview/2021/10/25/why-do-we-have-face-to-face-meetings/?sh=491355231f07">high-quality interactions</a>, easy access to information, supporting new colleagues in person, and putting human faces to inhuman avatars in chat rooms.</p><p>And it is precisely because these things <em>are</em> important that we need more than hoping they will happen when we put people physically next to one another.</p><p>We need purpose. We need intent. We need new forms of collaboration — and management — adapted to the reality of in-person collocation being an expensive arrangement.</p><p>Office collocation is a near-luxury item that should not be avoided altogether but also not be used in the same ways, or as frequently as we did ten, twenty, or thirty years ago.</p><p>Moving forward means isolating the good things we expect from RTO and adapting them to the realities of evolving technology and shifting demographics across a society coming to terms with life-altering events.</p><p>The buildings may be familiar, but the pandemic was a difficult time of extreme adaptation and, in many cases, isolation.</p><p>For now, returning to the office and seeing more faces offers a welcome respite to the latter and an opportunity to reexamine the former.</p><p>With concerted effort, we may bump into the best blend of pros and cons between the opposite ends of the morning commute.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=18d9ca4ebd37" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>