Bun HTTP Server: #1 in Mixed Workloads, #41 in Pipelining — The Full Picture (HttpArena Deep Dive)

Every few months, someone posts “Bun is fast” on Twitter and the replies turn into a warzone. Node fans say it doesn’t matter. Deno fans say their runtime is better. Rust folks just post flamegraphs.

So let’s look at actual numbers. I ran Bun through HttpArena, an open-source benchmark suite that tests HTTP frameworks across a bunch of real-world-ish scenarios — not just “hello world” in a loop. We’re talking baseline throughput, pipelining, JSON serialization, compression, mixed workloads, uploads, noisy neighbor tolerance, and more.

The results are… honestly fascinating. Bun is a study in contrasts.

What is Bun?

If you’ve been living under a rock: Bun is a JavaScript/TypeScript runtime built from scratch using JavaScriptCore (Safari’s engine) instead of V8. It’s written in Zig and aims to be a drop-in replacement for Node.js — but faster at everything.

Its built-in HTTP server () skips the Node.js module entirely and goes straight to optimized native code. In the HttpArena benchmark, the implementation uses and spawns one Bun process per CPU core — simple multiprocess scaling with no clustering library needed.

The Headline Numbers

Let me just lay out where Bun landed across the key tests (at 4,096 connections unless noted):

Test Rank RPS Latency (avg) Memory
Baseline #13/51 1,557,305 2.62ms 2.2 GiB
Pipelined #41/51 491,345 106.30ms 2.0 GiB
JSON #9/50 708,960 4.58ms 2.9 GiB
Compression #2/49 15,804 251.28ms 3.3 GiB
Mixed workload #1/47 52,274 72.41ms 6.1 GiB
Noisy neighbor #11/47 1,939,652 1.25ms 2.3 GiB
Limited conn #6/51 1,388,768 2.85ms 2.4 GiB
Upload (256 conn) #42/48 264 866.85ms 10.3 GiB
H2 baseline (256) #18/21 378,032 72.87ms 2.2 GiB

Read that again. #1 in mixed workloads. #2 in compression. But #41 in pipelining and #42 in uploads. That’s wild range for a single runtime.

Where Bun Dominates

Mixed Workload: The Overall Champion

The mixed workload test is the closest thing to a “real app” benchmark — it combines baseline requests, JSON serialization, compression, static file serving, and database queries all in one stream. And Bun sits at #1:

Look at that. Bun beats go-fasthttp, which is usually a throughput monster. And it does it with 6.1 GiB of RAM vs go-fasthttp’s absurd 80.7 GiB. That’s over 13x more memory-efficient.

Three of the top 5 run on the Bun runtime (bun, Elysia, Hono). The Bun ecosystem basically owns this test.

Why? My theory: Bun’s built-in gzip (), native JSON handling, and pre-loaded static files all contribute. When you mix these operations together, Bun’s “everything is native” approach pays off vs frameworks that rely on separate npm packages for each concern.

Compression: Natively Fast Gzip

Bun’s with level 1 compression keeps it competitive with Rust’s salvo and ahead of nearly everything else. Deno edges it out here (probably because Deno’s compression pipeline is also quite optimized), but check the memory: Bun uses 3.3 GiB vs Deno’s 12.8 GiB. Nearly 4x more efficient.

The implementation is elegant too — pre-compute the JSON buffer once, compress per-request:

JSON Serialization: Top 10 Overall

At #9/50 with 708,960 rps, Bun is the fastest JS/TS runtime for JSON workloads (tied with Elysia which runs on Bun). For context:

Bun is ~20% faster than Node and ~23% faster than Fastify at JSON. Not the 10x improvement some marketing suggests, but a solid, consistent edge.

Limited Connections & Noisy Neighbors

Bun handles constrained scenarios well. At limited connections (#6/51, 1,388,768 rps), it beats everything in the JS/TS world by a comfortable margin — Elysia is next at #12. Under noisy neighbor conditions (#11/47, ~1.94M rps), Bun stays stable and leads the JS/TS pack again.

Where Bun Struggles

Pipelining: The Big Miss

This is the elephant in the room. #41 out of 51 frameworks in pipelining at 4,096 connections, with only 491,345 rps and 106ms average latency.

Node.js is nearly 5x faster than Bun at pipelining. Even Express — Express! — only drops to #42. The entire Bun ecosystem (bun, Elysia, Hono) clusters at the bottom.

What’s happening? HTTP pipelining sends multiple requests over a single TCP connection without waiting for responses. Bun’s likely processes requests one-at-a-time per connection rather than batching pipelined requests. Node’s module has years of pipelining optimization baked in.

Is this a dealbreaker? Honestly, not for most real apps. HTTP pipelining is rarely used in production (browsers don’t even support it over HTTP/1.1 anymore). But if you’re building an internal service-to-service API where clients pipeline aggressively, this matters.

Uploads: Surprisingly Weak

At 256 concurrent connections uploading data, Bun lands at #42/48 with only 264 rps and 867ms latency, using 10.3 GiB of memory:

Node is 3.5x faster at uploads. Express — the framework everyone loves to call slow — handles uploads 3.6x faster than Bun. This suggests Bun’s request body reading () has significant overhead for large payloads, or there’s a memory management issue when buffering upload data.

HTTP/2: Not There Yet

Bun’s H2 support exists but isn’t competitive:

Node.js beats Bun by almost 4x in HTTP/2. Even at higher connection counts (1,024), Bun only reaches 558,342 rps. If you’re doing H2-heavy work, Node is the better runtime right now.

The “Bun Ecosystem” Effect

One of the coolest things the data reveals: frameworks running on Bun tend to perform very similarly to bare Bun. At 4,096 connections:

Framework Baseline RPS JSON RPS Mixed RPS
bun (bare) 1,557,305 708,960 52,274
Elysia 1,458,341 722,557 51,251
Hono (Bun) 1,242,917 662,019 49,378

The abstraction cost of a framework on top of Bun is remarkably small — maybe 5-20%. Compare that to Node.js where Express is 76% slower than bare Node in baseline. Bun’s API is apparently so close to what frameworks need that there’s minimal overhead in wrapping it.

Architecture: What Makes It Tick

Looking at the HttpArena implementation, a few things stand out:

Multi-process via reusePort: The entrypoint script spawns one Bun process per CPU core, each calling . The kernel load-balances connections across processes. Simple, effective, no IPC overhead.

Everything pre-loaded: Static files, datasets, and the SQLite database are all loaded at startup. The endpoint re-processes the dataset per request (as the benchmark requires), but the raw data is already in memory.

Bun.gzipSync() over zlib: The compression endpoint uses Bun’s native gzip instead of Node’s zlib bindings. This is why compression performance is stellar — it’s going through Zig’s optimized zlib implementation.

Minimal dependencies: Only for PostgreSQL. Everything else — HTTP serving, SQLite, gzip, file reading — uses Bun built-ins. Fewer layers, fewer places for overhead to hide.

Who Should Use Bun?

Based on these numbers, Bun is a strong choice if:

  • Your app does a mix of things (JSON, compression, static files, DB queries) — Bun literally wins this category
  • You want good JSON throughput without leaving the JS/TS ecosystem
  • You care about memory efficiency — Bun consistently uses less RAM than Node/Deno at similar throughput
  • You want minimal deps — built-in SQLite, gzip, and HTTP server reduce your node_modules

Think twice if:

  • You need HTTP/2 performance — Node is 4x faster today
  • You handle lots of uploads — Node/Express handle it much better
  • You’re building pipelining-heavy internal services — unlikely, but if so, Node or Deno serve this better

The Bottom Line

Bun isn’t uniformly faster than everything — no runtime is. But it has a genuinely impressive performance shape: it excels at the things most web apps actually do (mixed workloads, JSON, compression) while being memory-efficient. Its weaknesses (pipelining, uploads, H2) are in areas that matter less for typical web services.

The real story isn’t “Bun fast, Node slow.” It’s that Bun makes different tradeoffs. JavaScriptCore over V8. Native built-ins over npm packages. Simple multi-process over clustering. And for a lot of real-world use cases, those tradeoffs pay off beautifully.

All data from HttpArena (GitHub). Tests run on identical hardware with standardized configurations. Check the repo for methodology and raw data.

Previous deep dives: Actix-web | go-fasthttp | Drogon

Building a Linear Regression Model from Scratch with Gradient Descent in Python

Overview

Title

Gradient Descent Linear Regression in Python

Meta Description

Learn how to build a linear regression model from scratch using gradient descent in Python. Step‑by‑step code, math, and practical tips.

Tags

  • linearregression
  • gradientdescent
  • python
  • machinelearning
  • dataanalysis
  • codingtutorial
  • algorithm
  • mse
  • supervisedlearning

1. Introduction

Linear regression is usually the first model you build when learning machine learning. It introduces the essential concepts of parameters, loss, gradients, and optimisation in the simplest setting: a straight‑line fit.

In this post we’ll walk through a compact Python script that learns a line from five data points using gradient descent. We’ll explain the maths, step through the code, and predict a new value. By the end you’ll understand why the parameters change and how to tweak the algorithm for your own data.

2. What the program does in a nutshell

The script trains a linear model

math

to minimise mean‑squared error between predictions hat{y} and the true outputs y.

Starting from m=0, b=0, it repeatedly updates these two numbers until the loss stops improving, then prints the learned slope, intercept, and a prediction for a new input.

3. Code Implementation

import numpy as np
from tqdm import tqdm

# Data
X = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])

# Initial parameters
m = 0          # slope
b = 0          # intercept

# Hyper‑parameters
lr = 0.01      # learning rate
epochs = 1000  # number of iterations

n = len(X)     # number of training samples

# Gradient descent loop
for _ in tqdm(range(epochs)):
    y_hat = m * X + b

    dm = (-2 / n) * np.sum(X * (y - y_hat))   # gradient wrt m
    db = (-2 / n) * np.sum(y - y_hat)         # gradient wrt b

    m -= lr * dm
    b -= lr * db

print("Slope:", m)
print("Intercept:", b)

# Prediction for a new input
input_value = 6
pred = m * input_value + b
print("Predicted y for x=6:", pred)

4. Step‑by‑step walk‑through

  • Imports – numpy for vector maths; tqdm for a progress bar.
  • Data – X (inputs) and y (targets).
  • Parameters – start with m = 0, b = 0.
  • Hyper‑parameters – learning rate (lr) controls the step size; epochs limits how many updates we perform.
  • Training loop

    1. Compute predictions: y_hat = m * X + b.
    2. Compute gradients:
      • dm = (-2 / n) * np.sum(X * (y - y_hat)) (slope).
      • db = (-2 / n) * np.sum(y - y_hat) (intercept).
    3. Update parameters: move a fraction (lr) of the negative gradient.
  • After training – print the final m and b, then predict y for x = 6.

5. Key concepts (with maths)

5.1 Linear regression model

math

  • m – slope (rate of change).
  • b – intercept (value at x=0).

5.2 Loss function (mean‑squared error)

math

5.3 Gradient of the MSE

math

math

These match the dm and db formulas in the code.

5.4 Gradient descent update

With learning rate alpha:

math

math

Repeating moves the parameters toward the minimum of the loss surface.

6. Example section

Here’s what the first few iterations look like (values rounded for clarity):

Step m b MSE
0 0.000 0.000 12.80
1 0.040 0.240 8.23
2 0.070 0.360 6.46
… … … …

After 1 000 epochs the algorithm converges to approximately

Slope: 0.60
Intercept: 1.20

Predicting for x = 6 gives

math

so the program outputs “Predicted y for x=6: 4.8”.

7. Quick sanity checks

Setting Observation
Small learning rate (lr = 0.0001) Converges slowly; more epochs needed.
Large learning rate (lr = 1) Updates overshoot the optimum; loss may diverge.

Choosing a suitable lr and epochs is a standard practice for any optimisation problem.

8. Take‑away

  • This code implements ordinary least‑squares regression with gradient descent.
  • Gradient descent is a generic optimisation routine that underpins logistic regression, neural networks, and more.
  • Understanding the update equations clarifies why the parameters evolve and how to troubleshoot training.

Feel free to experiment:

  • Swap in a new dataset.
  • Try different learning rates or epoch counts.
  • Normalise your inputs or add a bias term.

Happy coding and keep building!

Slug: linear-regression-gradient-descent-python

SEO Title: Gradient Descent Linear Regression in Python

Meta Description: Learn how to build a linear regression model from scratch using gradient descent in Python. Step‑by‑step code, math, and practical tips.

Keywords: linear regression, gradient descent, python, machine learning, data science, supervised learning, mean squared error, model training, algorithm explanation

Tags: linearregression, gradientdescent, python, machinelearning, dataanalysis, codingtutorial, algorithm, mse, supervisedlearning

I Built the Cloud Resume Challenge on AWS — Here’s Everything I Learned

I’m currently studying for the AWS Solutions Architect Associate (SAA-C03)
and I wanted to go beyond flashcards and practice exams. The Cloud Resume
Challenge by Forrest Brazeal is exactly what I needed — a project that
forces you to use the services you’re studying in a real, production-grade
deployment. Here’s what I built and what I actually learned along the way.

The Stack

S3 · CloudFront · ACM · Lambda (Python) · DynamoDB ·
API Gateway · Terraform · GitHub Actions

All running on AWS Free Tier. Total cost: $0.

Live site: https://d19mfjmr0dtnqm.cloudfront.net
GitHub: https://github.com/RavjotD/cloud-resume-challenge-aws

Week by Week

Week 1–2: S3 + CloudFront

Started by writing my resume in plain HTML and CSS, deploying it to an
S3 bucket with static website hosting enabled, and putting CloudFront
in front of it for HTTPS and global edge caching. The moment I opened
that CloudFront URL and saw my resume load over HTTPS from a CDN was
the first real “I built this” moment.

One thing I didn’t expect — S3 defaults to blocking all public access.
You have to explicitly unblock it and apply a bucket policy. AWS makes
you opt in to public exposure rather than opt out. Smart default,
confusing the first time.

Week 3: DNS

Skipped the custom domain step. Route 53 isn’t in the free tier and
I didn’t want to buy a domain just for a portfolio project. The
CloudFront URL is perfectly functional for what this project needs to
demonstrate. I’ll add a custom domain when I’m hosting real client
infrastructure on this account.

Week 4: Lambda + DynamoDB

This is where the project gets interesting. I wrote a Python Lambda
function that reads a visitor count from DynamoDB, increments it, and
returns the updated value. Then I invoked it from the CLI and watched
the count go from 0 to 1 to 2 to 3 in real time.

The IAM Role setup here is directly from the SAA-C03 curriculum —
create a role, define a trust policy that allows Lambda to assume it,
attach least-privilege policies. Doing it by hand makes it click in
a way that reading about it never does.

Week 5: API Gateway

Wired Lambda to a public HTTP endpoint using API Gateway so the
browser can call it. Straightforward setup — create the API, create
the integration, create the route, deploy a stage.

Then spent way too long debugging CORS. Short version: API Gateway
was stripping the CORS headers that Lambda was correctly returning.
The fix was updating the API’s CORS configuration to explicitly allow
my CloudFront origin. The debugging process — browser console, curl
with verbose headers, Lambda invocation logs — taught me more about
how HTTP actually works than any course section on networking.

Week 6: Terraform

This was the week everything changed. I rewrote every resource I had
built manually — S3 bucket, CloudFront distribution, DynamoDB table,
Lambda function, IAM role, API Gateway — into Terraform .tf files.

The moment I ran terraform plan and saw “No changes. Your
infrastructure matches the configuration” was genuinely satisfying.
Everything I had built over 5 weeks was now codified. Someone could
clone my repo, run terraform apply, and have the entire stack
rebuilt from scratch in under 2 minutes.

I also had to import existing resources into Terraform state rather
than destroy and recreate everything. Learning the difference between
terraform import, state management, and drift detection was an
unexpected but valuable deep dive.

Week 7: GitHub Actions

Added a CI/CD pipeline that triggers on every push to main.
Two jobs run in sequence — first the test job runs my Lambda unit
tests, and only if they pass does the deploy job run, uploading the
HTML to S3 and invalidating the CloudFront cache.

First successful pipeline run completed in 6 seconds. From that
point on I never manually ran an aws s3 cp command again.

Week 8: Tests and Documentation

Wrote Python unit tests for the Lambda function using unittest and
mocking the DynamoDB table with unittest.mock. Four tests covering
the counter increment logic, status codes, CORS headers, and
DynamoDB being called correctly.

Built the architecture diagram in draw.io and added it to the repo.
Wrote this post.

The Hardest Part

CORS. It’s always CORS.

The counter wasn’t loading on the live site. No errors in the browser
console, just a dash where the number should be. I opened the Network
tab — the API request wasn’t even showing up.

Traced it step by step. Manually ran the fetch in the browser console
— it returned {count: 14} perfectly. So the API worked. The
JavaScript was correct. But the live page showed nothing.

The issue: CloudFront was caching a stale version of the HTML. I had
two CloudFront distributions — created one accidentally during
earlier testing — and I was invalidating the wrong one the whole time.
Found it by listing all distributions from the CLI and comparing the
domain names.

That kind of debugging — ruling out code, ruling out the API, tracing
the exact cached response — is exactly the thinking a solutions
architect needs. The challenge put me in a position where I had to
use it.

What I Actually Learned

Studying for the SAA-C03 teaches you what the services are. Building
this project teaches you how they fit together and where they break.

I now understand why you’d put CloudFront in front of S3 instead of
exposing S3 directly. I understand why Lambda needs an IAM Role
rather than hardcoded credentials. I understand why Terraform state
matters and what happens when it drifts. I understand why tests need
to run before deployments, not after.

None of that comes from flashcards.


What’s Next

  • AWS SAA-C03 exam — June 2026
  • Azure version of the Cloud Resume Challenge — same project
    rebuilt on Azure Blob Storage, Azure CDN, Azure Functions,
    and Cosmos DB
  • One Terraform codebase deploying to both clouds
  • One GitHub Actions pipeline deploying to both environments

The multi-cloud version is the portfolio piece I’m working toward.
When it’s done I’ll write about that too.

If you’re studying for a cloud certification and haven’t done a
hands-on project yet — start the Cloud Resume Challenge. The gap
between knowing a service and deploying one is bigger than you think,
and closing that gap is the whole point.

Async Decision Making for Remote Teams: How to Align Without Meetings

How OneMind Works

Remote teams waste hours in sync meetings that could be async. Learn why asynchronous decision making produces better alignment and how structured convergence makes it practical.

The Meeting That Could Have Been an Email — And the Email That Solved Nothing

It’s 8 AM in New York. Your engineering lead in Berlin has been online for six hours. Your designer in Tokyo already signed off. And someone just scheduled a “quick alignment call” for 4 PM UTC — which is dinner time in Berlin, midnight in Tokyo, and right in the middle of deep work for New York.

The call happens anyway. Half the team attends live. The rest watch a recording three days later and reply with comments that nobody reads because the decision already got made by whoever showed up.

This is the default decision-making process for most distributed teams. And it’s broken in ways that “better meeting hygiene” can’t fix.

The problem isn’t that your team needs better meetings. It’s that synchronous decision making fundamentally doesn’t work when your team spans time zones, schedules, and working styles. What you need are async decision making tools for remote teams — approaches that let people contribute their best thinking on their own time, then converge on an answer everyone can support.

Why Synchronous Decisions Fail Remote Teams

Time zone math is a tax on participation

For a team spanning three or more time zones, there is no “good” meeting time. Someone is always attending at an inconvenient hour. Over time, the people in the “wrong” time zone participate less, contribute less, and quietly disengage from decisions that affect their work.

Meetings reward presence, not quality

In a live meeting, the people who happen to be alert, prepared, and comfortable speaking up have outsized influence. The loudest voice in the room often wins — not because their idea is best, but because the process rewards confidence over substance. This problem compounds remotely, where connection issues and camera fatigue further skew who gets heard.

Recordings don’t equal participation

Teams try to solve the timezone problem by recording meetings. But watching a 45-minute recording is passive consumption, not participation. By the time someone comments, the group has moved on.

Decision fatigue multiplied

Remote workers attend more meetings than their in-office counterparts. Each meeting demands a context switch, draining the cognitive energy that would have produced better thinking in an asynchronous format.

Async Approaches: The Promise and the Limits

Slack polls and emoji votes

The most common async “decision tool” for remote teams is a Slack poll or emoji reaction. Someone posts a question, people react, the most popular emoji wins.

  • Pros: Zero friction, everyone knows how to use it, instant results.
  • Cons: Whoever writes the poll controls the options. No nuance. Early votes anchor later ones. No mechanism for ideas to evolve.

Email and document threads

Someone writes a proposal in a Google Doc or email, and the team comments. This gives everyone time to think and respond.

  • Pros: Asynchronous by nature, supports long-form thinking, creates a paper trail.
  • Cons: Threads fracture. Loud voices still dominate via word count. No clear mechanism to resolve disagreement. Decisions stall in “still discussing” limbo.

Dedicated async tools (Loomio, Range)

Purpose-built tools offer structured proposals with voting, threads, and deadlines. A step up from Slack polls, but most still rely on voting mechanics with their well-documented limitations. Proposals are tied to names, introducing bias. One-round voting means the group commits before ideas have been stress-tested.

What Effective Async Decision Making Actually Needs

  • Equal access: Everyone participates on their own schedule, regardless of time zone.
  • Anonymous input: Ideas compete on merit, not on who proposed them.
  • Structured evaluation: Not thumbs-up/thumbs-down, but nuanced rating across all proposals.
  • Iteration: Ideas get tested over multiple rounds, not locked in after a single vote.
  • Clear resolution: A defined endpoint so decisions don’t languish in “open” status indefinitely.

Structured Convergence: The Missing Async Decision Making Tool for Remote Teams

Structured convergence — anonymous proposing, rating, and iterative rounds — turns out to be naturally asynchronous. It works better async than sync, because it was designed around written contributions rather than verbal debate.

Step 1: Everyone proposes on their own time

A question goes out to the group. Each person submits their proposed answer anonymously within a time window — hours or days, not minutes. Your Tokyo team member contributes during their morning. Your Berlin lead adds theirs after lunch. Nobody missed the meeting because there was no meeting.

Step 2: Everyone rates every idea

Once proposals are in, each participant evaluates every idea. Not a binary vote, but a comparative rating that captures nuance. Because ideas are anonymous, the evaluation is based purely on substance.

Step 3: Top ideas advance, new ideas enter

The highest-rated proposals carry forward to the next round. Participants can submit new ideas to compete alongside the winners. Ideas get pressure-tested across rounds.

Step 4: Convergence resolves the decision

When the same idea wins back-to-back rounds, that’s convergence — genuine group alignment. The entire process happens asynchronously. No scheduling conflicts. No time zone math.

How OneMind Works

Real-World Examples: Async Decisions in Practice

Distributed engineering team: Quarterly priorities

A 15-person engineering team across San Francisco, London, and Singapore needs to decide which technical debt to tackle in Q3. With async structured convergence, all 15 engineers submit proposals during their regular hours. Anonymous rating ensures the Singapore team’s input carries equal weight. After two rounds over three days, the team converges on a database migration that the architects hadn’t prioritized but the team collectively identified as the biggest bottleneck.

Cross-timezone committee: Nonprofit policy update

A global nonprofit’s advisory committee spans six time zones. Instead of three weeks of calendar coordination, they post the policy question with a 48-hour proposing window and 24-hour rating window per round. Three rounds produce convergence incorporating perspectives from every region. Total time per participant: under 30 minutes.

Hybrid organization: Product roadmap

A 40-person company with half the team remote faces a persistent problem: in-office employees dominate roadmap decisions via hallway conversations. Async convergence levels the field. Every team member submits feature proposals anonymously. The roadmap reflects the genuine priorities of the entire team, not just those with physical proximity to decision-makers.

When Async Isn’t the Right Call

  • Crisis response: If the server is down, you need a war room, not an async poll.
  • Relationship building: Some meetings exist for trust and rapport, not decisions.
  • Creative brainstorming: Live riffing has genuine value for early-stage ideation.
  • Very small, high-trust teams: A three-person founding team probably doesn’t need formal async structure.

Making the Shift: Practical Tips

Audit your meetings first

Which recurring meetings exist primarily to make decisions? For each one, ask: “Could this decision be made better if everyone had time to think before responding?” If yes, that meeting is a candidate for async conversion.

Set explicit time windows

Instead of “respond by Friday,” try “proposing window: Tuesday 9 AM to Thursday 9 AM UTC.” Time windows give every time zone a full working day to participate.

Separate proposing from evaluating

Let everyone submit ideas first. Then evaluate as a separate step. This prevents anchoring — the first idea posted in a Slack thread no longer sets the frame for everything after.

Make anonymity the default

Remote teams have invisible power dynamics: the person in the CEO’s time zone, the one who responds fastest in Slack. Anonymous proposing and rating neutralize all of these.

Try Async Convergence with OneMind

OneMind is a free consensus-building app built for exactly this problem. Groups propose ideas anonymously, rate them fairly, and repeat rounds until one idea wins back-to-back — all asynchronously. No scheduling. No time zone math. No meetings.

If your team is tired of meetings that don’t decide anything and Slack polls that oversimplify everything, OneMind is the async decision making tool built for how remote teams actually work.

Watch a 2-minute demo: https://www.youtube.com/watch?v=zzq2TPhuVSg

Try it free at onemind.life

From Writing Terraform to Guiding AI: My Journey into Agentic DevOps with Claude Code

Ultimate Agentic Ai Cert.

Ultimate Agentic Ai Cert.
screenhot of claude.md
For a long time, I thought DevOps was just about writing scripts, managing infrastructure, and automating deployments.

Then I discovered something that changed everything:

👉 What if instead of just writing code, you could guide an AI to think like a DevOps engineer?

That’s exactly what I explored while taking the Ultimate Agentic AI DevOps with Claude Code course.

And it completely reshaped how I approach building, deploying, and managing systems.

🚀 The Shift: From Tools to Agents

Traditional DevOps is tool-driven:

  • Terraform for infrastructure
  • GitHub Actions for CI/CD
  • Bash scripts for automation

But in this course, I learned something deeper:

DevOps is evolving from tool usage → agent orchestration

Instead of doing everything manually, I started:

  • Designing workflows for AI agents
  • Defining rules for how AI should behave
  • Automating decision-making, not just execution

🧠 The Most Important Concept: Context is Everything

The biggest lesson?

AI is only as good as the context you give it.

This is where CLAUDE.md comes in.

It’s not just a documentation file — it’s a control system for AI behaviour.

Inside CLAUDE.md, I defined:

  • Project architecture
  • Deployment workflows
  • Engineering constraints
  • Rules (like no JavaScript frameworks allowed)

And something amazing happened.

When I asked Claude to:

“Add a React component to the homepage”

It refused.

Not because it couldn’t — but because it understood the rules of the system.

That moment made one thing clear:

👉 We’re no longer just writing code — we’re designing AI behaviour.

⚙️ Building Real DevOps Workflows with AI

This course wasn’t just theory — it was hands-on.

I worked on:

🔹 Terraform Automation

Using slash commands like:

/tf-plan
/tf-apply

Claude could:

  • Generate Terraform configurations
  • Validate infrastructure changes
  • Suggest improvements

🔹 GitHub Actions + OIDC

I implemented secure CI/CD pipelines using:

  • GitHub Actions
  • OpenID Connect (OIDC)

This eliminated the need for long-lived AWS credentials, making deployments more secure.

🔹 AI Sub-Agents

One of the most powerful concepts was creating specialised AI agents, such as:

  • Security agent → checks for misconfigurations
  • Cost optimisation agent → flags expensive resources
  • Deployment agent → handles release workflows

This felt like building a DevOps team powered by AI.

🔹 MCP Servers (Connecting AI to Real Infrastructure)

I also explored Model Context Protocol (MCP) servers.

This allows AI to:

  • Interact with real systems
  • Fetch live data
  • Execute meaningful DevOps tasks

Instead of static responses, AI becomes environment-aware.

🌍 Real Outcome: What I Built

To apply everything I learned, I built and deployed:

👉 A static portfolio website on AWS (S3 + CloudFront)

But this wasn’t just a basic deployment.

I used:

  • AI-assisted workflows
  • Structured project context (CLAUDE.md)
  • DevOps best practices

The result?

A clean, scalable, and production-ready deployment powered by AI-guided engineering decisions.

⚠️ Challenges I Faced

This journey wasn’t without obstacles.

  • Struggled with MCP server connections
  • Faced authentication and configuration issues
  • Had to troubleshoot CLI environments and permissions

But these challenges helped me understand:

DevOps isn’t about avoiding problems — it’s about solving them systematically.

💡 Key Takeaways

Here’s what stood out the most:

  • AI doesn’t replace engineers — it amplifies structured thinking
  • Clear documentation is now a core engineering skill
  • DevOps is evolving into AI-assisted system design
  • Security and guardrails are more important than ever
  • The future is not just automation — it’s intelligent automation

🔮 Final Thoughts

We’re entering a new phase of software engineering.

One where:

  • You don’t just write code
  • You define rules, context, and intent
  • And AI helps execute within those boundaries

Learning how to guide AI effectively is becoming just as important as learning how to code.

And for me, this course was the starting point of that journey.

🙌 Acknowledgment

Big thanks to Pravin Mishra for creating such a practical and forward-thinking course on Agentic DevOps.

📌 What’s Next?

I’m continuing to explore:

  • Advanced Terraform automation
  • AI-driven infrastructure management
  • Scalable cloud architectures

If you’re also learning DevOps or exploring AI in engineering, let’s connect and grow together 🚀

What Is Agentic Governance? (The Definition That Actually Ships)

“Agentic governance” is being used to mean two different things, and the gap between them is where most production incidents happen.

The first meaning — the one that fills enterprise whitepapers and framework documents — describes governance as a set of principles: accountability structures, ethical guidelines, oversight committees, policy documents for how AI should behave. It’s governance as intention.

The second meaning describes governance as a runtime enforcement layer: the software infrastructure that controls what AI agents are actually allowed to do at execution time, independent of what the agent’s own reasoning might suggest. It’s governance as enforcement.

The first kind of agentic governance tells you what your agents should do. The second kind determines what they can do. Most organizations investing in AI have the first kind. Far fewer have the second.

Agentic governance is the set of runtime policies and enforcement mechanisms that control what autonomous AI agents are permitted to access, spend, output, and execute — enforced at the infrastructure layer, evaluated before each action, independent of the agent’s own reasoning. It is distinct from AI governance frameworks (which define principles and accountability structures) and from AI observability (which records what agents did). Agentic governance is the enforcement layer between an agent’s intent and the real-world consequences of its actions. Without it, agents can reason correctly within their training and still take actions that violate safety, compliance, or cost constraints — because nothing stops them.

Why does the definition matter?

Because the wrong definition leads to the wrong investment.

Organizations that treat agentic governance as a framework exercise produce documentation. They define acceptable use policies, establish accountability chains, and write AI ethics principles. These are not worthless — they establish intent and can satisfy some regulatory requirements. But a framework document has no mechanism to stop an agent from routing customer PII to an external API. It has no mechanism to terminate a session that is burning $500 in API costs per minute. It has no mechanism to require human approval before an agent issues a database update.

The agent doesn’t read the governance document. It executes code.

The organizations that treat agentic governance as a runtime enforcement capability build systems that actually control agent behavior. The difference shows up in production, when something goes wrong that the framework didn’t anticipate — which is to say, regularly.

What makes a system “agentic”?

Before defining governance, it helps to be precise about what makes an AI system agentic, because the governance requirements scale directly with agentic capability.

A traditional LLM application is stateless and bounded: a user sends a prompt, the model generates a response, the interaction ends. The blast radius of a bad output is limited to that single response.

An agentic system is different in four ways that matter for governance:

Autonomy. Agents make sequences of decisions without human review at each step. They determine what to do next based on intermediate results, not just the original instruction.

Tool access. Agents don’t just generate text — they take actions. They call APIs, query databases, write files, send messages, trigger workflows. The blast radius of an agentic error is not a bad sentence — it’s a database write, a sent email, a processed transaction.

Persistence. Agents maintain context across steps and, increasingly, across sessions. They accumulate state. A governance failure that compounds across a multi-step workflow is categorically different from a single bad response.

Delegation. In multi-agent architectures, agents spawn and direct other agents. A single governance failure can propagate through a hierarchy of sub-agents before any human reviews it.

These four properties — autonomy, tool access, persistence, and delegation — are what make agentic systems powerful. They’re also what make agentic governance necessary. Each property multiplies the potential consequence of a governance gap.

What does runtime agentic governance actually enforce?

Runtime agentic governance operates across five enforcement domains. Each maps to a category of real production risk.

What is access governance for AI agents?

An agent’s capabilities are defined by what systems it can access: which databases, which APIs, which file paths, which external services. Without access governance, any tool in an agent’s definition is available to it in every context. With access governance, tool access is scoped to the session, the user, the task type, and the data classification of what’s being processed.

The enforcement question: is this agent permitted to invoke this tool, on this data, in this context?

What is cost governance for AI agents?

Agentic systems run in loops. A session that’s expected to consume $0.10 in tokens can, under the right (or wrong) conditions, consume $10 or $100. Without cost governance, the only ceiling is the API provider’s rate limits. With cost governance, a per-session token budget terminates the session before it exceeds its threshold — not after.

The enforcement question: has this session exceeded its authorized spend limit?

What is content governance for AI agents?

Agents process and generate content containing sensitive information: PII, financial data, healthcare records, confidential business information. Content governance intercepts inputs and outputs, applies classification and filtering rules, and blocks transmissions that violate data handling policies before they execute — not after they’re logged.

The enforcement question: does this content violate data handling policy for this context?

What is quality governance for AI agents?

An agent that is highly confident can still be wrong. Quality governance sets enforcement thresholds: outputs below a defined confidence level are flagged, held for review, or blocked rather than delivered. For high-stakes applications — medical information, legal advice, financial guidance — this is the difference between real enforcement and hope.

The enforcement question: does this output meet the quality threshold required for this use case?

What is operational governance for AI agents?

Beyond individual actions, agents can exhibit patterns that require intervention: retry loops that should trigger circuit breakers, sessions that should escalate to human review, operations that require approval. Operational governance defines the behavioral envelope within which agents are permitted to run.

The enforcement question: does this agent’s current behavior pattern require escalation or termination?

What agentic governance is not

Agentic governance is not observability. Observability records what your agents did. Governance controls what they’re allowed to do. You can have perfect observability — full traces, every tool call logged, complete cost data — and zero governance. You’ll know exactly what went wrong after it goes wrong. You won’t have stopped it. Observability and governance are complementary layers, not alternatives.

Agentic governance is not prompting. Writing “do not access customer financial records” in a system prompt is not governance. It’s an instruction. Agents can fail to follow instructions — due to context length limitations, adversarial injection, model drift, or simply because the edge case wasn’t anticipated. Governance operates at the infrastructure layer, not the prompt layer. It enforces regardless of what the model’s reasoning concludes.

Agentic governance is not testing. Evaluation suites, red-teaming, and pre-production testing reduce the probability of bad behavior. They do not eliminate it, and they do not intervene when novel edge cases appear in production. Runtime governance is the enforcement layer that catches what testing didn’t cover.

Agentic governance is not compliance documentation. Policy frameworks, acceptable use documents, and AI ethics guidelines establish intent and create accountability. They are not enforcement mechanisms. An agent does not consult your governance policy before making an API call.

Why the framework-first approach leaves a gap

Most enterprise AI governance investment today goes into framework governance: defining principles, establishing accountability structures, creating oversight bodies. This investment is not wasted — it’s necessary for organizational alignment and regulatory positioning.

But framework governance has a specific and predictable failure mode: it governs human decisions about AI systems, not the systems themselves.

A governance framework can establish that “agents must not process PII outside approved data regions.” A runtime governance policy can actually enforce that constraint. The framework creates the rule. The runtime layer makes the rule real.

The gap between framework governance and runtime governance is where most production AI incidents live. An agent violates a data handling policy — not because the policy didn’t exist, but because there was no enforcement mechanism between the policy document and the agent’s execution.

According to the AI Risk Management Framework published by NIST (AI RMF 1.0), effective AI governance requires both governing structures and technical controls. The technical controls — the enforcement layer — are what framework-only approaches consistently underinvest in.

The architecture of runtime agentic governance

Runtime agentic governance has three architectural requirements that distinguish it from both observability and framework governance.

Infrastructure-layer enforcement. Policies must operate at the infrastructure layer, not inside the agent’s code. An agent cannot be relied upon to govern itself — not because agents are malicious, but because their reasoning can fail, and because agent code changes frequently while governance requirements change on a different cadence. The governance layer must be independent of the agent’s own logic.

Pre-execution evaluation. Policies must evaluate before actions execute, not after they’re logged. Post-hoc detection of governance violations is valuable for learning; it is not governance. Governance is the intercepting layer between intent and consequence.

Framework agnosticism. Most organizations run agents across multiple frameworks — LangChain, CrewAI, LlamaIndex, custom Python. Runtime governance must apply consistently across all of them, enforcing the same policies regardless of what framework built the agent underneath.

How Waxell handles this

How Waxell handles this: Waxell is built around the runtime definition of agentic governance. The execution tracing layer instruments agents across any framework in three lines of SDK code, capturing the full execution graph: LLM calls, tool invocations, external API requests, token usage, costs. On top of that observability layer, runtime governance policies evaluate before each tool call and output — enforcing access scope, cost limits, content filtering, quality thresholds, and operational circuit breakers at the infrastructure layer, independent of the agent’s code. Policies are defined once and enforced across every agent regardless of framework. Enforcement records are embedded in the execution trace, creating the audit trail that compliance requires.

Agentic governance in practice: three scenarios

A financial services firm deploys a document analysis agent that reads customer financial records and generates summaries. Framework governance defines that the agent should not transmit account numbers externally. Runtime governance enforces a content policy that intercepts any outbound request containing detected account number patterns before the API call executes. The framework states the rule. The runtime layer makes it real.

A healthcare platform’s patient intake agent begins a session that enters an unexpected loop — repeatedly re-querying a symptom database due to a parsing edge case that didn’t appear in testing. Cost governance with a per-session token budget terminates the session automatically when it exceeds its threshold. Without the policy, the loop runs to timeout.

An enterprise deploys 12 agents across customer service, document processing, and internal IT functions. A quarterly compliance audit requires evidence that agents operated within data handling constraints. Waxell’s enforcement records — embedded in each execution trace — document every policy evaluation: what was checked, what triggered, what was blocked, what was allowed. The audit produces enforcement documentation, not just logs.

Frequently Asked Questions

What is agentic governance?
Agentic governance is the set of runtime policies and enforcement mechanisms that control what autonomous AI agents are permitted to do at execution time — including what tools they can access, how much they can spend, what content they can transmit, and when they must escalate to human review. It operates at the infrastructure layer, evaluated before each agent action, independent of the agent’s own reasoning. This is distinct from AI governance frameworks (which define principles and accountability structures) and from AI observability (which records what agents did). Agentic governance is enforcement, not documentation.

What is the difference between agentic governance and AI governance?
AI governance broadly refers to the policies, frameworks, and oversight structures that guide responsible AI development and deployment. Agentic governance is a specific subset focused on autonomous AI agents — systems that take sequences of actions and use tools to interact with real-world systems. Agentic governance requires runtime enforcement because agents have a broader action surface than static LLM applications: they call APIs, write to databases, and execute workflows. Framework documents can describe what agents should do; runtime governance enforces what they can do.

What is the difference between agentic governance and AI observability?
Observability gives you visibility into what your agents did: traces, logs, cost data, tool call records. Governance determines what your agents are allowed to do: it enforces policies at runtime, before actions execute. You can have complete observability and zero governance — you’ll know exactly what went wrong after the fact, but you won’t have prevented it. Waxell provides both in a unified data model, so enforcement events appear in the same execution trace as observability events.

Why can’t I govern AI agents with system prompts?
System prompts are instructions — they tell the agent what to do. They’re not enforcement mechanisms. An agent can fail to follow a system prompt instruction due to context window limitations, adversarial prompt injection, model drift, or simply unanticipated edge cases. Runtime governance operates at the infrastructure layer, outside the agent’s reasoning loop. It enforces regardless of what the model concludes — which is why it’s governance rather than guidance.

What policies does agentic governance cover?
Runtime agentic governance covers five enforcement domains: access governance (which tools and systems the agent can invoke), cost governance (per-session and cumulative spend limits), content governance (PII filtering, data classification, output screening), quality governance (confidence thresholds and output quality gates), and operational governance (circuit breakers, escalation triggers, session termination conditions). Each domain maps to a category of production risk that framework governance can describe but cannot enforce.

How is agentic governance different from AI guardrails?
“Guardrails” typically refers to input/output filtering for LLM responses — checking that outputs don’t contain harmful content or meet quality thresholds. This is content governance, which is one component of agentic governance. But agentic governance is broader: it also covers tool access control, cost enforcement, operational circuit breakers, and compliance audit trails. Guardrails address what an agent says; governance addresses what an agent does. Agents with tool access require governance across the full action surface, not just the output surface.

Sources

Bipolar and Sleep Deprivation: What Actually Happens

Originally published at steadyline.app

Sleep deprivation is one of the strongest and most consistent triggers for manic episodes in bipolar disorder. Research shows that even a single night of significantly reduced sleep can initiate hypomanic symptoms, and two consecutive nights of poor sleep substantially increases the risk of a full mood episode. The mechanism is neurological, not psychological: sleep loss destabilizes the circadian and neurotransmitter systems that are already vulnerable in bipolar disorder.

I need to tell you something that took me far too long to learn.

When I don’t sleep, what happens to me is not what happens to most people. Most people get tired. They’re groggy, they need coffee, they push through the day and crash early that night. Their system self-corrects.

Mine doesn’t. When I lose sleep, something different happens. Something that feels, at first, like the opposite of tiredness. And that’s exactly what makes it dangerous.

What actually happens: the cascade

Here’s the sequence I’ve experienced and tracked enough times to describe it with precision.

Hours 0 to 16 (the first bad night): Nothing obvious.

You slept 4 hours instead of 7. You feel a little off, maybe slightly foggy in the morning, but it clears. By midday you feel fine. Maybe even better than fine. There’s a subtle sharpness, a low-grade buzz of energy that doesn’t match the sleep deficit. If you’re not paying attention, and you’re probably not, this passes without notice.

This is where it starts. Not with a dramatic crash. With a misleading uptick.

Hours 16 to 40 (the day after, heading into night two): The divergence.

This is where the bipolar brain separates from the neurotypical response. A neurotypical brain responds to sleep debt with increasing sleepiness. The homeostatic sleep drive pushes harder, you get drowsy earlier, you sleep longer the next night. System corrects.

In bipolar, research suggests the homeostatic response can malfunction. Instead of getting sleepier, you may get more alert. Dopamine and norepinephrine spike in response to sleep deprivation, and in a brain already prone to mood dysregulation, that spike doesn’t just wake you up. It energizes you. It lifts your mood. It makes you feel productive, clear, capable.

Your brain is breaking, and it feels like your brain is finally working.

If you sleep normally on night two, you usually recover. The system resets. This is why one bad night is survivable. It’s the second night that matters.

Hours 40 to 72 (two bad nights in a row): The 48-hour window.

This is the danger zone. Two consecutive nights of short sleep, under 5 or 6 hours, is enough to destabilize the entire system in someone with bipolar. I’ve lived this pattern enough times to describe it from the inside.

Your thoughts speed up. Not anxiously. They feel fluid, connected, brilliant. You have ideas and they all seem urgent. You’re talking more, texting more, planning more. Your mood is elevated but your patience is thin. You’re euphoric and irritable at the same time, which makes no sense unless you’ve been there.

This is where the 48-hour rule becomes critical. Any decision that feels urgent at this point should wait. Because your judgment is compromised, and the urgency itself is a symptom.

Beyond 72 hours: The episode.

If the sleep deficit continues uncorrected, the cascade becomes a full mood episode. For me, this has always been mania or hypomania, though some people cascade into depression or mixed states. The early warning signs are fully present by this point. Decreased sleep need, grandiosity, rapid speech, impulsive behavior. But you don’t see them because you feel amazing. And feeling amazing after not sleeping is the most reliable sign that something is very wrong.

Why this isn’t just “being tired”

When someone without bipolar loses sleep, the effects are broadly linear. More sleep debt equals more tiredness. The response is proportional and predictable.

With bipolar, the response is nonlinear. Sleep loss doesn’t just make you tired. It triggers a cascade through your circadian system that can flip your neurochemistry into a different mode entirely. The clinical literature treats sleep deprivation as one of the most reliable experimental triggers for mania. Researchers have literally used sleep deprivation to induce hypomania in controlled settings. That’s how strong the connection is.

Here’s what that means practically. If you have bipolar and you pull an all-nighter for work, you haven’t just lost sleep. You’ve potentially initiated a process that takes days to play out and weeks to recover from. The all-nighter itself might feel fine. The episode that follows two days later will not.

I’ve seen this in my own tracking data. The worst mood episodes I’ve logged were almost always preceded by a cluster of short sleep nights. Not always dramatically short. Sometimes just 5 hours for three nights running. Enough to feel like “not a big deal” in the moment. Enough to start the cascade.

The paradox: why sleep loss feels productive

This is the cruelest trick of bipolar neurobiology.

The initial hours of sleep deprivation produce a neurochemical response that feels exactly like enhanced performance. You feel sharper. Tasks that usually bore you suddenly feel engaging. You’re writing faster, thinking faster, connecting ideas faster. The productivity is real, in the sense that output increases. But the judgment behind it degrades. Your data would show the pattern even though your feelings insist otherwise.

I’ve written code at 3 AM during these stretches that I was absolutely certain was brilliant. Some of it actually was. Most of it was not. The problem isn’t that sleep-deprived creativity is always wrong. It’s that you can’t tell the difference in the moment. And the cost of being wrong, a full episode, is vastly higher than the benefit of one productive night.

The productivity trap is particularly vicious because it creates a reinforcement loop. You lose sleep, you feel productive, you stay up to keep being productive, you lose more sleep, and the cycle accelerates. By the time the productivity curdles into irritability and chaos, you’re deep enough in the cascade that self-correction is much harder.

What I do now: the protocol

This is what I’ve built for myself after getting burned enough times.

I treat two bad nights as a medical event. Not a lifestyle inconvenience. Not something to push through. A signal that requires active response. The same way you’d respond to a 102-degree fever. You probably don’t call your doctor for a single bad night. Two consecutive bad nights? Call.

I track sleep every single day. Not just hours. Quality, timing, how rested I felt. I can see the patterns developing before they become episodes. Mood alone isn’t enough to catch this. The sleep data has to be there, tracked consistently, not reconstructed from memory.

I have a “no major decisions” rule after short sleep. This is the 48-hour rule in practice. If I slept poorly, I don’t make financial decisions, relationship decisions, or career decisions. Nothing that can’t be reversed. The urgency I feel is the symptom, not the situation.

I protect the second night. The first bad night is often out of my control. Travel, work, stress, a baby crying. The second night is where I intervene aggressively. Cancel plans. Take the prescribed sleep aid. No screens. No stimulants after noon. Whatever it takes to get 7 hours. Because that second night is the difference between a bad day and a bad month.

I tell someone. My dad, usually. “I didn’t sleep well last night, and if I don’t sleep tonight, I need you to watch for signs.” This isn’t dramatic. It’s practical. The people around you see it before you do. Giving them a heads-up when you know you’re vulnerable is one of the smartest things you can do.

The data makes it obvious

Looking back through months of tracking data, the pattern is so clear it’s almost boring. Every significant mood episode I’ve logged has a cluster of short sleep nights somewhere in the preceding week. Not every cluster of short sleep nights leads to an episode. But every episode has one.

That asymmetry is important. It means sleep tracking doesn’t give you certainty. But it gives you probability. And probability is enough to act on.

If you’re not tracking sleep alongside mood and energy, you’re missing the single most predictive dimension of bipolar stability. A complete tracking approach includes all of them. Because the cascade doesn’t show up in any single number. It shows up in the relationship between numbers over time.

I built Steadyline to catch this cascade before it plays out. The AI looks at exactly these patterns: sleep dropping, energy rising, mood and irritability diverging. It flags the pattern early, when there’s still time to do something about it. Not after the episode has started. Before.

Because sleep deprivation in bipolar isn’t just about being tired. It’s the first domino. And the only reliable way to keep the rest from falling is to see it tipping before you feel it.

Related reading:

I’m Sam, a software engineer living with bipolar disorder. I built Steadyline because the cascade from sleep loss to episode is predictable and preventable, if you have the data. More at steadyline.app.

Como eu penso e escrevo meus testes

Testes são uma parte fundamental do desenvolvimento de software. Eles nos ajudam a garantir que nosso código funcione como esperado e que possamos fazer alterações sem quebrar funcionalidades existentes.

Antes de criar uma aplicação, eu gosto de pensar em como vou testá-la. Isso me ajuda a projetar meu código de forma que ele seja mais fácil de testar.

Piramide de testes é uma forma de organizar os testes em uma aplicação. Ela é dividida em três camadas.
Na base temos os testes unitários, no meio os testes de integração e no topo os testes de ponta a ponta.

Piramide de testes

O próximo conceito de como escrever testes é o TDD (Test-Driven Development).
No TDD, escrevemos o teste antes de escrever o código. O fluxo é o seguinte:

  1. Escreva um teste que falhe.
  2. Escreva o código mínimo necessário para que o teste passe.
  3. Refatore o código para que ele fique mais limpo e organizado.
  4. Repita o processo.

Anatomia de um teste. Eu divido em 3 partes, setup, ação e verificação.

# setup
let(:user) { User.new(name: "Ewerton") }

# ação
user.save!

# verificação
expect(user).to be_persisted
``

Pensando em casos de uso, eu gosto de pensar em como o usuário vai interagir com o sistema. 
O BDD (Behavior-Driven Development) é uma forma de escrever testes que foca no comportamento do sistema.
Eu usei bastante na minha carreira uma gem para testes chamada rspec. O rspec é uma biblioteca de testes para Ruby que implementa o BDD. Aqui eu penso em 3 palavras, Given, When e Then.

1. Given (Dado que): Eu tenho uma calculadora e os números 5 e 10.
2. When (Quando): Eu executo a operação de soma.
3. Then (Então): O resultado deve ser igual a 15.

ruby
RSpec.describe “Calculator” do
describe “addition” do
let(:calculator) { Calculator.new }

context "when adding two positive numbers" do
  it "returns the sum of the two numbers" do
    result = calculator.add(5, 10)
    expect(result).to eq(15)
  end
end

end
end

class Calculator
def add(a, b)
a + b
end
end




Esse exemplo é bem simples, mas ele ilustra bem o conceito de BDD. Isso é um pouco de como penso e como escrevo testes. Mas esses conceitos são um mundo a ser explorado. Não cabe em um único artigo e pretendo escrever mais sobre testes em breve. 

4 Useful Terminal Commands for Awkward Finder Tasks (Bite-size Article)

Introduction

Today’s article is a short one, but I’d like to share four useful Terminal commands I recently learned for Finder-related tasks (Mac).

Until not long ago, I used to check these things manually, but doing them in Terminal is much faster, so I’ve been using these commands a lot lately. I decided to write this article partly as a memo for myself, and also to share them with people who may not know them yet. Much of this is fairly basic, so some of you may already know these, but if you’re interested, I hope you’ll give it a quick read.

1. Show Only Recently Updated Files

find . -type f -mtime -7

This command lists files that have been updated recently under the current directory and its subdirectories.

Finder does have a “Recent” section in the sidebar, but in my case—perhaps because of my own PC—it can sometimes take time to load, or miss files I expect to see. So this feels like a more reliable method.

The -7 part represents the number of days in the past, so it’s convenient that you can change it to any value you want.

2. Count Files

First, here is the simplest version as a basic way to count files.

find . -type f | wc -l

This command counts the number of files under the current directory (excluding folders).

If you want to include folders as well, you can use:

find . | wc -l

Note: In this form, the starting point . itself is also counted as one item. If you do not want to include it, use find . -mindepth 1 | wc -l instead.

Next, based on these commands, here is an example of excluding a specific folder.

find . -type f ! -path '*/node_modules/*' | wc -l

This counts files while excluding node_modules. In this case, the added condition is “exclude this folder.”

If you want to count only files that contain a specific string in their filename, you can change it like this:

find . -type f -name '*test*' | wc -l

This counts only files whose names contain test.

Here, the added condition is “filter by name.”

Finder already shows the number of items in a directory at the bottom by default, but by combining commands like these, you can investigate with much more specific conditions, which makes them very useful.

3. Find Empty Folders

find . -type d -empty

This command lists only empty directories.

Sometimes you create a folder during work and forget to put anything in it, or empty folders remain after reorganizing files. It is possible to look for them in Finder, but it becomes quite troublesome once the folder hierarchy gets deep.

In those situations, this command is convenient because it lets you check unnecessary empty folders all at once. It is a small thing, but quite useful when cleaning up a project.

4. Quickly See Which Folders Are Heavy

du -sh ./* | sort -h

This command displays the sizes of files and folders directly under the current directory in an easy-to-read order.

du -sh ./* shows the size of each item, and sort -h arranges them in order by size. Because of that, it is useful when you want to get a rough idea of which folders are taking up the most space.

In Finder, you can check information for individual items with Command + I, but comparing multiple folders in a list is a bit inconvenient. When you want to identify unused large data and delete it, it can be very productive to go to a suspicious directory first and run this command.

Note: In this example, hidden files and hidden folders whose names begin with a dot are not included.

Conclusion

Today I introduced four Finder-related Terminal commands that I have been using a lot recently.

Personally, many of these tasks could already be checked manually, so for a long time I never really had the idea of looking into whether there was a faster way to do them. However, once I started using them in real work, I found them extremely convenient, and I feel that they noticeably improve the speed of small verification tasks, even if only in subtle ways.

Finder can already do many things quite well, but when you want to check things with more specific conditions, Terminal still feels more useful. If I come across more commands like these, I’d like to keep sharing them here as notes for myself as well.

Thank you very much for reading!

Anchoring the Vibe: The AEGIS model

Mexian Standoff (Photo by Emilio del Prado, Wikimedia Commons)

Where different perspectives matter more than the prompt

We live in interesting and challenging times. With the introduction of AI and Large Language Models into everyone’s lives, we are experiencing a great shift in how work gets done across all industries.

As a software developer with over 20 years experience, this is by far the most significant disruption I’ve experienced. Many of the skills I’ve practiced daily — things that makes me feel proud about my work and that makes me feel professional — suddenly appears to have less value. Skills like clean code and TDD are still valuable, but they no longer have the same leverage.

I realize that I need to adapt to this reality. We all do. But my purpose of this article is not just to express personal reflections; it’s also about a concern I have related to what’s happening to the way we work and collaborate. I see patterns emerging that makes me worried.

The Mexican Standoff

Mexian Standoff (Photo by Emilio del Prado, Wikimedia Commons)

I’m a firm believer of the Agile principles — not as a set of rituals and ceremonies, but as a commitment to human relations and communication. For me the magic happens when everyone; product owners, developers , designers and other stakeholders; come together and collaborate. We all bring different backgrounds and experiences to the table and together I believe we bring the best value to our customers. And this is not easy.

I also know that far from everyone works like this today and I think that is sad. I’ve had my fair share of experiences in “the desert” but I’ve always strived to work in “a forest”, and even trying to plant one if it does not exist.

As Marc Andreessen has suggested, it looks like we are currently seeing a “Mexican standoff” happening between three roles in the software development: product owner, UX:er and developer. And this is happening because of AI.

  • The Product Owners believe they can “vibe code” a fully working, and decent looking application with a few prompts and without the involvement of developers and UX:ers.

  • The UX:ers can talk directly to the end-user to understand requirements, and develop a similar application without the need of developers or product owners.

  • The Developers can bypass the product owners and UX designers (and even other developers), figure out requirements, generating design and create the application on their own.

The scariest part? It works. It’s fast. You can go from idea to something that appears “customer-ready” in a fraction of time.

Does that mean that these three roles are now the same and capable of producing the same value? No, I don’t think so.

Does it mean that we should stick to the old barriers and silos between roles? Absolutely not.

Does this mean that the roles will change? Yes, most certainly.

Instead of waiting for the answers on how it will change, I think that all of us should embrace the tools, to learn and play with them as much as possible. But even more important, I also think we should challenge and experiment with the way we work together. Instead of continuing in the same rituals and processes as before, try to collaborate in different ways. And in doing this, recognize that our unique professional perspectives may now matter more than ever.

Cutting corners because our processes are broken is like painting over rust. Bypassing existing quality gates and challenges and leaning into “Vibe coding” might remove the immediate frustration of a handover, a conflict and disappointment, but the underlying structural issues remain. If we ignore human interaction to gain speed, we aren’t actually solving the problem of slow, incorrect deliveries — we’re just accelerating the path to a failed product.

Instead of using new technology to route around each other, let’s use it to tear down the walls. Gather around the tools and try to solve actual problems. I strongly believe that this is a recipe for success.

The Danger of “Vibe Coding”

Speed Warning Sign (Photo Adrian Newell, Pexels)

Are we underestimating the value of the team? If a product owner vibe-codes a solution without anchoring ideas and requirements with a developer, or validating the behavior and design with a UX expert, are we not missing the very essence and value of collaboration with other humans?

Speed is attractive, but we should’ve learned the hard way by now that Agile is not about speed. Vibe coding can make you addicted to the features. It is so easy and cheap to generate one new feature after another that we don’t stop to seek feedback from the users of the features. How do you ensure that you are providing value or learn from your mistakes when you can ship 30 features in a couple of vibe prompts?

I argue we should embrace a feature-by-feature approach. Keeping changes small and controlled allows us to test our assumptions with real users and learn, even if the code itself is written by AI.

Introducing the AEGIS model

A Forest (Photo Anton Atanasov, Pexels)

I’ve been experimenting with a mental model. I call it the AEGIS model. It’s an idea to ensure that we don’t drown in a flood of AI output and presumptions. The aim is instead to produce only what provides true value while encouraging close collaboration, ensuring that everyone has a place at the table.

**AEGIS **is a commitment to resolving our different perspectives into a high-density specification before an agent writes a single line of code. Whether applied to a solo project — where you rotate different “professional hats” — or within a full team, the principle remains the same: we should not underestimate the unique value that different domains and people bring to the table. By forcing this alignment up front it naturally encourages smaller, controlled features and a a continuous loop of testing and feedback.

The model is derived from the idea of Spec-Driven Development. By capturing multiple professional perspectives and storing them as part of the repository, we create a “Living Specification” that lives close to the code. This serves two critical purposes:

  1. For the Agent: It provides high-resolution requirements for the current task as well as access to a historical record of decisions taken. The AI can see the evolution and reasoning of the product, not just its current state and prompt.

  2. For the Team: It acts as professional guardrails. It reminds us to not ignore the architectural, design, or business implications that we take for granted today, and that has been built up by individuals years of experience building software. By centering our work around this shared specification, my hope is that we can break down barriers between the professions and work closer than before.

If we want to break the silos we need a new way to shake hands. AEGIS provides that structure by making sure that all features are filtered through multiple professional lenses before the actual code is generated:

  • A — Architecture: We utilize Architectural Decision Records (ADRs) to anchor the feature. This is not about what we are building, but why we have chosen a specific path, what alternatives we have discussed and what the consequences of the implementation will be.

  • E — Engineering: This is where the developer’s current craft remains essential. We provide the rules for the agent: how we want the code to be written and structured, the expected interface between modules, and strict separation of concerns. I’ve experimented with **EARS (Easy Approach to Requirements Syntax) **and have found it invaluable as a lightweight syntax for defining system logic and library preferences.

  • G — Goal: All changes needs to be justified. This is where we capture the business problem and the Value Hypothesis — what we think we’ll achieve and how we will measure success.

  • I — Interaction: This is the domain of the designer/UX:er. It can be anything from high-fidelity prototypes and wireframes to the specific color schemes, fonts, and interaction flows to ensure the product feels like ours and not something generic that the AI infers from prediction.

  • S — Specification: These are the behavioral requirements. We can use structured formats like Gherkin (Given/When/Then) or User Stories to define the functional requirements. The idea is that this becomes the source of truth that the agent must fulfill and we need a testing harness to be able to verify the behavior.

The power of traceability

I have experimented with a tagging system where every feature is assigned a unique, permanent ID. This is not just for organization; it is about creating a Traceable Thread through the life of the product.

By indexing specifications this way, we transform the collection of documents into a Relational Knowledge Base. This allows both humans and agents to navigate the “Why” behind the “What”. The idea is to get the agent to stop guessing and start operating with good context of the product’s evolution.

The Verification Loop

I think that one of the greatest risk with “Vibe Coding” is a false sense of completion. An agent might generate a beautiful UI or a complex function in seconds, but without a testing harness, that speed can be an illusion.

I believe that each feature requires a non-negotiable layer of verification. Whether the test itself is created by an agent or a human is secondary to the integrity of the proof. We should ensure that the result produced by the agent isn’t just “working code”, but a perfect match for the behavior we have specified.

This is where the human remains the ultimate judge. We can’t just “accept” the output; we need to verify it. By combining unit tests with automated test suites and acceptance testing, the hope is to turn the probabilistic nature of AI into a more deterministic professional outcome.

From Hype to Handshake

I am still experimenting with this model. Testing how AEGIS performs in the wild — not just on new “greenfield” projects, but also in the complex reality of “brownfield” legacy systems where the historical context is often missing or broken and refactoring is required.

Right now, the industry is strapped onto the hype train. I feel that we are so fascinated by the magic of the tools that we’ve stopped reflecting on how to use them together. We are treating AI as a replacement for labor, when I think we should be using it as a catalyst for closer human collaboration.

The promise of AI isn’t that it replaces the human handshake; it’s that it enables us to reach the user sooner and learn from our mistakes faster. It gives us bandwidth to stop worrying about the “how” and start obsessing over the “why”.

Why Cutting People Now is a Structural Risk

Another troubling trend that starts to appear are corporations demanding justification for their AI investments. It fells like a growing expectation that “less people can do more” now, leading to layoffs. And this before we have managed to identify and incorporate new ways of working using these tools.

Doing this while we are still in the experimentation phase is harmful. We are currently finding new ways to utilize this technology and this is changing by the minute; we must let that process take its time. If we are so stressed by the need for immediate ROI that we cut the very people who provide the “Anchor”, I think we have to question if that investment made sense in the first place.

Leaning into “Vibe Coding” as a way to justify a smaller headcount is a trap. It prioritizes the appearance of productivity over the reality of a sustainable product. If we lose our diverse professional perspectives where we seek to deliver value by balancing needs and costs, we aren’t becoming more efficient — we are just becoming more fragile.

I really want to stress that this is my opinion today. In an era where things change by the hour, my views might shift. But I strongly believe that the value right now is not in the “vibe” — it’s in the anchoring.

I would love to hear your reflections on this. Don’t hesitate to reach out to me — let’s make sure that all of us cultivate this forest together!