<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Marcos Sánchez</title>
    <link>https://sonirico.dev/</link>
    <description>Recent content on Marcos Sánchez</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 06 Sep 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://sonirico.dev/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The Counterexample Is the Test</title>
      <link>https://sonirico.dev/posts/the-counterexample-is-the-test/</link>
      <pubDate>Sun, 06 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/the-counterexample-is-the-test/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve spent the week putting a TLA+ model into a side project and wiring&#xA;it into the checks. Not as a document that says the protocol is sound,&#xA;but as something that fails when the model and the code drift apart.&#xA;I understood it about halfway through doing it, which is the wrong&#xA;order, so this post does it the right way round: a counter, two&#xA;workers, and one new piece per section until the shape of the real&#xA;thing appears.&lt;/p&gt;</description>
    </item>
    <item>
      <title>WIP: an RFC for check-based monitoring semantics</title>
      <link>https://sonirico.dev/posts/rfc-check-based-monitoring/</link>
      <pubDate>Sun, 30 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/rfc-check-based-monitoring/</guid>
      <description>&lt;p&gt;Check-based monitoring has run production floors for twenty-five years&#xA;and nobody ever wrote down what it means. A scheduler runs probes, each&#xA;probe exits with a code, state machines turn streams of results into&#xA;confirmed states, and a pager goes off on confirmed transitions. Every&#xA;tool in the Nagios lineage implements this. No two of them agree at the&#xA;edges, because there is no spec to agree with: the exit-code convention,&#xA;the host/service split, UP versus OK, UNREACHABLE, soft and hard states,&#xA;acknowledgements and downtimes are folklore, documented separately and&#xA;inconsistently inside each tool that inherited them.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A k9s for Redpanda</title>
      <link>https://sonirico.dev/posts/readpanda/</link>
      <pubDate>Sat, 29 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/readpanda/</guid>
      <description>&lt;p&gt;The sagacious reader will have noticed this blog&amp;rsquo;s fondness for Redpanda&#xA;by now. My homelab keeps everything in its topics&#xA;(&lt;a href=&#34;https://sonirico.dev/posts/the-art-of-not-buying-disk/&#34;&gt;part I&lt;/a&gt;), I patched the broker&#xA;itself to read them by key&#xA;(&lt;a href=&#34;https://sonirico.dev/posts/the-art-of-not-buying-disk-part-ii/&#34;&gt;part II&lt;/a&gt;), and the&#xA;serialization experiment that became&#xA;&lt;a href=&#34;https://sonirico.dev/posts/parco-serialization/&#34;&gt;parco&lt;/a&gt; was born streaming trades through&#xA;it. Today the streak continues with something smaller: I&amp;rsquo;ve released&#xA;&lt;a href=&#34;https://github.com/sonirico/readpanda&#34;&gt;readpanda&lt;/a&gt;, a terminal UI for&#xA;looking inside those topics.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-itch&#34;&gt;The itch&lt;/h2&gt;&#xA;&lt;p&gt;My inspection loop was &lt;code&gt;rpk topic consume&lt;/code&gt; piped through &lt;code&gt;jq&lt;/code&gt;. That&#xA;works until the topic is Avro, where the payload is a magic byte, a&#xA;schema id and bytes jq won&amp;rsquo;t touch. Then the loop grows a curl to the&#xA;schema registry and a decode script, multiplied by however many topics&#xA;I&amp;rsquo;m watching. k9s solved this shape of problem for Kubernetes years&#xA;ago: stop composing the inspection by hand, put the operator inside the&#xA;cluster. I wanted the same seat for my broker.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Art of Not Buying Disk, Part II</title>
      <link>https://sonirico.dev/posts/the-art-of-not-buying-disk-part-ii/</link>
      <pubDate>Fri, 28 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/the-art-of-not-buying-disk-part-ii/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://sonirico.dev/posts/the-art-of-not-buying-disk/&#34;&gt;Part I&lt;/a&gt; ended with&#xA;&lt;a href=&#34;https://github.com/sonirico/rpkv&#34;&gt;rpkv&lt;/a&gt;: a sidecar that reads compacted&#xA;Redpanda topics by key while storing only an index, &lt;code&gt;key -&amp;gt; (partition, offset)&lt;/code&gt;. The values never leave the log. It works, and one of its&#xA;benchmark numbers is where this story starts. I&amp;rsquo;m telling it as a&#xA;timeline because that&amp;rsquo;s the order I&amp;rsquo;ll want it back in.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-floor&#34;&gt;The floor&lt;/h2&gt;&#xA;&lt;p&gt;rpkv answers a read in 11.1 ms p50 over loopback. I went looking for my&#xA;bug and found the design instead: every lookup is a real Kafka fetch, so&#xA;it pays TCP, protocol framing, and a fetch request the broker schedules&#xA;like any other, all to retrieve one record the broker could read from its&#xA;own disk in microseconds. In other words, the sidecar sits outside the&#xA;process that owns the bytes, and every read pays admission.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Allowlist That Runs Anything</title>
      <link>https://sonirico.dev/posts/the-allowlist-that-runs-anything/</link>
      <pubDate>Thu, 27 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/the-allowlist-that-runs-anything/</guid>
      <description>&lt;p&gt;I maintain &lt;a href=&#34;https://github.com/sonirico/mcp-shell&#34;&gt;mcp-shell&lt;/a&gt;, a small MCP&#xA;server that lets an LLM run shell commands under a policy you control. It has&#xA;a &amp;ldquo;secure mode&amp;rdquo; that&amp;rsquo;s supposed to be the safe default: no shell&#xA;interpretation, a narrow allowlist of executables, a parser that only accepts&#xA;a single, fully-literal command.&lt;/p&gt;&#xA;&lt;p&gt;Over a few months I got four security advisories against it. Each one was a&#xA;different command. Each one slipped past the allowlist. Each one I &amp;ldquo;fixed&amp;rdquo;&#xA;with a patch that closed that case and left the door open for the next. This&#xA;post is about why those patches kept failing, and the one change that closed&#xA;the class.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Un lexer para parsear &#39;now-24h&#39;</title>
      <link>https://sonirico.dev/posts/un-lexer-para-parsear-now-24h/</link>
      <pubDate>Mon, 24 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/un-lexer-para-parsear-now-24h/</guid>
      <description>&lt;p&gt;De vez en cuando entro en &lt;a href=&#34;https://www.npmjs.com/package/datetoken&#34;&gt;npm&lt;/a&gt; a&#xA;mirar cómo le va a datetoken. Unas mil doscientas descargas a la semana, cero&#xA;proyectos que dependan de ella. Mi teoría es que son los pipelines de CI de mi&#xA;antigua empresa, ejecutándose con la puntualidad que nunca tuvieron nuestros&#xA;informes. Si es así, es el usuario más fiel que he tenido nunca.&lt;/p&gt;&#xA;&lt;h2 id=&#34;el-problema-que-era-de-verdad&#34;&gt;El problema, que era de verdad&lt;/h2&gt;&#xA;&lt;p&gt;Datetoken nació en &lt;a href=&#34;https://wocu-monitoring.com&#34;&gt;wocu-monitoring.com&lt;/a&gt;, donde&#xA;casi todo lo que pintábamos era una ventana de tiempo relativa: las últimas 24&#xA;horas, la última semana. Si el frontend resolvía &amp;ldquo;las últimas 24 horas&amp;rdquo; a dos&#xA;timestamps y los metía en la URL, cada petición era única en el universo y la&#xA;caché del recurso no servía para nada, porque el &amp;ldquo;ahora&amp;rdquo; cambiaba en cada&#xA;segundo que pasaba.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Job Board That Remembers</title>
      <link>https://sonirico.dev/posts/a-job-board-that-remembers/</link>
      <pubDate>Mon, 17 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/a-job-board-that-remembers/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve put &lt;a href=&#34;https://jobctl.net&#34;&gt;jobctl.net&lt;/a&gt; online. It&amp;rsquo;s a job board that&#xA;keeps the history other job boards throw away. Postings are polled,&#xA;reconciled against the last look, and every difference is written down:&#xA;appeared, changed, went missing, closed, came back. It&amp;rsquo;s small and it&amp;rsquo;s&#xA;opinionated. It exists because of two grudges and one curiosity.&lt;/p&gt;&#xA;&lt;h2 id=&#34;grudge-one-they-took-rss-away&#34;&gt;Grudge one: they took RSS away&lt;/h2&gt;&#xA;&lt;p&gt;Browsers used to understand feeds. There was an icon in the address bar,&#xA;you clicked it, and from then on the site came to you. Firefox&#xA;&lt;a href=&#34;https://support.mozilla.org/en-US/kb/feed-reader-replacements-firefox&#34;&gt;removed live bookmarks in 2018&lt;/a&gt;.&#xA;Chrome never cared. Safari still has an RSS button, though I don&amp;rsquo;t think&#xA;anyone at Apple remembers why. The web didn&amp;rsquo;t stop publishing feeds. Most&#xA;of it still does. It just stopped telling you.&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Art of Not Buying Disk</title>
      <link>https://sonirico.dev/posts/the-art-of-not-buying-disk/</link>
      <pubDate>Tue, 11 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/the-art-of-not-buying-disk/</guid>
      <description>&lt;p&gt;I have released &lt;a href=&#34;https://github.com/sonirico/rpkv&#34;&gt;rpkv&lt;/a&gt; v0.1.0: key-value&#xA;reads over Redpanda topics without duplicating values. That is the whole&#xA;pitch. &amp;ldquo;Without duplicating values&amp;rdquo; is not a feature. It is a grudge.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-economics-of-2026-hardware&#34;&gt;The economics of 2026 hardware&lt;/h2&gt;&#xA;&lt;p&gt;RAM is currently priced like it is mined by hand. NVMe went up with it,&#xA;out of solidarity. The industry&amp;rsquo;s advice has not changed: buy more anyway.&#xA;Storage is cheap, say the articles, all of them written when it was.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Paranoid</title>
      <link>https://sonirico.dev/minijuegos/paranoid/</link>
      <pubDate>Sun, 19 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/minijuegos/paranoid/</guid>
      <description>Un clon de Arkanoid empezado en 2014 y terminado en 2026. Rompe el muro, caza las cápsulas, persigue la máxima puntuación.</description>
    </item>
    <item>
      <title>The Repository Graveyard Just Lost a Tenant</title>
      <link>https://sonirico.dev/posts/repository-graveyard/</link>
      <pubDate>Mon, 13 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/repository-graveyard/</guid>
      <description>&lt;p&gt;Every developer I know keeps a graveyard. Mine lives under &lt;code&gt;~/src&lt;/code&gt;. Until recently its most distinguished resident was an Arkanoid clone I started in 2014, a game that was born dead. It never compiled for anyone but me. It never shipped. It never earned a README. It had a paddle, a ball, four levels, and the smell of a side project abandoned the week reality resumed. Twelve years in the freezer. The first commit of its resurrection says, with more honesty than I usually put in commit messages, &lt;em&gt;&amp;ldquo;Rescue operation done.&amp;rdquo;&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>El aire acondicionado no fabrica frío</title>
      <link>https://sonirico.dev/posts/aire-acondicionado/</link>
      <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/aire-acondicionado/</guid>
      <description>&lt;p&gt;Cada verano me pasa lo mismo. Alguien me explica cómo funciona el aire acondicionado &amp;ndash;o lo leo, o me lo cuenta un vídeo&amp;ndash;, lo entiendo con esa sensación limpia de haberlo entendido de verdad, y unas semanas después ya no sabría reconstruirlo sin ayuda. Llevo años en ese bucle, así que esta vez lo dejo escrito, con diagramas y todo, para el yo del verano que viene. Esto no va de sistemas distribuidos ni de colas de mensajes; va del aparato que tengo colgado en la pared del salón, que sospecho que es la pieza de ingeniería más antiintuitiva de toda mi casa.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Parallelization Index</title>
      <link>https://sonirico.dev/posts/parallelization-index/</link>
      <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/parallelization-index/</guid>
      <description>&lt;p&gt;El otro día me encontré con cuatro terminales abiertas, cada una con un agente trabajando en una parte distinta del sistema: uno refactorizando el módulo de autenticación, otro generando tests de integración para un servicio nuevo, un tercero explorando una migración de base de datos y el cuarto escribiendo el plan de un cambio en la capa de eventos. Cuatro líneas de trabajo en paralelo, todas avanzando, todas requiriendo mi atención intermitente para validar decisiones, corregir el rumbo, aprobar o rechazar. Y me descubrí pensando algo incómodo: &lt;em&gt;esto no se parece en nada a lo que hacía hace dos años, y sin embargo es lo más productivo que he sido nunca.&lt;/em&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Plan-Driven Development</title>
      <link>https://sonirico.dev/posts/plan-driven-development/</link>
      <pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/plan-driven-development/</guid>
      <description>&lt;p&gt;Estaba hace unos meses inmerso en un cambio arquitectural de cierta envergadura: sistema de colas, muchas piezas móviles, el tipo de modificación que toca suficientes capas del sistema como para que un error de criterio sea difícil de deshacer. Abrí el modo de planificación del agente y empecé a trabajar con él: que escaneara el código existente, que identificara dependencias, que propusiera opciones y razonara las descartadas. El plan fue creciendo solo, incorporando trade-offs, fragmentos de código, enlaces a funciones concretas. En algún punto me alejé del teclado y lo leí de un tirón, como se lee un documento antes de enviárselo a alguien.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Parco: An Experiment in Go Serialization</title>
      <link>https://sonirico.dev/posts/parco-serialization/</link>
      <pubDate>Sat, 07 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/posts/parco-serialization/</guid>
      <description>&lt;p&gt;At Atani we built a real-time producer that connected to over 30 cryptocurrency exchanges and DEXes. It streamed trades, orderbook updates and market data through Redpanda and NATS to a crowd of consumers. Millions of messages a day. Microseconds mattered.&lt;/p&gt;&#xA;&lt;p&gt;We used &lt;code&gt;easyjson&lt;/code&gt; for serialization. It worked. JSON is readable and debuggable, and easyjson generates marshal code that&amp;rsquo;s much faster than the standard library. For our throughput and latency it was enough.&lt;/p&gt;</description>
    </item>
    <item>
      <title>About</title>
      <link>https://sonirico.dev/about/</link>
      <pubDate>Thu, 09 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/about/</guid>
      <description>&lt;h2 id=&#34;who&#34;&gt;Who&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;m Marcos Sánchez. I work as a Site Reliability Engineer at&#xA;&lt;a href=&#34;https://www.chess.com&#34;&gt;Chess.com&lt;/a&gt;, from Madrid. Before that I spent six years&#xA;at &lt;a href=&#34;https://web.archive.org/web/20250617093636/https://atani.com/en/&#34;&gt;Atani&lt;/a&gt;,&#xA;now defunct, building the real-time plumbing of a crypto exchange: order&#xA;books from thirty venues, billions of messages a day, microseconds that&#xA;mattered. Most of what I know about systems I learned there, at 03:00,&#xA;from things that had broken.&lt;/p&gt;&#xA;&lt;h2 id=&#34;why-this-site-exists&#34;&gt;Why this site exists&lt;/h2&gt;&#xA;&lt;p&gt;Three reasons, in the order they occurred to me.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Career Timeline</title>
      <link>https://sonirico.dev/career/</link>
      <pubDate>Thu, 09 Oct 2025 00:00:00 +0000</pubDate>
      <guid>https://sonirico.dev/career/</guid>
      <description>&lt;p&gt;A chronological timeline of my career building distributed systems and leading technical teams.&lt;/p&gt;&#xA;&lt;h2 id=&#34;site-reliability-engineer-at-chesscom&#34;&gt;&lt;strong&gt;Site Reliability Engineer&lt;/strong&gt; at Chess.com&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;November 2025 - Present | Remote&lt;/em&gt;&lt;/p&gt;&#xA;&lt;p&gt;Reliability and infrastructure work for a high-traffic platform serving millions of players. Focused on keeping production available, observable, and fast.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Key responsibilities:&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Own service availability, incident response, and operational readiness&lt;/li&gt;&#xA;&lt;li&gt;Improve observability and performance across production systems&lt;/li&gt;&#xA;&lt;li&gt;Automate infrastructure and delivery workflows&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;senior-reliability-engineer-at-atani&#34;&gt;&lt;strong&gt;Senior Reliability Engineer&lt;/strong&gt; at Atani&lt;/h2&gt;&#xA;&lt;p&gt;&lt;em&gt;December 2023 - October 2025 | Madrid&lt;/em&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
