Blog
Notas de ingeniería
No es un resumen de mi CV, son los problemas de arquitectura y debugging que cualquier ingeniero senior termina enfrentando tarde o temprano.
Gestión de tokens OAuth a escala: lo que se rompe al pasar de una cuenta a diez
Integrar OAuth para una sola cuenta es un tutorial. Hacerlo para decenas de cuentas gestionadas centralmente es un problema de ingeniería completamente distinto.
Rate limiting hacia afuera: por qué limitarte a ti mismo es parte de la ingeniería
Casi toda la conversación sobre rate limiting es sobre proteger tu propia API de abuso externo. La mitad menos discutida es limitarte a ti mismo frente a las APIs de terceros que consumes.
Resolver problemas NP-hard con herramientas reales, no reinventándolas
La tentación de implementar tu propio algoritmo de optimización es fuerte y casi siempre equivocada. Cuándo apoyarse en herramientas especializadas es la decisión de ingeniería correcta.
Web vs. nativo: cuando una sola restricción decide toda la arquitectura
La elección entre web y nativo rara vez se decide por preferencia tecnológica. Casi siempre la decide un requisito no funcional que parece secundario hasta que no lo es.
Rotación de proxies: la ingeniería aburrida que decide si tu infraestructura sobrevive
Detrás de cualquier sistema que hace muchas peticiones salientes hay un problema poco glamoroso pero crítico: cómo saber, antes de que sea tarde, qué recursos ya no sirven.
Debugging de una race condition de UI: un caso real
Un bug que solo aparecía a veces, en cierto orden de clics, y lo que enseña sobre depurar estado compartido en el frontend.
Por qué las APIs del navegador están migrando de imperativo a declarativo
El cambio de interceptar peticiones de red línea por línea a declarar reglas por adelantado no es una moda de sintaxis. Es una respuesta directa a un problema de seguridad y rendimiento.
Degradación elegante: diseñar para que lo secundario falle sin tumbar lo esencial
Cuando un componente no crítico depende de un servicio externo, la pregunta de diseño más importante es qué pasa el día en que ese servicio no responde.
Idempotencia: el problema que todos creen entender hasta que llega el primer duplicado
Casi todo ingeniero puede definir idempotencia en una entrevista. Muy pocos sistemas la implementan correctamente donde de verdad importa.
Concurrencia en sistemas de pujas: cuando dos usuarios no pueden ganar al mismo tiempo
Un sistema de subastas en tiempo real concentra, en un solo problema, casi todos los retos clásicos de escrituras concurrentes. Lo que enseña sobre diseñar para el momento exacto en que dos personas compiten por lo mismo.
Background services en Android: una negociación constante con el sistema operativo
Por qué mantener un proceso vivo en segundo plano en Android no es un problema de código, sino de negociar garantías con un sistema diseñado para matar procesos.
Cómo diseñar un programa de referidos que no se pueda hackear
Todo incentivo monetario automatizado es, en el fondo, un sistema de seguridad. Las reglas que separan un programa de referidos sano de uno que se autodestruye.
Integración directa vs. intermediario: el trade-off que nadie discute a tiempo
Usar un proveedor intermediario acelera el arranque. Integrarse directamente con la plataforma da control total. La decisión correcta depende de una pregunta que rara vez se hace al principio.
Stateless vs. stateful: cuándo la simplicidad le gana al control
Dos formas legítimas de resolver el mismo problema de mensajería, y cómo elegir entre ellas sin caer en el dogma de 'siempre simple' o 'siempre robusto'.
Diseñar para la auditabilidad desde el modelo de datos, no como una capa de reportes
Cuando un negocio necesita responder 'qué pasó con esto exactamente', la respuesta no puede depender de reconstruir la historia después. Tiene que estar en cómo se modelaron las entidades desde el principio.
Extender un framework de terceros sin tocar su núcleo
Cuándo la respuesta correcta no es forkear ni parchear, sino diseñar tu funcionalidad como un ciudadano externo bien portado del sistema que extiendes.
Dejar que los datos expiren a propósito: el TTL como decisión de arquitectura
No todos los datos merecen vivir para siempre. Diseñar la expiración desde el modelo de datos, en vez de tratarla como un job de limpieza posterior, cambia por completo el perfil de escala de un sistema.
Diseñar para un runtime que puede morir en cualquier momento
Manifest V3 obliga a repensar cómo se mantiene vivo un estado que antes dábamos por garantizado. Lo que enseña sobre diseñar sistemas para entornos efímeros.
Connection pooling: la optimización invisible que decide si tu sistema escala
Abrir una conexión nueva por cada petición parece inofensivo hasta que el tráfico crece. Por qué el pooling de conexiones es una de las decisiones de rendimiento más subestimadas.
Reintentos que empeoran la caída: el problema de las retry storms
Reintentar una petición fallida parece la solución obvia. Sin coordinación, es una de las formas más comunes de convertir una falla pequeña en una caída total.