← Home

Blog

Insights, tutorials, and lessons learned

Comparison between Recoverable errors (typed domain errors: Effect.fail, UserNotFound, ValidationFailed, Forbidden, which belong in the signature) and Defects (out-of-type: Effect.die, DbConnectionLost, NetworkPartition, propagated as a global exception, translated into an HTTP 500).

Errors as values: typed errors vs defects

Not every error belongs in your types. How to separate recoverable domain errors from technical [...]

Diagram comparing two approaches to Agentic Coding: on the left, 'the illusion of productivity' with four topics started in parallel and none finished; on the right, 'one-piece flow' with a single topic carried all the way to production.

Faster with AI without burning out: Agentic Coding done right

Why AI exhausts so many dev teams, and how Agentic Coding done right lets you ship faster, better [...]

Function Coloring comparison: on the left, without Effect, the sync world (render, buildApp, readFile) cascades into a forced async world as soon as one function becomes asynchronous; on the right, with Effect, a single world where Effect<A, E, R> composes readFile, parseConfig and handleError identically, the runtime choosing sync or async.

Function coloring: when sync and async become an implementation detail

The Function Coloring problem between sync and async functions, and how Effect Systems like Effect [...]

Dashboard showing the number of push notifications delivered over a month: 77.52k, illustrated by a daily histogram.

Push notifications: a distributed system in its own right

From template to device: how mobile push notifications actually work, their product and technical [...]

AI is revolutionizing how we write software, not the engineer's role

AI is transforming how we write software, but not the engineer's mission: laying the rails the AI [...]

A train stamped 'LLM' at the junction of two tracks: on the left, broken rails leading into chaos for lack of standards; on the right, aligned rails lined with documentation, ADRs and best practices leading toward the horizon.

The underestimated advantage of AI

An AI agent aligns easily with a team's standards, but it amplifies the good and the bad alike. Why [...]

Illustration of Chaos Engineering: preparing for chaos, with the four steps of the scientific method (steady state, hypothesis, injection, measurement).

Chaos Engineering explained: preparing for the worst in production

Chaos Engineering, popularized by Netflix: deliberately inject failures to uncover the weaknesses [...]

Listening to bad news: Bill Gates' lesson

For Bill Gates, his most important job was making sure bad news was never ignored. A Lean lesson on [...]

Two head profiles facing each other under the title "Near Transfer": on the left a brain above an open book ("Learning"), on the right a brain above a gear ("Practice"), connected by an arrow and a checkmark.

Near Transfer: strike while the iron is hot to learn

The Near Transfer concept from neuroscience applied to Problem Solving: solving problems the moment [...]

A brick building facade whose windows have all been smashed one after another, illustrating the Broken Windows Effect.

A test that pollutes the console should fail: the Broken Windows Effect

Why a green test that pollutes stdout/stderr should be red, and how the Broken Windows Effect [...]

Worker Threads: run CPU-intensive tasks without blocking the Event Loop

How to offload CPU-intensive tasks with Node.js Worker Threads without degrading the Event Loop [...]

Blocking vs non-blocking: mastering Event Loop performance

Understanding Blocking and Non-Blocking in Node.js: the Reactor Pattern, Event Loop, thread pools [...]

Illustration of a bearded scout near a tent and a campfire, with the text 'The boy scout rule: leave the code cleaner than you found it'.

The Boy Scout Rule: leave the code cleaner

The Boy Scout Rule and Opportunistic Refactoring: turning continuous code improvement into a [...]

Illustration of the Bulkhead pattern: a ship where a single compartment, sealed off by bulkheads, takes on water and catches fire without dragging down the rest of the hull.

The Bulkhead pattern: isolate failures for a resilient app

The final pattern in the resilience series: the Bulkhead. Partition resources to isolate failures [...]

Visibly worn copy of the O'Reilly book "Distributed Systems with Node.js: Building Enterprise-Ready Backend Services" by Thomas Hunter II, resting on a dark background.

Production-ready: what an app lives after deployment

Our job doesn't stop at the commit. The pillars of an Enterprise-Ready application in production [...]

Rate limiting: protecting the server from overload

Rate Limiting to protect the server: capping requests for stability, security, and business. How it [...]

Circuit Breaker pattern: a shield against cascading failure

The Circuit Breaker, the circuit breaker of a resilient architecture: a CLOSED/OPEN/HALF-OPEN state [...]

The Timeout pattern: stopping cascading failure in prod

The Timeout pattern for resilience: bound every external interaction in time, free up resources [...]

Retry pattern: don't stop at the first error

First of 5 resilience patterns: the Retry and its backoff strategies (fixed, exponential, jitter) [...]

An import { something } from "./foo" line surrounded by question marks: the same statement may resolve to foo.ts, foo.tsx, foo/index.ts or foo/index.js, illustrating the ambiguity of module resolution.

JavaScript's module system: a hell for tooling

Why a single import triggers dozens of disk lookups, and how explicit extensions [...]

Type-Driven Development: the TDD no one talks about

Branded types, illegal states unrepresentable, parse don't validate: how to get the most out of the [...]

Enforcing a hexagonal architecture with code

Konsist, ArchUnit, eslint-plugin-boundaries: make a hexagonal architecture executable by automating [...]

Antoine Coulon presenting Effect at a conference, alongside the GitHub repository card for Effect-TS/effect: 'Build production-ready applications in TypeScript'.

How the Effect library makes you a better software engineer

Concurrency, functional programming, resilience, type-safety: why exploring Effect forces you to [...]

Diagram contrasting 'Move fast' and 'Do it well' in IT, where the 'VS' is crossed out and replaced by 'AND' to illustrate operational excellence.

Operational excellence = technical + organizational

Technical excellence alone won't make a tech product succeed. How Lean Management lets you move [...]

Concurrency: why abstractions are not enough

Callbacks, Promises, Fibers, Coroutines reduce complexity but don't eliminate resource leaks and [...]

Diagram of an optimistic update: a click moves the counter from 0 to 1 immediately, while the network request stays pending in the background.

The mishandled loading states that wreck your app's UX

Flicker, endless spinners: how to guarantee consistent loading states with spin-delay, optimistic [...]

Comparison of two models for handling I/O concurrency: on the left, the one-connection-one-thread model where N connections consume N threads via a dynamic thread pool; on the right, the Event Loop model where N connections share a single main thread backed by a fixed-size thread pool.

Concurrency: handling I/O with threads is a leaky abstraction

From Ryan Dahl's diagnosis to the birth of Node.js: why the Event Loop is an alternative to the [...]

Illustration of a smiling person energetically scrubbing a toilet, a metaphor for the work of cleaning up a messy codebase.

Is technical excellence forged in chaos?

Why spaghetti codebases and big balls of mud are the best learning opportunities to become a better [...]

Diagram of four overlapping circles titled “Evaluation and Execution strategies”: Lazy and Eager face each other on the evaluation axis, Sync and Async on the execution axis, illustrating that the two dimensions combine independently.

Evaluation strategy vs execution strategy: lazy/eager & sync/async

Two fundamental concepts often confused: the evaluation strategy (eager/lazy) decides when an [...]

Inversion of Control (IoC): the core concept and its use cases

A deep dive into Inversion of Control: its history, the Hollywood Principle, callbacks, framework [...]

Consultant: a tarnished role, but is the job to blame?

The IT consultant role suffers from a bad reputation. A look at the three pillars of the job and [...]

Two code blocks illustrating the Zalgo anti-pattern: a releaseZalgo function that invokes its callback either synchronously or asynchronously depending on a condition, and the calling code for which the execution order of 'Before', 'Done' and 'After' becomes impossible to determine.

Callbacks: the Zalgo anti-pattern, never mix sync and async

Why a callback that is both synchronous and asynchronous is an anti-pattern (Zalgo) [...]

Callbacks: a callback isn't necessarily async

Demystifying callbacks in JavaScript: the difference between synchronous and asynchronous [...]

Closures: what are they actually for?

Six concepts that rest on closures: currying, partial application, higher-order functions [...]

Closures: a closure is not just a function

Understanding closures in JavaScript: bound vs free variables, capturing the lexical context, and [...]

Lean in service of technical excellence

How Lean, seen as a continuous learning system, turns every bug into an opportunity to eradicate [...]

Automate SQL migrations with Docker Compose Watch

How Docker Compose's Watch feature (sync, rebuild, sync+restart) shortens the feedback loop and [...]

Open source: the best playground to grow as an engineer

Why open source is the best place to learn: skill growth, collaborating with the best, real impact [...]

Watch mode: Live Reload vs Hot Reload, JavaScript's envied feature

Live Reload vs Hot Reload (HMR): how they work, granularity, feedback loop, and the developer [...]

Successful tech teams have learned to solve problems

Adopt a Lean mindset to turn every obstacle into an opportunity: Continuous Delivery, root-cause [...]

Comparison between batch production and One-Piece Flow: three workstations handling pieces one at a time reduce space, Lead Time, and inventory compared to batch processing.

Cut your lead time with One-Piece Flow and Little's Law

How One-Piece Flow from Lean Management reduces Lead Time, proven mathematically with Little's Law [...]

Stop flooding your backlogs: embrace Just-in-Time

Why the backlog creates overproduction Muda, and how Just-in-Time from Lean Management aligns [...]

The DataLoader pattern: solving N+1 in GraphQL

Discover the DataLoader pattern to solve the N+1 problem in GraphQL through batching and caching [...]

Understanding the N+1 problem with GraphQL

The N+1 problem explained in detail in the context of GraphQL: how a single initial query triggers [...]

A "Muda Hunting" diagram: a trash can at the center, surrounded by seven colored shapes naming each type of waste: overproduction, overprocessing, inventory, transportation, waiting, motion and defects, each pointing an arrow toward the trash can.

The 8 Mudas of Lean: hunting waste with TIM WOOD

A tour of the 8 categories of Muda (waste) from the Toyota Production System, memorized with the [...]

Illustration of the Gemba Walk: a trail of footprints climbing toward a mountain, symbolizing the climb of continuous improvement.

The Gemba Walk: spotting problems on the ground

How the Lean-born Gemba Walk helps a Team Lead spot, on the ground, the organizational and [...]

Better type-safety in TypeScript with Branded Types

Structural vs nominal type systems in TypeScript, and how Branded Types bring type-level uniqueness [...]

Promises and resource management: the interruption problem

The little-known flaw in Promises: their non-interruptible nature prevents resources from being [...]

Generic, type parameter, type argument: real semantics

Restoring the true definition of a generic in TypeScript: a generic type takes type parameters [...]

Caching: invalidation and eviction, a cache's complexity

Understanding a cache's complexity: invalidation via TTL and eviction with the LRU, LFU and FIFO [...]

A caching story: where does a cache's speed come from?

How a cache speeds up your web apps: in-memory storage, data proximity (CDN), LRU/LFU algorithms [...]

Diagram of a private cache managed by the browser: two users query an API server that responds with Cache-Control: private, max-age=3600, each storing its own copy locally.

A caching story: speeding up a web app, simply

An intro to web caching: avoiding over-fetching with the HTTP Cache-Control header, private and [...]

Handling termination signals for graceful shutdown of containerized applications in production.

Running containerized apps in production: graceful shutdown

Why production containers need proper SIGTERM handling: graceful shutdown, the PID1 init problem [...]

The production mistake to avoid: PID1 in a container

Why your app must not be a container's PID1: signal propagation, zombie/orphan processes, Docker's [...]

Directed Acyclic Graphs (DAGs) and topological sort

Understanding DAGs: why cycles are a problem, how topological sort determines task execution order [...]

Dependency graphs: Nx, Rush, Bazel, docker-compose & CI/CD

Why dependency graphs sit at the heart of modern tooling: monorepo task orchestration, the Affected [...]

The problem-solving culture: PDCA and root causes

Why problem-solving is so rarely standardized: the Lean-born PDCA, the difference between symptom [...]

skott web app v2 rendering an interactive project dependency graph with configurable layouts.

Visualizing project dependencies with skott web app v2

A tour of skott web app v2: cluster & hierarchical graph layouts, a VSCode-like file explorer [...]

A blue TypeScript cube and a yellow JavaScript cube sitting side by side on a platform, symbolizing the choice between static typing and a dynamic language.

TypeScript or a prayer before deploy? A case for static typing

Why dropping TypeScript for untyped JavaScript is a step backward: feedback, fearless refactoring [...]

Test-Driven Development and Dependency Injection working together to drive software design.

Test-Driven Development and Dependency Injection are the way

How TDD and Dependency Injection drive software design: Test-First vs Test-Last vs TDD, baby steps [...]

Why Effect? An open-source introduction to the library

Why Effect in TypeScript: making errors and dependencies explicit, testing, resilience [...]

Code coverage versus mutation testing: why 100% coverage doesn't guarantee meaningful tests.

Don't target 100% coverage (but achieve it anyway)

Why 100% code coverage is a misleading target: a trap example, mutation testing with Stryker, and [...]

skott on the road to v1: web application, incremental processing and unused-dependency detection.

Exploring the latest features of skott: road to v1

skott's road to v1: the new web application display mode, incremental graph processing with [...]

Package managers and dependency management: installing, updating and securing software dependencies.

Everything you need to know about package managers

How package managers work: install/update/remove, dependency-tree consistency with lockfiles [...]

Abstract representation of static analysis: parsing source code into an Abstract Syntax Tree.

What it takes to build a static analysis tool

The foundations of static analysis: parsers, lexical vs syntactic analysis, Abstract Syntax Trees [...]

skott: a tool that generates a dependency graph from your JavaScript, TypeScript and Node.js projects.

Introducing skott, the new Madge

Meet skott: a devtool that builds a dependency graph of your JavaScript/TypeScript/Node.js project [...]

Implementing the Incremental/Affected build pattern with directed graphs in JavaScript.

Implementing the Incremental/Affected pattern

Build the Incremental/Affected pattern by hand: model a project as a directed graph, hash + cache [...]

Master directed graphs by example with JavaScript

An introduction to directed graphs for developers: vertices, edges and adjacency, plus three real [...]