Clock with multiple time zones representing UTC and local times in ETL

UTC, Time Zones, and ETL: A Real Story About a Silent DST Bug (and a Lucky Escape)

The guiding principle (the motto) Keep UTC for as long as possible. Change to a local timezone only when it is truly required. This principle was not theoretical. It emerged from a real incident — one that almost became a production bug, and only didn’t because of a fortunate configuration coincidence. Why time zones are dangerous in ETL Time-related issues are among the hardest problems in data engineering because: ...

January 18, 2026 · 6 min · Frederico Gago
Deterministic UUID v5 generation with namespaces and separators to avoid collisions

UUID v5 as a Primary Key in PostgreSQL: when business keys stop being unique (and how to avoid collisions)

Summary I was generating deterministic UUID v5 primary keys from business keys. It worked well—until subtle but serious collision risks appeared: Ambiguous concatenation (ab + cd vs a + bcd) Cross-table collisions (different tables, same business values → same UUID) This post presents a clean, modular solution using explicit separators and namespace scoping, and explores the harder problem of multi-source ingestion. ⚙️ Context & Problem In data platforms and ETL systems, business keys are often the only stable identifiers available (for example, composite natural keys). To ensure idempotency and simplify upserts and deduplication, a common pattern is: ...

January 18, 2026 · 6 min · Frederico Gago
PostgreSQL index tree and storage pages visualization

Indexes and Fillfactor in PostgreSQL: Power, Trade-offs, and the Cost of Speed

Resumo: Indexes are one of the first performance tools every PostgreSQL user learns — and one of the easiest ways to accidentally slow a system down. This article explains how indexes actually work, why they are never free, how different index types behave in real workloads, and how fillfactor quietly determines whether your database ages gracefully or slowly collapses under write pressure. Indexes Feel Like Magic (At First) You run a query on a table with millions of rows. ...

January 18, 2026 · 5 min · Frederico Gago
SQL and ORM balance for backend developers

Why Every Backend Developer Should Master SQL — Even in the Age of ORMs

Summary: ORMs make development faster, but mastering SQL and database internals turns good backend engineers into great ones. Here’s why understanding both levels — abstraction and reality — matters. ⚙️ Context & Problem Modern web frameworks — Django, FastAPI, Spring Boot, Laravel — all encourage the use of Object-Relational Mappers (ORMs). They make it easy to map objects to tables, run queries in a few lines of code, and forget about SQL altogether. ...

October 26, 2025 · 5 min · Frederico Gago
Microservices Resilience Cover Image

How to Handle Microservice Failures: The Ambiguous Timeout Dilemma

🧩 The Classic Problem: When a Service Doesn’t Respond Imagine the following flow in a service-oriented system: Client → the-api → the-upstream → Database 1️⃣ The client calls the-api/v1/test 2️⃣ the-api calls the-upstream 3️⃣ the-upstream writes data into its own database 4️⃣ It replies OK to the-api 5️⃣ the-api stores the result in its database and replies OK to the client Everything works fine — until step 4 (D) fails because of a network partition or timeout. Now, the-api doesn’t know if the upstream actually wrote the data or not. You can’t safely commit your local write — and you can’t confidently reply to the client. ...

October 6, 2025 · 5 min · Frederico Gago
Conceptual diagram of a Unit of Work with application and persistence layers

Unit of Work (UoW) in Python with SQLAlchemy: explicit transactions, savepoints, and outbox

Building a Production-Grade Unit of Work (UoW) System in Python with SQLAlchemy When you build complex applications with databases, services, and background jobs, you eventually run into the transaction problem: How do I guarantee all operations happen atomically? How do I handle nested scopes (reuse vs rollback)? How do I ensure events are only published once? How do I protect against duplicate commits when retries happen? The solution is a Unit of Work (UoW) system — a design pattern that wraps all your persistence operations in a clear, explicit transaction boundary. ...

September 26, 2025 · 5 min · Frederico Gago
Ilustração de reconciliação de dados

Reconciliação Automática de Contribuições (ERP ↔ Portal) com Python

Resumo: Como automatizei a reconciliação mensal de contribuições entre um ERP e um portal externo. Mostro padrões reutilizáveis: bounded concurrency, retry com backoff + jitter, tolerância monetária, bucketização por período+taxa e upsert idempotente de divergências — usando value objects (YearMonth, Money) e ports (interfaces). Sem expor integrações reais: o foco é a arquitetura e as ideias reutilizáveis. ⚙️ Contexto & Problema Em RH, após o processamento salarial (até dia 10 em PT), é enviado o mapa de contribuições do mês anterior para o portal oficial. Se ocorrerem alterações após o envio (ajustes, faltas, prémios, correções), é fácil esquecer o reenvio do mapa corrigido — gerando inconsistências com risco regulatório e retrabalho. ...

September 11, 2025 · 5 min · Frederico Gago
Illustration of string prefixes

Longest Common Prefix: Five Algorithms Compared

🔢 Problem Statement LeetCode 14 – Longest Common Prefix Given an array of strings, return the longest common prefix among them. If no common prefix exists, return an empty string (""). Example 1 Input: ["flower", "flow", "flight"] → Output: "fl" Example 2 Input: ["dog", "racecar", "car"] → Output: "" Constraints 1 ≤ strs.length ≤ 200 0 ≤ strs[i].length ≤ 200 strs[i] contains only lowercase English letters if non-empty. 👨‍💻 Solution Strategies We’ll explore and compare five distinct approaches, from brute force to divide & conquer: ...

August 3, 2025 · 3 min · Frederico Gago
Cover Image

From Spreadsheets to Scripts: My Journey Automating Accounting with Python

From Spreadsheets to Scripts: My Journey Automating Accounting with Python My journey into process automation started at an accounting firm, where I quickly found myself buried in repetitive manual tasks and inefficient workflows. From processing invoices to reconciling spreadsheets, I could see how much time was being lost to work that could — and should — be automated. When I started working there, I spent the first few months organizing paperwork and doing basic data entry. I quickly realized two things: ...

July 27, 2025 · 4 min · Frederico Gago
Python Code Cover Image

Roman to Integer — Clean, Fast, and Functional Approaches Compared

🧩 Problem: Roman to Integer (LeetCode 13) Convert a string representing a Roman numeral into its integer value. Roman numerals are typically written from largest to smallest (left to right), except for six well-known subtractive cases: I before V or X → 4, 9 X before L or C → 40, 90 C before D or M → 400, 900 ✅ Clean Idiomatic Solution (One-Pass) class Solution: SYMBOLS = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 } def romanToInt(self, s: str) -> int: total = 0 prev_value = 0 for c in s: value = self.SYMBOLS[c] total += value - 2 * prev_value if value > prev_value else value prev_value = value return total Single loop Detects subtractive patterns with value > prev_value Clean inline logic ✅ Runtime: 3 ms (faster than 79.17%) ✅ Memory: 17.6 MB (less than 90.19%) ...

July 20, 2025 · 3 min · Frederico Gago