Writing


Proficiency Is the Pursuit

November 2026 · 3 min read

GoScriptures is more than just a social media platform I created; it has been my technical test bed for nine years. I have deeply honed my Angular, Node.js, Java, and PostgreSQL skills working on it. I have designed, architected, and coded across all layers, but I have had to rely on others with various expertise over the course of the project: DevOps, help with Java velocity, UI/UX, and graphic design. In my circumstances, that reliance has often slowed progress: finding the right people, getting them up to speed, coordinating schedules, and waiting for availability.

About a year ago, I began a UX redesign, recognizing that GoScriptures is built on four pillars: discuss, engage, explore, and circles. I fed screenshots of every page into Claude Code, explained every feature and every data field in detail, explained the pillars concept, and explained my vision for the UI/UX. Working with Claude Code, we developed a strategy document for a new approach. We laid out a new navigational scheme and a flat page hierarchy; I kept the leaf-node pages and just reorganized the navigational elements. Once the design was complete, I coded it, and the result is a massive step forward: not just a more intuitive UX but, equally important, the first solid representation of the brand itself, embodied in the UX.

I still had a problem, though. My AWS runtime was more complex than necessary, resulting in unnecessary costs, and I was still dependent on others for deployments, maintenance, and issue diagnosis. So I sat down with Claude Code and began outlining what was important to me in a runtime environment:

  • I wanted the production runtime to be replicable on my local machine. Until then, production ran a different architecture, which meant the production deployment itself could introduce issues. I wanted to close that gap.
  • I was actively expanding my DevOps skills, but I wanted to favor a simpler approach: the simplest architecture capable of satisfying the platform's requirements.
  • Makefile targets re-engineered for this new approach, following the development and delivery workflows.
  • A transient test environment in AWS, to support a test deployment before each production deployment.

These were the basics. I wrote a strategy document, placed it in the root of the repo, and got to work. I built a new Makefile and targets, Terraform scripts, and Dockerfiles, reconfigured the AWS accounts, and reworked the GitHub Actions. I defined new operational management procedures with weekly and monthly maintenance tasks, defined database backup and recovery processes and tested them across the new test and local environments, and defined an evolution workflow outlining the sequence for adding layers of sophistication and the events that should trigger each one.

I spent over a month reviewing scripts, documenting processes, running tests, and strengthening the automated testing practices, with Cypress on the front end and JUnit on the back end. I provisioned test environments on AWS, deployed, tested, and tore them down, over and over. I practiced database restores to gain proficiency in the process. I had Claude force errors so that I could hunt through the logs and improve my ability to diagnose production failures. All of it was meticulously documented. There are too many details to keep everything in my head, so thorough documentation gives Claude and me a reliable reference when revisiting decisions, processes, concerns, or action items.

The day finally came. On October 1, 2026, GoScriptures cut over to an AWS operational runtime of my design and in my control. Since then, I have had two major deployments, and neither went entirely to plan. One deployment failed when a special character in a generated database credential interacted unexpectedly with Docker Compose's environment-variable parsing. My bootstrap process hadn't accounted for that case. I traced the failure through the deployment logs, identified the cause, and corrected the script with Claude's assistance.

The liberation I feel being able to run through sprints without a DevOps dependency is amazing. The time it takes me to introduce new features, improve capabilities, and remediate observed inconsistencies has gone from months to days.

I love the four quadrants of proficiency: unconscious incompetence, conscious incompetence, conscious competence, and unconscious competence. Pursuit is the mechanism that moves us to the next higher quadrant and anything that inspires pursuit is something to be treasured.


Where Does It Go from Here?

September 2026 · 5 min read

Guardrails, instructions, skills, repositories, IDEs, and AI: words that seem to occupy many minds these days. A colleague asked me to help him with some agentic engineering work. He owns a small local business and has vibe-coded some productivity tools. Although he is very bright and runs a successful business, he is not technical by training. He vibe-coded some interesting software, specific to his industry and the size of his business. However, the code only runs on his own machine and uses JSON files for data persistence. He asked if I could help him elevate his process to make something accessible to everyone in the organization.

The first thing to do is understand what he really needs. After some discussion, here is our list:

  • He will continue AI coding, but he needs guardrails to guide the technical output to fit within an enterprise framework.
  • He wants a dashboard page that his employees log in to, where every program he creates is served to those with access to its various components.
  • Data must be centrally managed so that it is accessible to each application and each user.

The first time I used AI to help me derive functional output was about two years ago. While contracting at the State of Utah, I had to enable OpenAPI documentation with Swagger. I worked with ChatGPT, grinding through the codebase, helping enable Swagger across our Java endpoints. From that moment on, AI became an ever more prevalent part of my professional work, but I was cautious about adopting AI-generated solutions without first understanding the broader implications. My human-in-the-loop approach might be more methodical than others, but I have always been a believer in evolution, not revolution.

Alongside my colleague’s engagement, I am working to expand AI’s involvement in coding on GoScriptures. I have been working on a wholesale change to the runtime architecture for GoScriptures and all the DevOps assets that go with that. That work is nearly finished and, once done, removes dependencies I have on others to build, deploy, and manage my runtime environments. However, I will need to expand my use of AI into the programming realm because I am a one-man band and have a lot I wish to accomplish.

To begin Claude’s coding on GoScriptures, I break out targeted pieces of work and have Claude write the code. I review every class and every changed component, every line of code, and make detailed notes on what I like and what I don’t. These notes become instructions placed into the appropriate nodes within the repo, and they define the technical design dos and don’ts for each subtree. As we continue this process, bigger changes are made, touching more files, and I continue my detailed reviews. Skill files are created defining the intentions for programmatic idioms, async thread management, change detection, detailed transaction flows across tiers, and more. My primary intention, as I let Claude code more of GoScriptures, is that when I open the IDE, the code I see remains consistent with design patterns and code idioms I have already decided upon. The process works the other way, as well: Claude has access to practically every known pattern, so letting Claude make recommendations is important. However, as I mentioned in a previous post, AI is not a process; it is a productivity tool. So, recommendations are typically pushed to a backlog as GitHub Issues, marked with a status of “Needs Review” and given a priority, to be assessed later, by me, against other Issues as sprint planning occurs.

For example, I designed my Angular layer to follow a classic three-tier application design (component, manager, and API layers), with common services and model classes to the side. There is an async boundary between the UI components and the manager classes, because the manager classes call the API methods as Observables. I rely on root-level DI of view models: when a manager class receives a response, it modifies a view model and change detection re-renders the DOM. When Claude Code built some pages, I closely inspected the code and saw Observables in the UI components, which are on the wrong side of the async boundary. I know this topic is evolving because of changes occurring within change detection. I am not espousing one pattern over another. I am, however, espousing consistency. If changing my UI design patterns becomes important, then that type of change needs to be planned, not just coded in the context of a ticket intended for a different type of change. So, I reflect my pattern preferences as instructions. Claude reviews the instructions and adds notes of its own. And voilà: code I recognize when I open my IDE.

As I develop methods for controlling how AI is used in development, as I expand my views on operational management, sprint planning, capability enhancements, and QA improvements, and as I work through the AI framework engagement for my colleague, I recognize first-hand the importance of strategy documents, guardrails, instructions, and skills as versioned files, peers to any other project asset. Further, it is really interesting how these AI assets are managed in different environments, much of it depending on how repositories are used. I see three classifications for AI asset management, and I am sure there are more:

  • Smaller companies with a single repo, or very few, keep those assets within the project hierarchy, much like test versus main nodes across subprojects.
  • Larger organizations with monorepos have project structures that represent their SOA: common components, service components, even build and package artifacts are laid out in a structure that reflects their specific architecture. AI files follow those structural patterns.
  • Organizations with multiple repos, mono or otherwise, create standalone repos to hold their AI assets and point their AI processes to those repos for consistency across the enterprise.

In each case, the principle is the same: the assets are versioned, reviewed, and shared. It is the principle behind both my colleague’s system and GoScriptures, and it represents a strategic approach to productive utilization of AI-generated code.

I ask myself, then, what is the definition of vibe coding? Vibe coding is not defined by how much code AI generates, but by how much code reaches production without either adhering to established engineering standards or undergoing meaningful developer review.

As I transition more GoScriptures coding to AI, I place greater emphasis on detailed reviews and on capturing variances in my guardrails documents. As I continue working on the framework for my colleague, I use what I am learning on GoScriptures, tailoring the guardrails to the uniqueness of his operational requirements and building test apps as he would to measure the quality of the guardrails. It is pretty cool that AI-written code is itself a testable output.

Where does it go from here? For me, cautious expansion. I say it a lot: we have to walk before we can run. And I take comfort in recognizing that the definition of vibe coding rests on the degree of control we relinquish to AI, not on the amount of code AI creates.


AWS Certified Solutions Architect – Associate

August 2026 · 1 min read

I just earned my AWS Certified Solutions Architect – Associate. The engineers I admire most, the people I believe are best suited to lead overall engineering efforts, are coders whose skills extend beyond designing and building functional software. Building great systems is the heart of it, but coding is much more than implementing business requirements. More and more of the technical complexity these days isn’t in the business logic itself, but in everything around it: how it is deployed, scaled, secured, and observed.

The “how” seems to spill ever more into the DevOps realm. I see the work in four areas:

  • The design, development, and delivery of business software: typical software engineering concerns such as tiered architecture, database design and connection pool management, transactions, error management, and performance.
  • Cloud services provisioning and deployment: IaC, CI/CD, pipelines, workflows, and release and container management, all the things that provision a runtime environment and deploy functioning code into it.
  • Issue diagnosis and remediation: the most talented developers I have seen at diagnosing issues are completely comfortable in a cloud console searching logs to determine root cause.
  • Security and observability: great developers know how the system is performing before errors occur, and are aware of security risks and how to detect and mitigate them before issues arise.

I invest heavily in these areas. For years, I have seen the difference these characteristics make in an engineer’s value. As the adage goes: find someone who defines success for you, and emulate them. Today I passed the exam with a scaled score of 820, and look forward to continuing my journey in these areas.


The Importance of Mentorship

August 2026 · 2 min read

Whether you are a hands-on, head-down developer or performing in a leadership role, we all lead. We lead by example, we lead by our willingness to jump in and solve a problem, we lead in the manner in which we treat others, and we lead in the manner in which we inspire each other.

Mentorship has always been important to me, and it fills me with joy to read some of the recommendations people have written on my behalf. We all should be motivated to help ourselves and others perform at our best. Think about it: that action, that behavior, itself defines culture. The Wisdom of Teams, by Jon Katzenbach and Douglas Smith, offers a really interesting perspective that touches everyone within an organization. The book reports what the authors found studying many different organizational teams, looking at their performance and characteristics. In essence, it describes the two most productive team types, notes that the top tier performed significantly better than the second, and finds that the single most pronounced difference is that the members of the highest-performing teams demonstrated personal concern for each other. Mentorship doesn’t just help people perform at their best; it impacts productive output and it changes culture.

As such, I was absolutely blown away by an article I recently read about a colleague of mine from Vix Technology, Ahmed AlSharif. Ahmed worked for me at Vix. We worked hard together to bring the technology integration processes I had built in the Americas into the way Ahmed and the team in Europe performed their work. One day, Ahmed mentioned to me that he wanted to leave Vix because his heart was pulling him to the gaming industry. Now, I had personally invested in Ahmed, and when he told me this, my mind raced to find things to say that would make him want to stay. I thought about it for a moment and then said, “Ahmed, if your heart is guiding you to the gaming industry, then don’t let anyone advise you otherwise. We will miss you, but you should follow your heart.”

Nothing could have prepared me for what happened next. I watched Ahmed’s career from a distance and was amazed at the success he created for himself. He went from Technical Director of Quality Engineering at EA’s Ghost Games to Technical Director across EA’s North Sea studios, then Head of Reality Labs Automation and Platform Engineering at Meta, then CTO of Sandsoft, and I read several of his articles, each full of insight and poise. Truly impressive. But then Ahmed surprised me again. He had been working behind the scenes on a new AI technology, and he left Sandsoft to found think, an AI company deeply focused on efficiency.

His company, think, just closed a record pre-seed round, and The Saudi Times interviewed Ahmed about it (The Saudi Times, 20 August 2026). The interview is well worth reading for a sense of his warmth and genuine expertise.

As I read it, I was humbled beyond words. Discussing the mentors who shaped his approach, Ahmed said:

“David King and Marija Radulovic-Nastic from EA, Tom Gibbons from Vix, Senthil Kumaran at Meta, they all mentored me throughout my career, each taught me their own dimensions. The best leaders adapt and have technical depth in their areas. Deep understanding, paired with strong commercial instincts too. They can make decisions quickly because they know the terrain no matter how senior they become.”


I Dreamed It

February 2026 · 2 min read

I first discovered software engineering in 11th grade. Before discovering programming, I wanted to be an electrician. When I was growing up in Flint, Michigan, huge manufacturing plants were a common sight. I really loved electricity. As a kid, I rigged up a car battery in our treehouse to power switches and headlamps. The battery was on a pulley system, so periodically we lowered it, charged it, and pulled it back into place. I stared at those giant plants, multiple city blocks in size, trying to envision their electrical requirements, envisioning myself running around in a yellow hard hat resolving an issue on the plant floor.

But 11th grade changed everything. I took my first programming class: Apple BASIC. Oh my gosh, it was like being punched in the face. I fell in love! I remember a senior teaching me how to move a game piece around a two-dimensional array. He taught me the eight directions: y+1; y+1 and x−1; x−1; x−1 and y−1; y−1; y−1 and x+1; x+1; x+1 and y+1. That changed my life. I spent hours in the computer science lab: before school, during lunch, after school. I developed games: space war games, strategy games, and, in my senior year, a Rubik’s Cube simulator.

I have never fallen out of love with coding. Coding is how my mind works. My neural pathways did not evolve because I became a coder; structured logic is simply inherent to them. As such, I dream in code. My dreaming awareness becomes a thread, then multiple threads, and my memory knows the code I’ve written. All night long, I process instructions, and when I wake up, I have new insights and new ideas, and oftentimes I have figured out a bug or a better way to do something.

This happened last night. I was making some changes in GoScriptures, trying to introduce behavior typically associated with discussion logic into the challenges code path. Before going to bed, I began restructuring the challenges code path to integrate with a discussion manager class, but it felt so shoehorned; the foot wasn’t fitting. It was late, so I walked away and went to bed. I woke up at 3:30 a.m., very excited, because I had dreamed that I could abstract the logic the challenge needed out of the discussion manager into a service class, inject it at root, and access it from both code paths. I mean, the answer was obvious, but sometimes brute force seems just fine, until those onion layers I keep peeling begin to burn my eyeballs.

I often walk away from the keyboard. I take a walk somewhere private and parse the issues in my head over and over, and in that process, I solve complex problems. For me, creativity happens away from the keyboard; implementation happens in front of it.


I’m Happy, Hope You’re Happy, Too

November 2025 · 3 min read

The hot topic of the day hasn’t changed much: AI, AI, AI. I am tempted to begin this entry with one of those cute graphics I see on LinkedIn about AI being an untamed lion or the foundation of a certain type of house, but, other than mild humor, I don’t really see the point in them. That said, I am very happy about something that has recently occurred: I have been asked to write up my thoughts on operational policies, and on how technical innovation does and does not affect them. Yes, I have been talking to others about my general observations, and it isn’t just AI in the workplace. It also includes things like PR reviews, the developer’s definition of done when finishing a ticket, and, yes, AI adoption.

I was so excited about this because, more than on any other contract gig since I started Ptolemy, I have been thinking about development, testing, delivery, the technical evolution of a solution set, and the operational policies governing development activities while working with the State of Utah. I love it, because I find it fascinating, and I believe there is real room for productive improvement.

I have held many different positions as a consultant. As a consultant, you represent a type of expert, someone walking into a business with expertise and answers. Many times I have actually been a little worried: do I really possess expertise worthy of what this organization is paying to have me here? And so many times, it has surprised me how focusing on simple basics is a differentiator.

I would like to say that the operational plan I put together for the State was deeply insightful, and perhaps it was, but to me it was about applying sound engineering and operational principles to the organization's particular needs. Think of a bread-and-butter Scrum cycle: that is the starting point of the whole thing. My client has specific organizational strengths in some areas and lacks them in others, as do we all, so the basic plan adjusts to focus on their strengths and de-emphasize their weaknesses. No big deal.

However, there were three important aspects of growth that I felt needed to be called out:

  • Controlled adoption of new capabilities.
  • Standardization in the methods developers use to perform work in sprints.
  • Standardization in the programmatic idioms developers use within their code.

These applied across AI usage, automated testing, dependency library management, the use of common programmatic services, when and how tickets get allocated to developers, and more.

Now, a primary recognition is that technical strategic planning is critical. The organization has amazingly bright people, both on staff and on contract. How, then, does an organization elevate technical planning to the status of a first-class citizen? Product planning is typically the input into sprint planning, and sprint results typically inform product planning. The plan elevates technical planning to the same height: appropriate staff, whom I defined by title and role description, engage in technical planning that feeds into sprint planning, and sprint results inform technical planning. How much of a given sprint each discipline informs is, like any knob built to tune capability, not fixed when the process is defined. The percentages are dynamic and should change based on business need and sprint outcomes. For example, if post-deployment issues force rollbacks at a certain frequency, and applying sprint time to technical strategic initiatives improves that statistic, it is easier to justify the sprint time allocated to technical strategy.

So the issues affecting the organization, such as controlled AI adoption, standardized methods, and common idioms, become the input into the technical strategic process. Of course, I have my opinions and, if I had a magic wand, I would tell everyone exactly what technical changes should be made and how. But it is not my job to dictate technical strategy; it is to identify a process that formalizes the opportunity for the team to make progress on technical evolution.

The primary technical issues facing any organization are unique to that organization and, for the most part, the development team already knows what they are. Aligning the entire project team, from top to bottom, around a focused, coordinated methodology that defines how new technologies should be used, and how the technical concerns affecting the team are formally managed through our tried-and-true agile operational practices, seems a common-sense approach. It is one I believe will have a positive cultural impact and provide controlled technical evolution to the benefit of the supported systems.


Oh No, Don’t Say It’s True

August 2025 · 3 min read

At the turn of the century, agile and iterative development changed the way we think about operational processes and systems delivery. Although operational management was further affected by cloud computing, I don’t believe the fundamentals of sprint management changed; rather what is being managed, the impacts on velocity, and the scopes of concern did. We have seen tremendous growth in technical capabilities, but I argue that changes in technical capability don’t change the fundamentals of operational practice. And not every technical opportunity represents productive growth; whether a technology will yield productive growth should be assessed case by case.

AI is a powerful technology, perhaps the second most game-changing I have seen in my career, cloud computing being the other. But it is important to understand the context of this capability. AI is not an operational process; it is a productivity tool.

PR reviews seem to have replaced the traditional delivery walk-through. We don’t seem to meet with our peers to review our changes before releasing them. Instead, we issue a PR and accept that a peer’s approval is the equivalent of a traditional sign-off. This is a practice I lament. I find some amusement in the notion that “the code is the documentation.” It is a clever comment, but it misses two important points:

  • Code was never intended to be the system of record. Traditionally speaking, account managers, business analysts, product management strategists, and the like invest time defining the functional goals of a system. Regardless of how that process works or what its defined outputs are, those outputs represent the system of record.
  • Code itself does not convey the developer’s intention. Oh, I can hear many people already thinking of all the reasons this statement is not true, but think of set theory. Code reduces everything that occurred within the developer’s head to a minimal, finite, deterministic set of operational instructions. By definition, the result is a subset of the developer’s thinking and, philosophically speaking, a proper subset.

They say a picture is worth a thousand words, so picture this: a PR containing thousands of lines of changed code just showed up in your inbox with a request to review and approve, and the attached ticket was something like, “Why does Process A result in a failure notification during specific usage scenarios?” I have actually talked with developers who were disappointed in their peers because their PR approval requests had been outstanding for too long. I don’t know what to say in that moment, other than to suggest that a parser already overwhelmed with important work, interrupted by an incoming message that pushes it beyond the resources allocated to its process context, is bound to fail.

I have seen developers use PRs, and how often they issue them, as a kind of metrics ballot-box stuffing, and who can blame them? Companies often measure productivity with these kinds of metrics, and raises, or even our jobs, are often based on them. Assessment breeds behavior. I am not saying this is a wrong thing; I’m just saying it is a thing. Tied to this is the number of lines of code changed. GitHub’s contributor graphs show commits, additions, and deletions per developer, a fuzzy notion of who changed, or owns, how much of the code.

So there might be two reasons developers are pumping out huge changes per PR: a newly discovered love affair with AI, or a desire to improve one’s stats. Either way, neither is an operational process change.

Sprint management is an operational practice. It has a cadence, with specific steps that iterate: assigning scrubbed tickets to a release, assigning those work units to specific developers, and managing that process through delivery. Important parts of the process include measuring velocity, error rates, and more. However, never in traditional sprint management did a developer make changes to unrelated code just because they could. AI gives a developer the ability to make massive changes, within or outside the boundaries of a ticket, but the operational practices we have followed for two decades don’t suggest they should; quite the opposite. Could and should are not the same thing. The scope of a change should be tied to the scope of its ticket, and opportunities discovered along the way should be raised as enhancements and prioritized against the other tickets in the backlog.

Yes, taken in a vacuum, it is easy to agree that using AI does not in itself represent an operational process change. But developers seem comfortable introducing change in ways that weren’t true before AI and that, in some cases, run contrary to the founding principles of agile development.


Abstractions Are Learned from the Ground Up

June 2025 · 3 min read

I am contracting with the State of Utah and really enjoy it. The legacy system is AngularJS, pre-v1.8! The back end is Java with Spring MVC on Oracle. This is the second time I’ve worked on pre-2.0 Angular and, wow, Angular 2.0 and beyond was a radical departure. I really enjoy the work, though, because you can see how the earlier versions of Angular, and JavaScript frameworks in general, shaped the architecture of the UI, and witness the incredible power of decoupling via REST and other interfacing frameworks.

On another project, I spent a year with gRPC and document-based payloads, and I have to say I like it: gRPC and documents make REST with JSON seem chatty. That is where the Go folks like to play. Java’s old superpower was write once, run anywhere, but containers have commoditized the OS; I pick my Linux from a cafeteria-style menu and never think about compatibility. So the new purists chase small runtime footprints: a Go binary is a fraction of the size of a JVM image and starts in an instant, which is a big reason Go has won so much of the cloud-native world.

Anyway, the State is very keen on a next-generation child care platform, and I like being able to play with the rigors of AngularJS and Spring MVC. If I am going to be a part of the next-generation child care platform for the State of Utah, then getting to know the baseline system is of value, regardless of tech stack. And I have to say, like the LUFAS rules-based auditing system I worked on at the Church, this is a non-trivial system. It:

  • Keeps track of child care providers.
  • Applies the assessment rules the State created to classify the capabilities of child care businesses, which often have multiple branch locations.
  • Applies the same kind of assessment to child care workers, who tend to stay in the industry, moving from provider to provider.

It is a rules processing engine with a lot at stake, because state subsidies are based in part on its assessments, both qualitative and quantitative, of these businesses and people.

There is this one guy who sits in the corner. I like this cat. He is more experienced than me and knows Java, Spring, and DevOps better than me. I periodically swing by his desk to test him, you know, espousing all the things I have learned, all the things I know, and how they apply to the really important stuff we are doing. He indulges me with his attention and seems, at times, interested in my points of view, but then, when he wants to get back to his screen, he says something that always feels to me like a mic-drop moment. I head back to my desk and begin poring deeper into GitHub Actions, AWS logs, connection pool management, and Oracle views. This database design is very interesting because it is built upon views upon views, sometimes four or more deep, which appears to be the result of a custom-developed object-to-relational mapper. The mapper is really interesting and used for every DB operation, but it doesn't support higher-level SQL constructs such as joins.

But then, magic occurs. The powers that be purchased GitHub Copilot licenses, integrated into IntelliJ, for all of us! Hallelujah, we are stepping into the light. Now, I am like a cartoon character of a man in a 1920s bathing suit, worriedly dipping one toe into the water to see if it is too cold to jump in, but my buddy, the one I periodically try to outsmart, is high in the air, already tucked into a cannonball, a huge smile on his face, just waiting for the splashdown. Before us both are fields of experience ripe with learning opportunities, just waiting to be discovered.


I Got It

July 2024 · 3 min read

Well, that took way too long: not to study and take the test, but to prioritize it! I took and passed the AWS Certified Cloud Practitioner exam. Surprisingly, it wasn’t easy. I mean, Cloud Practitioner basically means you understand the basic services: their names, what they do, and how they do it. For me, the tricky part was just the sheer volume of information. I have been researching different cloud providers for a while: AWS, GCP, DigitalOcean, and more.

We use AWS for GoScriptures, and I have been pleased with their services, certainly reliable and reasonably priced, but I will always have a soft spot in my heart for the little guys. Some of my colleagues laugh at me, but I still do a lot of business with XMission, a local ISP with hosting and email services. I like them because they are always one phone call away. As everything gets bigger, the art of customer service seems to quietly vanish.

Heck, I have a buddy who does some really interesting work: home-grown, real-time stock trading platforms. Now, this guy has very little formal training. It’s like one day he woke up and said, “I think I am going to code for a living.” His discipline in his craft is very impressive. He and I meet maybe once every other month at the same sushi restaurant for lunch, and he bounces his ideas off me. I have coded for him a few times, in C#.NET. He has many different clients and several products he supports, and he always seems to be just a wee bit busier than he prefers. Anyway, he still does co-lo at a local Utah firm. Yeah, he still drives over to mount servers!

Silly me, in many ways I envy that, and in many ways I find it romantic, in a renaissance kind of way. Here is this guy who just up and decides to code for a living, teaches himself the basics, and grows from there. He finds a professional niche, treats his clients arguably overly fairly, and earns a healthy living for himself and his family. If he wants to co-lo, then good on him! It reminds me of the JP Morgan Chase days, where we had an on-prem NOC with large plasma screens running OpenView.

I have also been studying CI/CD, Infrastructure as Code, and containerization. It is hard being fully reliant on outside DevOps expertise for GoScriptures. I actually hired a firm to help me re-engineer a sound runtime and the minimum provisioning assets. We broke the contract into three phases:

  • Phase 1: a new runtime architecture, with the minimum Terraform and Helm chart setup to provision and deploy manually.
  • Phase 2: automated CI/CD, integrated into GitHub Actions.
  • Phase 3: observability and security analysis. I have GitHub’s Dependency Graph set up for GoScriptures, but I mean CloudWatch, CloudTrail, and Prometheus.

Thank goodness I broke the contract into three phases and fixed the price on the first one, because, despite my expectations, the firm was unable to deliver. We had deliberately chosen a straightforward architecture for GoScriptures, consisting of S3, EKS, and RDS. Yet months later, I still didn't have a functioning solution. It was disappointing, but it reinforced my determination to develop the expertise to manage the platform myself.

So it is time to make it official, and I am immediately working on the Solutions Architect certification. Time always seems to be an insurmountable constraint, but capability doesn’t have to be. Without taking deeper control of every aspect of GoScriptures, I fear for her. So thank you, AWS, for great training programs, and thank goodness I found the time to improve my DevOps proficiency.


Video Fun, Anyone?

August 2022 · 3 min read

They say sprint training burns visceral fat. You know: run as fast as you can in bursts, over and over. I found it didn’t work for me, so after one day, I stopped! 🙂

Angular 14 is here, with our first taste of standalone components. Angular Material 14 brings some stability enhancements, Google is moving to Material Design 3 with lots of mobile platform support, and React 18 is upon us with its concurrent rendering. I sound so smart, like I know exactly what I am talking about with these releases and what each one contains.

I think these providers aim for, what, major releases every six months, with multiple minor releases in between and bug-fix releases in between those, and I have only mentioned four popular front-end libraries but there are hundreds of them out there. Most pushing for fast release cycles to enhance capability, improve security, fix detected issues. I mean, that is an incredible amount of aggregated effort.

Now, why do I say some might think I am smart for knowing all this about library changes and new capabilities? I mean, that is smart, right? Well, yeah, kinda. I am smart in that I recognize smart people. This rapid pace of change creates a really interesting cottage industry, one I really enjoy and have considered joining more than once: the video content creators who are always so excited to tell us all about the changes in the newest versions of our favorite libraries.

I really like these people. They remind me of newspeople in the classic era: fancy microphones visible in the frame, lighting just perfect, and gobs of graphics and cool technology to present complex ideas in easy-to-understand ways, some even sharing a screen and writing code to demonstrate the actual semantics of change.

I really do believe these content creators provide a valuable service, and the entrepreneur in me envies them. I watch them carefully, analyzing their unique approaches to their craft and looking for gaps I could fill with my own content, aimed at teaching the world how to do really neat things with code. I mean, is this the new O’Reilly? The new For Dummies? I tell my wife about these video providers, their content, the whole “Learn NgRx in twenty 15-minute videos” notion. I am fascinated, intrigued, and really enjoy consuming knowledge this way.

Of course, these trainings are highlights, right? Watching a 15-minute video about standalone components does not teach us how to code standalone components. My contract work is not migrating to standalone components and I am not migrating GoScriptures to them either, at least not right now. I know a lot of developers, tech leads, and architects who feel it is very important to migrate to the latest capabilities. Hey, I get it: when CVEs point to concerning vulnerabilities, that should get our attention. But updating to the latest version to enhance security is not the same as migrating an entire system to the latest constructs built into a brand new library version.

Don’t get me wrong, the new stuff is exciting, but GoScriptures is well over a hundred thousand lines of code, tested and working. Fully integrating new capabilities every 3–6 months is a full-time job in itself. It is an industry that creates itself, a self-perpetuating machine that feels like progress, though progress against what can sometimes feel elusive.

I love keeping up to date with the latest, I love watching video personalities help us understand what is new, and I love how learning the new capabilities affects the ways I contemplate the work being done. But I also like being warm in the winter. 15-20% body fat keeps the chill at bay and, if not sprinting to every enhancement on the perpetual clock cycle keeps me plump and rosy-cheeked, I guess I am OK with that!


Wow, That Was Hard

April 2021 · 4 min read

I have a new contract gig at The Church of Jesus Christ of Latter-day Saints, and I really like this assignment. I am working on their LUFAS auditing system, which is extremely complex. It is a massive home-grown, rules-based system that uses persisted data to determine:

  • The data models to use for the authenticated user, based on where that user sits within the global Church structure.
  • Based on the same factors, the controls and capabilities required on a screen-by-screen basis: basically, dynamic UI/UX.
  • Which auditing rules apply to the organizational unit and the hierarchy above it.
  • The actions and workflow approvals required, based on conditional outcomes when the auditing rules are run.

This system has indirections on its indirections. As I study the code, I can’t help but be very impressed by the imprints I see: the imprints of the minds that conceived and coded this program.

Our tech stack at the Church is Angular 8, Java, Spring Boot, Oracle, and REST. I have been spending much more time in the back end, coding Java and Spring Boot. Honestly, this is my first hands-on gig with Spring Boot, and I find it very interesting: a Spring context into which services are registered through annotations, which is DI at its finest. I love the flexibility of annotating REST controllers, services, transactions, and the properties of data objects for RDBMS mapping. The conceptual flow fits an Angular mentality, which is pretty cool.

The Church is very disciplined. Sprint planning and operational management are run by a proper Scrum master and PM who is serious about his role yet loves to keep things light and moving. Our lead technologist is amazingly bright. I mean, this guy has command of the tech stack, the functional scope, DevOps, and the operational implications of doing technology at the Church, and he is so fast. I have seen him take on complex projects and finish them remarkably quickly, with extremely impressive code, project structure, and automated testing. He is also warm and approachable and takes the time to mentor. I am just so impressed by this guy. I have learned so much on this contract and really enjoy working with this team.

Ahh, but a milestone of a different kind has been achieved. I earned my 4th degree black belt in Tang Soo Do, the lowest rank at which you are considered a master. I have studied martial arts for most of my adult life, jumping into different styles and earning various ranks. I am a certified first degree in Kukkiwon taekwondo, and I spent a year and a half studying Hung Gar kung fu, a year and a half studying Wing Chun, and about a year studying Hapkido. Honestly, I would have invested much more in Hapkido if our master instructor hadn’t taken off unannounced, leaving us at the doors of the dojang wondering when class was going to start.

I took some time off from martial arts when my son was born. After he turned 5, I thought it was time for us both to jump in. I searched hard for the right school: something old school in the principles it teaches, rough and serious, but also family friendly. I met Master Dustin Andersen and was impressed. My son and I worked out with him a few times, and I decided I wanted to join. Master Andersen knew I had studied in the past and, at his request, I gave him my Kukkiwon certification. He said he would discuss an appropriate starting rank for me in the PanAm Federation with his master, Grand Master Chun Su Kim. A week or so later, he bowed to me, handed back the certification, and handed me a white belt.

I didn’t know what to think. I got home that evening and asked my wife, “Am I supposed to be offended by this? What is he trying to tell me?” I thought about it and asked myself: what am I trying to accomplish? The answer was to train in martial arts side by side with my son and, soon, my younger daughter; to enjoy punching and kicking together; to get in good physical condition; and to enjoy a fun sport as a family. In answering that question, I realized belt rank had nothing to do with my goals. I could do everything that mattered to me regardless of the color of my belt, so any concern about belt colors drifted more into ego territory than anything else. At the next class, my son and I showed up in our brand-new uniforms, each of us proudly displaying our white belts.

It took me about 4 years from the time I began with Andersen Tang Soo Do to earn my first degree black belt, and once it is earned, it takes a minimum of 9 more years of continuous training even to be invited to test for 4th degree. I remember, when I was awarded my first degree, that I could not envision staying with this one school, this one discipline, for another 9+ years. I thought a lot about that as I prepared for my master’s test. I worked out 3+ hours a day, 5 days a week, for 6+ months to prepare for the exam, and that was on my own time; I still attended class three days a week on top of it! I trained hard, performed my contract work, and kept working on GoScriptures.

Learning new systems, new technologies, new operational environments, like martial arts, can be challenging and very humbling. I love my new contract gig. Yeah, it is hard, but as a dear professional colleague always says: if it were easy, everyone would do it.


Oh Dang

November 2018 · 2 min read

Well, they went and did it. Savage switched from Angular to React. They brought in a new CTO, who made the decision to change frameworks, and that brought the Angular contracts to an end, including mine.

I am not upset at all. I really enjoyed my time at Savage and learned so much. However, it raises an interesting point. I totally get the React versus Angular argument, and frankly, I am seeing more React contract opportunities these days than Angular ones. In all fairness, I have played with React and written some pretty simple stuff on my own, just to try it out. It’s fine; I have no issues with React. Going from Angular’s component lifecycle to React’s render-driven lifecycle flips my noodle just a tad, and switching back and forth, for me, takes a moment.

But here is the part I find myself curious about: what tips the scales when you are knee-deep in one to switch to the other? That is a big business decision, because this organization had years of investment in Angular, with all the assets produced along the way. To me, the two frameworks are close to a 50/50 trade, so I wonder what the deciding factors were. There must be considerations I can’t see from where I sat, and I would love to understand them.

Now, in fairness, I never interacted with that CTO, so I am speaking blindly about the motivations behind it. I would be the first to admit that I don’t always see the bird swooping out of the tree. Regardless, my contract gig with Savage is over, and I will begin looking for a new one. In the meantime, I will play more with React, which might at least open me up to new contract opportunities, and I will invest more in GoScriptures.

I swear, we are in the dog days on that platform. I would have told you my functional requirements were decomposed beyond ambiguity, but I think ambiguity is made of water: it is highly malleable and finds all the cracks. But we keep moving forward.

I love the operational discipline my partner brings to the table: Slack, GitHub, GitHub Issues, and we have played with Kanban and various sprint planning toolsets. Everything is very formal. Even though it is just the two of us, and even though progress has slowed, formality is the new cleanliness, in that it is next to Godliness. Yes, pun intended.


RxJS and Thread Synchronization

September 2018 · 1 min read

Oh dear Lord. Work today made me think back to programming on Solaris workstations in college. I thought the Dining Philosophers was the coolest thing anyone could write: C on Unix, forks, semaphores. I don't know Unix history very well but, to me, that was a romantic time in the history of our industry.

Now we are firing off multiple Observables, using multiple RxJS operators to synchronize the callbacks, and firing off view updates based on the various result sets: combineLatest, forkJoin, mergeMap, concatMap, and switchMap, not just on their own but chained. It flips my noodle a tad, because the interactions between the responses aren’t painting a clear picture in my head.

I can see when race conditions are possible. That is pretty cool. I look at the code, the multiple Observables all controlled through long chains of RxJS calls, and it hits me - that looks subject to a race condition. Our lead engineer, on staff at Savage, often compliments me on being quick to spot race conditions, but I am struggling to see how to use the RxJS constructs to plug the holes. Once he tells me, I get it. Oh yeah, I see it, I get it. But come tomorrow, I am asking him, “Now tell me that one again!”

The contract gig is going well. I really like the people, and I super like the code. It is hard to believe that, what, a year ago I didn’t know how to spell Angular, and now we are doing some pretty darned impressive highly asynchronous, distributed, RxJS-to-the-max front-end development, and I am holding my own.

GoScriptures is moving along. Being fully employed has reduced my availability, but I am putting in late hours and weekends. The mission and its pull never waver!

Onward, brave soldiers!


The Boys Are Back

July 2018 · 1 min read

I have worked on and off with a dear friend ever since our JP Morgan Chase days. He was my lead architect at Chase, I hired him at Vix, and he became the Global Head of Software Development, moving to Sydney for quite a few years for that role. Now, the boys are back. He has agreed to join me on GoScriptures! He is one of the most talented architects and software engineers with whom I have ever worked, and I mean by a long shot. He has forgotten more than I will ever know about software engineering.

We have a formal architecture, with Java REST endpoints and a PostgreSQL database on the back end. We are using OAuth2 with JWTs for authentication and security. Progress is being made and it feels fantastic.

Also, speaking of great things, I got my first contract gig, with Savage Waste as an Angular front-end developer. I am really excited.

They say you have to walk before you can run. Well, this ain’t running, but I am feeling some wind in my face.


Oh My Gosh – SPA?

February 2018 · 1 min read

I have written my fair share of HTML, CSS, JavaScript, and jQuery over the years, but these frameworks are on a whole different level. Partial page submission used to be the holy realm of AJAX, but Angular flips the script. I played with React, but I like the separation of concerns implied within an Angular component.

It has been grueling: driving the detailed requirements for GoScriptures (oh, I changed the name), trying to find a reliable partner, architecting how this code is going to work, and learning Angular, all at the same time. I would be lying if I said there haven’t been some frustrating days.

Still no partner and still no insight on the back end, but the requirements are really coming along, I am able to write Angular code, and I even feel pretty good about the technical design of the front end. I have a buddy who is an Angular developer. I talked him through my design, and he said, “Why would you want to do that?” LOL.

I am using a proper three-tier approach: components, manager classes, and API classes, along with models and services. There is an async boundary between the components and the manager classes, and the managers use Observables to call the API methods that wrap the REST calls. If I inject my model objects at root and fill them in the manager classes when data comes back from the Observable, change detection updates the view. I think they call this the MVVM pattern. I like it.

Speaking of requirements, oh my gosh, the ideas just keep flooding in. The thing started out as a simple socialization platform, but now that I have it in my head, I see everything through its eyes, and the opportunity for a platform like this is incredible.


I Quit

October 2017 · 1 min read

I am so done with social media. I mean, where is the fun in that? Where is the joy? I used to love connecting with old friends. I would walk away feeling good inside, because it was so cool to touch base with people I knew from every era of my life. Now I can’t tell advertisements from user posts, and everyone is arguing with each other. I logged off today and felt negativity in my heart. Well, that is not the purpose or intent.

So I sat back and began dreaming. What uplifts me? What would I want in my life so that I feel uplifted instead of disparaged? Here, in no particular order:

  • Treat users with dignity, not with secret intentions.
  • Keep everyone’s data private: no sharing, no mining, no advertising.
  • I have discovered that actually living a faith-centered life is really hard. I would love to talk with people about their experiences living a faith-centered lifestyle.

I remember traveling to Sydney, Australia, with Vix. I stayed over the weekend and went to church that Sunday. I met a few people there, and one of the guys offered me a ride to my hotel. As he drove, he asked if I would like to see the places where he hangs out. So we drove around for a couple of hours, him showing me around, and we talked about the Gospel. I loved hearing his perspectives and comparing them to mine. We need a platform that lets a worldwide audience share faith experiences.

A few hours later, Holy Scriptures is born: a new social media platform that I will develop, aimed at bringing people together, uplifting one another, and learning from a worldwide audience what it means to live a faith-centered life!


After Ten Years at Vix, Back to the Keyboard

August 2017 · 1 min read

After 10 years at Vix Technology, my work there is over. I truly enjoyed my time at Vix. The transportation industry is extremely interesting, with very challenging distributed systems problems to solve. I also loved the variety of solution components we integrated to build a solution for each client, and getting to know so many of the people at the start-up organizations we worked with.

My last two years at Vix were as Global Head of Technology Integration. I traveled around the world, often twice a month, and met incredible people from all over. Interestingly enough, I began at Vix as a contract software engineer. I developed a credit card payment gateway in C#.NET, using factory patterns to spin up objects that integrated with different gateway providers, and then with different card types. It was pretty cool. You see, after leadership positions at JP Morgan Chase and iBahn, I wanted to get my fingers back on the keyboard. I find I most love working on the front lines, designing, developing, and delivering great solutions.

Well, here I am again. I have rehydrated Ptolemy Software (software centered around you – get it?) and intend to code for a while. It is an exciting time because you never know where the journey will take you. I look forward to jumping back onto the front lines and reacquainting myself with an IDE.