<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.2">Jekyll</generator><link href="https://www.abhinav.co/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.abhinav.co/" rel="alternate" type="text/html" /><updated>2026-06-19T22:08:33+00:00</updated><id>https://www.abhinav.co/feed.xml</id><title type="html">Abhinav Saxena</title><subtitle>I&apos;m Abhinav. I am a generalist with interests in entrepreneurship, software engineering, product management, and engineering leadership.
</subtitle><author><name>Abhinav Saxena</name></author><entry><title type="html">From rails to a paved road</title><link href="https://www.abhinav.co/introducing-pave" rel="alternate" type="text/html" title="From rails to a paved road" /><published>2026-06-07T00:00:00+00:00</published><updated>2026-06-07T00:00:00+00:00</updated><id>https://www.abhinav.co/introducing-pave</id><content type="html" xml:base="https://www.abhinav.co/introducing-pave">&lt;p&gt;For years, the most fun I had building anything was on Rails and Phoenix.&lt;/p&gt;

&lt;p&gt;Not because of the languages. Because of the feeling. You ran one generator, you got a working app with auth, a database, background jobs, and a deploy story, and then you spent your time on the thing you actually wanted to build. The framework had already made a hundred decisions for you, and most of them were right.&lt;/p&gt;

&lt;p&gt;Then I would go back to Python and feel the difference immediately.&lt;/p&gt;

&lt;p&gt;Python is the language I reach for most. But for years the honest answer to “how do I structure a real web app in Python” was Django, and Django is excellent at exactly the kind of app it was designed for. FastAPI is where a lot of new energy went, and deservedly so. It is fast, it is typed, the developer experience is lovely. But FastAPI hands you a request router and wishes you luck. Auth, sessions, jobs, deploy, the folder layout, the thing that turns a tutorial into a product - all of that is left as an exercise.&lt;/p&gt;

&lt;p&gt;So everyone writes that glue themselves. Badly, usually, and differently every time. I have done it more than once, and did not enjoy it any of the times.&lt;/p&gt;

&lt;p&gt;Pave is my attempt to stop writing it.&lt;/p&gt;

&lt;p&gt;The pitch is one line: full-stack Python, no React required. You write FastAPI. Pave handles the parts around it - auth, background jobs, an HTMX component kit, a markdown content system, and a deploy pipeline - and it ships your app to a real Linux box with one SSH command.&lt;/p&gt;

&lt;h2 id=&quot;boring-on-purpose&quot;&gt;boring on purpose&lt;/h2&gt;

&lt;p&gt;The first decision I made was the one most people will argue with, so let me say it plainly. No Docker. No Kubernetes. No Node build step.&lt;/p&gt;

&lt;p&gt;I want to be careful here, because this is a preference, not a law. There are good reasons to reach for containers, and if you already run a fleet on Kubernetes, Pave is not asking you to tear it down. But for the app that does not exist yet - the one you are trying to get to its first real user - all of that is ceremony you pay for before you have earned it.&lt;/p&gt;

&lt;p&gt;A handful of long-lived Python processes supervised by systemd will carry most apps a lot further than people admit. So that is what Pave does. It ships Python files to an Ubuntu host and runs them under systemd, behind Nginx, served by Gunicorn. Migrations with Alembic. The ORM is SQLAlchemy 2.0, async. Deploy is Fabric.&lt;/p&gt;

&lt;p&gt;The whole thing is the kind of stack a sysadmin in 2010 would recognize, and I mean that as the highest compliment I can give infrastructure. It is boring. Boring things do not page you at 2am.&lt;/p&gt;

&lt;p&gt;If you have heard “you’ll regret not using Docker” enough times to half-believe it, here is the honest trade-off. The day you genuinely outgrow one box, you will have to do some work to move. But there is no Pave-specific lock-in to undo first, and you will be doing that work with real traffic and real numbers in front of you, instead of guessing about scale you do not have yet.&lt;/p&gt;

&lt;h2 id=&quot;the-job-queue-problem&quot;&gt;the job queue problem&lt;/h2&gt;

&lt;p&gt;Background jobs are where the boring-infra promise usually breaks.&lt;/p&gt;

&lt;p&gt;You want to send a verification email without making the user wait for it. Easy enough. So you reach for a job queue. The standard answer in Python is Celery, and Celery wants Redis or RabbitMQ. Now your “one box, one database” app has grown a second piece of infrastructure whose only job is to hold a list of things to do later.&lt;/p&gt;

&lt;p&gt;You already have a database that is very good at holding lists of things. It is right there. It is Postgres.&lt;/p&gt;

&lt;p&gt;So Pave’s job queue, Soniq, runs on Postgres. No Redis, no broker, no new daemon to babysit. It does the unglamorous things a queue needs to do - retries, a worker you run with one command - and it does them against the database you were already running. Two real jobs ship with Pave as worked examples, not toys: processing a webhook, and sending that verification email off the request path.&lt;/p&gt;

&lt;p&gt;I wrote &lt;a href=&quot;https://github.com/abhinavs/soniq&quot;&gt;Soniq&lt;/a&gt; as its own library because I kept wanting it in projects that had nothing to do with Pave. But this is the project where it earns its keep. One fewer moving part is not a small thing. It is the whole point.&lt;/p&gt;

&lt;h2 id=&quot;no-react-and-i-mean-it&quot;&gt;no React, and I mean it&lt;/h2&gt;

&lt;p&gt;The other place I dug in is the frontend.&lt;/p&gt;

&lt;p&gt;I have watched the React tax get paid for more than a decade, on teams I led that shipped React and React Native. My own frontend JavaScript was Backbone, back when that was the reasonable choice. So for this class of app I am opting out, and the reflex I am opting out of is reaching for a separate frontend build, a Node toolchain, and a single-page app for what is fundamentally a few forms and an admin dashboard. You are now running two applications that have to agree with each other, and a build step that breaks in its own special ways.&lt;/p&gt;

&lt;p&gt;Pave renders on the server. The components are Jinja2 templates, made interactive with HTMX and a little Alpine.js, styled with Tailwind. Every component traces back to one set of design tokens, so the buttons match the forms match the cards without anyone freelancing a hex code at midnight. Dark by default, with a real light theme, responsive down to a phone, all from the same templates. No separate mobile build.&lt;/p&gt;

&lt;p&gt;There is no package.json. Tailwind runs from a standalone binary. I will admit I was a little smug the first time I deleted node_modules from a project and nothing broke.
t
This will not suit everyone, and the README says so. If you are building a rich SPA, the HTMX kit will fight you, and you should use something built for that fight. But for the enormous category of apps that are mostly server-rendered pages with some interactivity, all of that JavaScript machinery was solving a problem you did not have.&lt;/p&gt;

&lt;h2 id=&quot;deploy-in-one-line&quot;&gt;deploy in one line&lt;/h2&gt;

&lt;p&gt;Here is the part I am most quietly proud of.&lt;/p&gt;

&lt;p&gt;Once a server is prepared, you deploy with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fab production deploy&lt;/code&gt;. That one command validates your environment schema, builds the CSS, runs migrations and tests and the type check, snapshots a new release on the server, flips a symlink to make it live atomically, restarts the systemd service, and then probes /health. If the health check fails, it rolls back on its own before the command even returns to your prompt.&lt;/p&gt;

&lt;p&gt;That last sentence is the one that matters. The deploys that hurt are not the ones that fail loudly. They are the ones that half-succeed and leave you SSHed into a box at midnight trying to remember what the last good state was. The release-directory model and the automatic rollback exist so that a bad deploy is a non-event. The old version never went anywhere. You flip back.&lt;/p&gt;

&lt;p&gt;That is the part Python never gave me. Not the speed of the first deploy, the calm of every one after it. Rails and Phoenix made deploying boring years ago, and boring is exactly what you want from the thing that puts your work in front of people. This is me trying to make it boring in Python.&lt;/p&gt;

&lt;h2 id=&quot;what-this-actually-is&quot;&gt;what this actually is&lt;/h2&gt;

&lt;p&gt;Pave is not a framework. It is a template - a starting point you clone, with the boring decisions already made and wired together correctly, so you can delete the ones you disagree with instead of assembling everything from nothing.&lt;/p&gt;

&lt;p&gt;It is pre-1.0, so the API may still shift. The name comes from the obvious place: you pave a path before you walk it. Pave lays the production surface down first, then you build on top.&lt;/p&gt;

&lt;p&gt;I built it because I wanted, in Python, the absence of a hundred small fights before the first real line of my own code. Not the magic. Just that.&lt;/p&gt;

&lt;p&gt;It is MIT licensed and on GitHub at &lt;a href=&quot;https://github.com/abhinavs/pave&quot;&gt;github.com/abhinavs/pave&lt;/a&gt;. Fork it, ship it, change the name on the tin.&lt;/p&gt;

&lt;p&gt;I am going back to building the app now. Which, I suppose, was the entire idea.&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="Python" /><category term="FastAPI" /><category term="Pave" /><category term="Soniq" /><category term="Infrastructure" /><category term="Ideas" /><summary type="html">Full-stack Python, no React required. I loved what Rails and Phoenix gave me. I wanted the same thing in Python, on a surface I laid myself.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing sqlalchemy-annotate</title><link href="https://www.abhinav.co/sqlalchemy-annotate" rel="alternate" type="text/html" title="Introducing sqlalchemy-annotate" /><published>2026-05-19T00:00:00+00:00</published><updated>2026-05-19T00:00:00+00:00</updated><id>https://www.abhinav.co/sqlalchemy-annotate</id><content type="html" xml:base="https://www.abhinav.co/sqlalchemy-annotate">&lt;p&gt;I have released &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sqlalchemy-annotate&lt;/code&gt;, a small command-line tool that keeps a schema summary at the top of every SQLAlchemy model file.&lt;/p&gt;

&lt;p&gt;When you read a SQLAlchemy model, the Python tells you which attributes exist but not what the database does with them. Whether a column is nullable, how long a string can be, which columns are indexed, what the foreign keys point at - none of that is visible in the model. You have to open the migration or connect to the database to find out. Rails has addressed this for years with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;annotate_models&lt;/code&gt;. This tool brings the same idea to modern SQLAlchemy 2.x and Alembic projects.&lt;/p&gt;

&lt;p&gt;It maintains a block like this, kept in sync with your actual metadata:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# == Schema Information
#
# Table name: users
#
# id         : integer, primary key
# email      : varchar, not null
# created_at : timestamp
#
# Indexes
#   ix_users_email (email) UNIQUE
#
# == End Schema Information
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are three commands. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sqlalchemy-annotate generate&lt;/code&gt; writes or updates the block, typically run after a migration. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sqlalchemy-annotate check&lt;/code&gt; exits non-zero when a model has drifted from its comment, which makes it suitable as a CI gate or pre-commit hook. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sqlalchemy-annotate remove&lt;/code&gt; strips every block.&lt;/p&gt;

&lt;p&gt;Two design decisions are worth stating directly.&lt;/p&gt;

&lt;p&gt;First, it never connects to a database. The schema is read from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base.metadata&lt;/code&gt;. If you pass a connection URL, only its dialect is used, so types compile correctly offline, and the URL is then discarded. Annotating a file does not require database credentials.&lt;/p&gt;

&lt;p&gt;Second, it does not rewrite files with regular expressions. All edits go through a single libcst transformer, so imports, comments, blank lines and formatting outside the marked block are preserved exactly. Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generate&lt;/code&gt; twice produces no further change, which is what makes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;check&lt;/code&gt; reliable.&lt;/p&gt;

&lt;p&gt;One trade-off should be clear before you adopt it. The tool imports your model package, in the same way pytest and Alembic do. If importing your models triggers side effects, those will run. For most projects this is not an issue, but it is worth knowing.&lt;/p&gt;

&lt;p&gt;Installation is from PyPI:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install sqlalchemy-annotate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The source, full documentation and configuration options are at &lt;a href=&quot;https://github.com/abhinavs/sqlalchemy-annotate&quot;&gt;github.com/abhinavs/sqlalchemy-annotate&lt;/a&gt;. The tool is intentionally small. The schema already exists in your metadata; this simply puts it where the person reading the model can see it.&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="Python" /><category term="SQLAlchemy" /><category term="Alembic" /><category term="Databases" /><category term="Open Source" /><category term="Engineering" /><summary type="html">A small command-line tool that keeps a schema summary at the top of every SQLAlchemy model file.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Introducing Soniq</title><link href="https://www.abhinav.co/soniq" rel="alternate" type="text/html" title="Introducing Soniq" /><published>2026-05-03T00:00:00+00:00</published><updated>2026-05-03T00:00:00+00:00</updated><id>https://www.abhinav.co/soniq</id><content type="html" xml:base="https://www.abhinav.co/soniq">&lt;h2 id=&quot;soniq---the-job-queue-for-people-who-dont-want-another-job-queue&quot;&gt;Soniq - the job queue for people who don’t want another job queue&lt;/h2&gt;

&lt;p&gt;I’ve been rebuilding the same job scheduler since 2011.&lt;/p&gt;

&lt;p&gt;The first version used MongoDB. The core trick was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;find_and_modify&lt;/code&gt; – MongoDB’s atomic operation that lets you fetch a document and update it in a single step. Claim a job before anyone else does, or don’t claim it at all. No double processing. I ran a &lt;a href=&quot;https://github.com/abhinavs/scheduler_service&quot;&gt;hosted multi-tenant version&lt;/a&gt; for two or three years. People used it. It mostly worked.&lt;/p&gt;

&lt;p&gt;Then I moved on. But the problem stayed with me.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Over the years I’ve used most of the serious job queue libraries. Resque and Sidekiq in Ruby. RQ in Python. Each one solved the core problem well enough. Each one also required something extra: Redis, a specific runtime, or an entirely different programming model. The closest thing to what I wanted was Oban in Elixir – PostgreSQL-backed, no broker, no Redis. But I was building in Python.&lt;/p&gt;

&lt;p&gt;I kept thinking about the infra cost. Not the money, but the maintenance. Every component you add to a production system is something that can fail, something you have to monitor, something you have to explain to whoever reads your deploy config next. Redis is not expensive to run. But Redis is one more thing to run.&lt;/p&gt;

&lt;p&gt;I believe in &lt;a href=&quot;https://mcfunley.com/choose-boring-technology&quot;&gt;boring infrastructure&lt;/a&gt;. The best infra component is usually the one you don’t add. Most Python applications already run PostgreSQL. Your jobs can too. It’s already there. It’s already backed up. You already understand it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Last year I built Fastjob. PostgreSQL as the datastore, transactional enqueue, dashboard, webhooks, scheduler. Feature-rich. I’m also willing to admit it became complicated. I added things before the core was solid, and eventually the project became what I was trying to avoid: one more thing to manage.&lt;/p&gt;

&lt;p&gt;In January this year I started again, on weekends. I call it Soniq.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Soniq is a batteries-included async job queue for Python. The only infrastructure dependency is PostgreSQL.&lt;/p&gt;

&lt;p&gt;No Redis cluster. No separate broker. No operational split brain between your app state and your queue state.&lt;/p&gt;

&lt;p&gt;If your application already depends on PostgreSQL, your queue can too.&lt;/p&gt;

&lt;p&gt;What that gives you that most queues don’t:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Transactional enqueue. A job is either committed or it isn’t. A user signs up, the database transaction commits, the welcome email job commits in the same transaction - there is no gap where one succeeds and the other disappears.&lt;/li&gt;
  &lt;li&gt;Built-in scheduler and recurring jobs&lt;/li&gt;
  &lt;li&gt;Built-in dashboard, no paid tier&lt;/li&gt;
  &lt;li&gt;Prometheus metrics out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most applications don’t need a dedicated distributed queue cluster just to send emails and process background tasks. Soniq is built for that majority - teams that need reliability and operational simplicity more than extreme throughput.&lt;/p&gt;

&lt;p&gt;If you’re already running PostgreSQL and don’t want another broker, &lt;a href=&quot;https://github.com/abhinavs/soniq&quot;&gt;Soniq is ready&lt;/a&gt; - MIT licensed, batteries included.&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="Python" /><category term="PostgreSQL" /><category term="Infrastructure" /><category term="Soniq" /><category term="Open Source" /><category term="Engineering" /><summary type="html">I&apos;ve been rebuilding the same job scheduler since 2011. Soniq is the version that finally knows what to leave out.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Terminal is having a second life</title><link href="https://www.abhinav.co/terminal-is-having-a-second-life" rel="alternate" type="text/html" title="Terminal is having a second life" /><published>2026-04-22T00:00:00+00:00</published><updated>2026-04-22T00:00:00+00:00</updated><id>https://www.abhinav.co/terminal-is-having-a-second-life</id><content type="html" xml:base="https://www.abhinav.co/terminal-is-having-a-second-life">&lt;p&gt;In 2001 I started with telnet.&lt;/p&gt;

&lt;p&gt;I was a student at &lt;a href=&quot;https://www.bits-pilani.ac.in/&quot;&gt;BITS Pilani&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Telnet&quot;&gt;telnet&lt;/a&gt; was simply how you got to the internet. I used &lt;a href=&quot;https://en.wikipedia.org/wiki/Pine_(email_client)&quot;&gt;Pine&lt;/a&gt; to send email. &lt;a href=&quot;https://en.wikipedia.org/wiki/Lynx_(web_browser)&quot;&gt;Lynx&lt;/a&gt; to browse. The world came to me as text on a black screen and I thought nothing of it. It was just how computers worked.&lt;/p&gt;

&lt;p&gt;Then GUIs got faster, browsers got richer, and the terminal slowly became the thing you minimised and forgot about. Developers kept using it. Everyone else moved on.&lt;/p&gt;

&lt;p&gt;I kept using it too. At Yahoo in 2005, the terminal was where the real work happened. I was working on a big data processing pipeline and my QA system was a pipe. Feed the output through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt;, filter it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cut&lt;/code&gt;, join datasets with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;join&lt;/code&gt;, scan compressed logs with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zcat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zgrep&lt;/code&gt;. Each tool did one thing. The intelligence lived in how you chained them. And if something went wrong, the tool that failed said so. The pipeline stopped. You knew exactly where to look.&lt;/p&gt;

&lt;p&gt;It felt powerful then. I didn’t fully understand why.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’ve spent the last two months building &lt;a href=&quot;https://vrk.sh&quot;&gt;vrk&lt;/a&gt; – Unix-style tools for LLM pipelines – and the Yahoo pipeline keeps coming back to me.&lt;/p&gt;

&lt;p&gt;Not as nostalgia. As explanation.&lt;/p&gt;

&lt;p&gt;AI agents need to do things: fetch a URL, check it fits within a model’s token limit, redact secrets, call the model, validate the output. The problem is what happens when something goes wrong. A model doesn’t crash on bad input. It guesses. It fills in what it didn’t see with text that sounds right. You find out three steps later, or you don’t find out at all.&lt;/p&gt;

&lt;p&gt;Agents, like the shell, are probabilistic at the edges but need determinism at the joints. The pipes are the joints.&lt;/p&gt;

&lt;p&gt;That’s the insight I kept arriving at while building vrk. The contract that made &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; useful – stdin in, stdout out, exit loudly on failure – turns out to be exactly the contract an agent pipeline needs.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I started using the terminal because it was all there was. I keep using it because nothing that came after improved on the pipe.&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="Terminal" /><category term="Unix" /><category term="AI" /><category term="Agents" /><category term="vrk" /><category term="Programming" /><category term="Ideas" /><summary type="html">From telnet in 2001 to LLM pipelines in 2025. The pipe is still the best contract we have for keeping agents honest.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">AI doesn’t have a Moore’s Law</title><link href="https://www.abhinav.co/ai-curves" rel="alternate" type="text/html" title="AI doesn’t have a Moore’s Law" /><published>2026-04-21T00:00:00+00:00</published><updated>2026-04-21T00:00:00+00:00</updated><id>https://www.abhinav.co/ai-curves</id><content type="html" xml:base="https://www.abhinav.co/ai-curves">&lt;h2 id=&quot;it-has-something-harder-to-name-and-harder-to-ignore&quot;&gt;It has something harder to name, and harder to ignore.&lt;/h2&gt;

&lt;p&gt;In January 2023, two months after ChatGPT launched, I started building &lt;a href=&quot;https://annexr.com&quot;&gt;annexr&lt;/a&gt;. I thought I was late. Three years later, I realize I was early.&lt;/p&gt;

&lt;p&gt;That mismatch - feeling late while being early - is the signature experience of building in AI right now. It has nothing to do with individual foresight. It has everything to do with how progress in this field compounds.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;one-curve-vs-many&quot;&gt;One curve vs. many&lt;/h2&gt;

&lt;p&gt;Moore’s Law was one curve: transistor density doubling on a predictable clock. Clean, measurable, predictive. And even that wasn’t a natural law. At Intel, it was a goal the company worked hard to keep. When physics pushed back, they adapted.&lt;/p&gt;

&lt;p&gt;AI progress isn’t like that. There is no single company shepherding a single metric. It is a bundle of partially correlated curves: compute, algorithms, inference cost, hardware efficiency, and how long AI systems can work without a human in the loop.&lt;/p&gt;

&lt;p&gt;What makes this unusual is that two different kinds of improvement run at once.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Moore%27s_law&quot;&gt;Moore’s Law&lt;/a&gt; runs on the calendar. Time passes, chips improve.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Experience_curve_effects&quot;&gt;Wright’s Law&lt;/a&gt; runs on cumulative work done. The more you make something, the cheaper it gets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In AI, both are active simultaneously. That coupling is what makes progress feel relentless. The decoupling is what produces the walls.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-curves-briefly&quot;&gt;The curves, briefly&lt;/h2&gt;

&lt;p&gt;Four numbers worth knowing:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Training compute&lt;/strong&gt; has grown roughly 4.5x per year since 2010&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Algorithmic efficiency&lt;/strong&gt; improves separately: the same capability now takes about 3x less compute each year&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Inference cost&lt;/strong&gt; has fallen by orders of magnitude, anywhere from 9x to 900x per year depending on the task&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Agent task horizon&lt;/strong&gt; - how long an AI can work before needing help - has been doubling roughly every four months&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren’t independent. Falling inference cost enables more compute at inference time, which improves reasoning, which pushes the task-horizon curve further, until it hits a wall.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;where-the-curves-break&quot;&gt;Where the curves break&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The logarithmic trap.&lt;/strong&gt; Benchmark performance scales roughly with the log of compute. Each doubling of performance costs far more than a doubling of the training budget. The current bet is test-time compute, shifting spend from training to reasoning during use. Whether the economics hold at scale is still open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The data wall.&lt;/strong&gt; High-quality human text is largely exhausted at frontier training scales. Synthetic data and model self-play have kept the curve alive in narrow domains like math and code. Whether they generalize is the open question.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reliability gap.&lt;/strong&gt; Task horizon measures length, not robustness. An agent that can work for a hundred hours but has a 1% chance of failure each hour is unusable for anything high-stakes. Reliability data lags capability data badly, which is itself a signal about what the industry has optimized for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The power grid.&lt;/strong&gt; Moore’s Law was about density, doing more in the same space. AI scaling is about absolute magnitude. Bigger clusters need more gigawatts. Power grids follow civil engineering timelines, not silicon ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The institutional curve, which is essentially flat.&lt;/strong&gt; Compliance, procurement, security review, change management: none of these scale exponentially. The AI curves are steep. The institutional curve is close to flat.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-this-means-practically&quot;&gt;What this means practically&lt;/h2&gt;

&lt;p&gt;The line of what is worth building keeps moving. Something too expensive or too unreliable last quarter can make sense this quarter. Something that barely works today can be boring infrastructure a year from now.&lt;/p&gt;

&lt;p&gt;But the problems blocking real adoption have shifted. They are no longer mostly about capability. They are about reliability, power capacity, data quality, and how long it takes large organizations to trust new systems.&lt;/p&gt;

&lt;p&gt;Most of the interesting work for the rest of this decade sits in closing the gap between a steep capability curve and a nearly flat institutional one. Not pushing the frontier further. Getting organizations to the threshold.&lt;/p&gt;

&lt;p&gt;That is a harder problem than making the models smarter. It is also a more tractable one.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;If you want the backstory on how these three threads came together, I wrote about that separately: &lt;a href=&quot;/ai-three-lines&quot;&gt;The AI moment was seventy years in the making&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;sources-and-further-reading&quot;&gt;Sources and further reading&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Moore%27s_law&quot;&gt;Moore’s Law&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Experience_curve_effects&quot;&gt;Wright’s Law / Experience curve effects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://epoch.ai/trends&quot;&gt;Epoch AI: Trends in frontier AI training compute and algorithmic efficiency&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://epoch.ai/data-insights/llm-inference-price-trends&quot;&gt;Epoch AI: LLM inference price trends&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://metr.org/blog/2026-1-29-time-horizon-1-1/&quot;&gt;METR: Measuring AI ability to complete long tasks (Jan 2026 update)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://hai.stanford.edu/ai-index/2025-ai-index-report&quot;&gt;Stanford HAI: AI Index Report&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Abhinav Saxena</name></author><category term="AI" /><category term="Scaling Laws" /><category term="Moore&apos;s Law" /><category term="Wright&apos;s Law" /><category term="Ideas" /><summary type="html">A bundle of curves, not one. Why AI progress compounds, and where it breaks.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">The AI moment was seventy years in the making</title><link href="https://www.abhinav.co/ai-three-lines" rel="alternate" type="text/html" title="The AI moment was seventy years in the making" /><published>2026-04-21T00:00:00+00:00</published><updated>2026-04-21T00:00:00+00:00</updated><id>https://www.abhinav.co/ai-three-lines</id><content type="html" xml:base="https://www.abhinav.co/ai-three-lines">&lt;p&gt;&lt;em&gt;Three independent lines of work. Each took decades. None waited for the others.&lt;/em&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In 1947, Bell Labs invented the transistor. A year later, Claude Shannon, working in the same building, published a paper on the mathematics of communication. Neither discovery knew what it was starting.&lt;/p&gt;

&lt;p&gt;What we call “the AI moment” is not one thing. It is the convergence of three threads, each of which matured on its own schedule, developed independently of the others.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-first-thread-a-language-for-information-itself&quot;&gt;The first thread: a language for information itself&lt;/h2&gt;

&lt;p&gt;In 1948, &lt;a href=&quot;https://en.wikipedia.org/wiki/Claude_Shannon&quot;&gt;Claude Shannon&lt;/a&gt; published &lt;a href=&quot;https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication&quot;&gt;&lt;em&gt;A Mathematical Theory of Communication&lt;/em&gt;&lt;/a&gt;. He was trying to solve a practical problem: how do you transmit a signal reliably over a noisy channel?&lt;/p&gt;

&lt;p&gt;What he produced was something much larger. A mathematical language for information itself. Entropy. Compression. Channel capacity. The idea that meaning could be separated from medium, quantified, and reasoned about formally.&lt;/p&gt;

&lt;p&gt;It laid the mathematical foundation that machine learning, deep learning, and modern AI are built on. Every token prediction in a modern language model is a descendant of that paper. Shannon did not know he was laying the foundation for AI. He was solving a telephone problem.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-second-thread-hardware-that-could-actually-run-the-math&quot;&gt;The second thread: hardware that could actually run the math&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Transistor&quot;&gt;transistor&lt;/a&gt; was invented in 1947. Seven decades of shrinking, specializing, and parallelizing followed.&lt;/p&gt;

&lt;p&gt;The moment hardware met modern AI visibly was 2012. A team at the University of Toronto trained a neural network called &lt;a href=&quot;https://en.wikipedia.org/wiki/AlexNet&quot;&gt;AlexNet&lt;/a&gt; on GPUs and won &lt;a href=&quot;https://en.wikipedia.org/wiki/ImageNet&quot;&gt;ImageNet&lt;/a&gt; by a margin that made everyone in the field stop and recalculate. GPUs were designed for graphics. They turned out to be the right shape for deep learning: massively parallel, fast at matrix operations, cheap enough to experiment with.&lt;/p&gt;

&lt;p&gt;Google followed with custom silicon. TPUs arrived in 2016, designed specifically for neural network workloads. The physical substrate that made scale possible was now being purpose-built for it.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-third-thread-an-architecture-that-changed-everything&quot;&gt;The third thread: an architecture that changed everything&lt;/h2&gt;

&lt;p&gt;In June 2017, a team at Google published &lt;a href=&quot;https://arxiv.org/abs/1706.03762&quot;&gt;&lt;em&gt;Attention Is All You Need&lt;/em&gt;&lt;/a&gt;. The paper proposed the &lt;a href=&quot;https://en.wikipedia.org/wiki/Transformer_(deep_learning_architecture)&quot;&gt;Transformer&lt;/a&gt;: a new architecture that dropped recurrence entirely and used attention mechanisms to process sequences in parallel.&lt;/p&gt;

&lt;p&gt;Google understood it well enough to ship BERT in 2018 and T5 in 2019. What it did not do was productize at the pace the architecture deserved. The constraint was probably search revenue. If your core business is people finding answers on web pages, a model that answers questions directly is a threat you have to manage carefully.&lt;/p&gt;

&lt;p&gt;OpenAI had no such constraint. GPT-2 in 2019. GPT-3 in 2020. The technical trajectory was visible to anyone watching. The three threads had already crossed.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-actually-happened-in-2022&quot;&gt;What actually happened in 2022&lt;/h2&gt;

&lt;p&gt;By the time ChatGPT launched in November 2022, nothing fundamental had changed in the underlying technology. The models were better, but the architecture, the hardware, the training approach: all of it had been in place for years.&lt;/p&gt;

&lt;p&gt;What changed was the interface. A chat box that anyone could use. No API key. No prompting knowledge required. The intersection of seventy years of work was suddenly in front of everyone with an internet connection.&lt;/p&gt;

&lt;p&gt;The rupture of 2022 was not a moment of invention. It was a moment of attention.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;The three threads took different amounts of time. Shannon’s 1948 paper needed sixty years of hardware before it could run at scale. The Transformer needed less than five years to go from research paper to the technology inside a product used by a hundred million people.&lt;/p&gt;

&lt;p&gt;The gap between discovery and deployment has been shrinking the whole time. That, more than any single breakthrough, is what makes the current moment feel different from the ones before it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;em&gt;The follow-on question, where those curves are headed and where they break, is what I wrote about in &lt;a href=&quot;/ai-curves&quot;&gt;AI doesn’t have a Moore’s Law&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="AI" /><category term="History" /><category term="Transformers" /><category term="DeepLearning" /><category term="InformationTheory" /><category term="Ideas" /><summary type="html">Three independent lines of work. Each took decades. None waited for the others.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">On learning new things without old baggage</title><link href="https://www.abhinav.co/learning-new-things-without-baggage" rel="alternate" type="text/html" title="On learning new things without old baggage" /><published>2026-02-27T00:00:00+00:00</published><updated>2026-02-27T00:00:00+00:00</updated><id>https://www.abhinav.co/learning-new-things-without-baggage</id><content type="html" xml:base="https://www.abhinav.co/learning-new-things-without-baggage">&lt;p&gt;Whenever I’m in Bangalore, I still default to Hindi.&lt;/p&gt;

&lt;p&gt;I lived there for ~6 years, but I never really learned Kannada. The moment someone spoke to me, my brain looked for a Hindi equivalent and came up short.&lt;/p&gt;

&lt;p&gt;Kids don’t do this. A child learning a new language maps words to real things - the sound and the reality arrive together.&lt;/p&gt;

&lt;p&gt;Adults, on the other hand, map words to other words. Duolingo does this too - every lesson maps the new language onto the one you already know. No wonder so few learners ever hold a real conversation.&lt;/p&gt;

&lt;p&gt;The same pattern shows up when engineers learn new programming paradigms.&lt;/p&gt;

&lt;p&gt;I learned C first. Then tried jumping to Java. Object-oriented programming felt alien - I kept asking “what’s the C equivalent of this?” and half the time, there wasn’t one. I gave up, took a detour through Perl, and arrived at objects gradually. The direct path didn’t work because I was carrying the old map into new territory.&lt;/p&gt;

&lt;p&gt;This is exactly what’s happening with AI right now.&lt;/p&gt;

&lt;p&gt;Most people learn AI tools by mapping them onto familiar things. ChatGPT is like Google, but better. Copilot is like autocomplete, but smarter. An agent is like a junior employee you can delegate to.&lt;/p&gt;

&lt;p&gt;These analogies help you start. They also limit how far you go.&lt;/p&gt;

&lt;p&gt;I’ll be honest - I catch myself doing this too. Twenty years in tech means twenty years of mental models that I keep reaching for, even when they don’t quite fit.&lt;/p&gt;

&lt;p&gt;The people I’ve seen get the most out of AI are often the ones without that baggage. AI-native - they didn’t learn to Google before ChatGPT, didn’t debug by posting on Stack Overflow before Claude Code. They’re not translating. They’re just using it for what it is.&lt;/p&gt;

&lt;p&gt;That model doesn’t come from reading about AI. It comes from approaching it with fresh eyes, not a map drawn from somewhere else.&lt;/p&gt;

&lt;p&gt;The ceiling isn’t the tool. It’s the map you bring to it. And I’m still drawing a new one.&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="Programming" /><category term="Languages" /><category term="AI" /><category term="Learning" /><category term="Paradigms" /><category term="Ideas" /><summary type="html">New paradigms and old maps - why AI will require fresh eyes</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Microservices are a people decision, not a technical one.</title><link href="https://www.abhinav.co/microservices-a-way-to-organize-teams" rel="alternate" type="text/html" title="Microservices are a people decision, not a technical one." /><published>2026-02-21T00:00:00+00:00</published><updated>2026-02-21T00:00:00+00:00</updated><id>https://www.abhinav.co/microservices-a-way-to-organize-teams</id><content type="html" xml:base="https://www.abhinav.co/microservices-a-way-to-organize-teams">&lt;p&gt;I’ve seen companies running thirty microservices with a twelve-person engineering team.&lt;/p&gt;

&lt;p&gt;Nobody questions it. Microservices have become the default answer to “how should we structure our system?” - adopted for the wrong reasons, creating new problems while the old ones quietly follow along.&lt;/p&gt;

&lt;p&gt;My unpopular opinion - microservices are mostly a way to organise teams, not to scale systems. And most companies that adopt them are doing it backwards.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-actual-value&quot;&gt;The actual value&lt;/h2&gt;

&lt;p&gt;Mel Conway observed in 1967 that organisations design systems that mirror their own communication structure. Three teams building together produce a three-part system - whether that’s the right architecture or not.&lt;/p&gt;

&lt;p&gt;This is the real case for microservices. When the payments team owns the payments service end to end - builds it, deploys it, fixes it at 2am - they stop waiting on five other teams to ship a change. Reduced coordination. Clearer ownership. That’s worth something.&lt;/p&gt;

&lt;p&gt;But it only works when the split is real. One team, one thing, completely.&lt;/p&gt;

&lt;p&gt;Most companies don’t do it this way.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-mistake&quot;&gt;The mistake&lt;/h2&gt;

&lt;p&gt;The most common thing I’ve seen: splitting code without splitting ownership.&lt;/p&gt;

&lt;p&gt;You have a user service, an auth service, an account service. They all touch the same user data. Any change to how a user is represented requires coordinating across three teams. The services are separate. The work isn’t.&lt;/p&gt;

&lt;p&gt;The mess hasn’t gone away. It’s moved into the gaps between services.&lt;/p&gt;

&lt;p&gt;And when something breaks, it breaks across multiple services at once. A bug that takes an hour to find in a monolith takes a day when you’re tracing requests through four systems and reading logs from three different places.&lt;/p&gt;

&lt;p&gt;Every service also needs its own deployment pipeline, its own monitoring, its own on-call rotation. At Netflix this overhead is justified. At a 20-person startup it’s a tax on every engineer, every day. I’ve watched teams ship at half their previous speed after going microservices - not because the technology was wrong, but because the team wasn’t big enough to carry the weight.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-this-matters-more-now&quot;&gt;Why this matters more now&lt;/h2&gt;

&lt;p&gt;AI coding agents change the calculation further.&lt;/p&gt;

&lt;p&gt;An agent can hold an entire codebase in context and make changes across multiple modules without getting lost. What’s harder is reasoning across service boundaries - different repositories, different API contracts, different deployment pipelines. Every boundary you add is friction for the agent.&lt;/p&gt;

&lt;p&gt;A modular monolith, where code is well-structured but lives in one place, is significantly easier for an agent to work with. I think this is where most teams will land as AI-assisted development matures - not because microservices are wrong, but because the tool that’s transforming how we build software works best with fewer walls.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;when-to-actually-use-them&quot;&gt;When to actually use them&lt;/h2&gt;

&lt;p&gt;Microservices make sense when teams are genuinely separate - different product lines, different shipping cadences, minimal coordination needed. They make sense when one part of your system has dramatically different scaling needs from the rest. At real scale, the operational overhead is worth it.&lt;/p&gt;

&lt;p&gt;The mistake is using them as the starting point. Start with a well-structured monolith. Split when you have a specific reason to split, not because microservices sound like the professional choice.&lt;/p&gt;

&lt;p&gt;The architecture should follow the team structure. Most of the time, the team is smaller than the architecture suggests.&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="Microservices" /><category term="Software Engineering" /><category term="Architecture" /><category term="Teams" /><category term="Technology" /><summary type="html">Microservices don&apos;t make systems easier. They just move the mess around.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">addy - like apt install, but for people</title><link href="https://www.abhinav.co/addy" rel="alternate" type="text/html" title="addy - like apt install, but for people" /><published>2025-07-21T00:00:00+00:00</published><updated>2025-07-21T00:00:00+00:00</updated><id>https://www.abhinav.co/addy</id><content type="html" xml:base="https://www.abhinav.co/addy">&lt;p&gt;Every company has a version of this problem.&lt;/p&gt;

&lt;p&gt;A new engineer joins. Someone sends a Slack message to whoever manages the servers. That person sets up access when they find the time - creating accounts, copying keys, updating permission files. All done by hand, all from memory. When that engineer leaves, most of this gets undone. Some of it doesn’t - old access quietly lingers on servers nobody thinks to check.&lt;/p&gt;

&lt;p&gt;Some teams give up and share a common &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deploy&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu&lt;/code&gt; user. One SSH key, everyone uses it. Fast to set up, impossible to audit. When something breaks in production - or something gets deleted - you have no idea who was logged in. The logs say &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu&lt;/code&gt;. That’s where the investigation ends.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-drift-nobody-notices&quot;&gt;The drift nobody notices&lt;/h2&gt;

&lt;p&gt;The manual approach creates drift quietly. Keys that should have been removed are still there. A contractor who left six months ago can still log in. Nobody knows exactly who has access to what because it lives scattered across the configuration of individual servers, not in any one place you can actually look at.&lt;/p&gt;

&lt;p&gt;You only find out how bad it is during a breach, an audit, or a compliance review.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;where-the-idea-came-from&quot;&gt;Where the idea came from&lt;/h2&gt;

&lt;p&gt;I worked at Yahoo from 2005 to 2007. One of the internal tools we used was yinst - a package manager built for Yahoo’s massive server fleet. Among other things, it handled adding and removing users across servers. One command, right setup, clean removal.&lt;/p&gt;

&lt;p&gt;I didn’t think much of it at the time. That was just how things worked at Yahoo.&lt;/p&gt;

&lt;p&gt;Years later, building and managing infrastructure at smaller companies, I kept noticing the absence of it. The manual approach isn’t wrong exactly - it works fine when the team is small and careful. But it doesn’t scale with the team, and it has no memory. When someone leaves or an audit arrives, you’re reconstructing history from Slack messages and gut feel.&lt;/p&gt;

&lt;p&gt;addy is my attempt to bring that same idea - one command, predictable outcome, Git as the record - to teams that don’t have a hundred infra engineers to build it from scratch.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-addy-does&quot;&gt;What addy does&lt;/h2&gt;

&lt;p&gt;addy treats server access like a package. Your team’s SSH public keys live in a Git repository. addy reads from that repository and applies changes to your server.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sudo addy install user/alice   # creates Linux user, installs SSH key
sudo addy install sudo/alice   # grants passwordless sudo
sudo addy remove sudo/alice    # revokes sudo
sudo addy remove user/alice    # removes access entirely
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;No database. No service to run. No web interface to maintain. Just a Git repo and simple commands.&lt;/p&gt;

&lt;p&gt;When someone joins, you add their public key to the repo and run one command. When they leave, you remove the key and run one command. Their access is gone - cleanly, completely, verifiably. No shared users. No drift.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;why-git-is-the-right-place-for-this&quot;&gt;Why Git is the right place for this&lt;/h2&gt;

&lt;p&gt;Git gives you two things that matter here.&lt;/p&gt;

&lt;p&gt;The first is workflow. Instead of sharing public keys over Slack and hoping someone copies them correctly, engineers open a pull request to add their key to the repository. The team can review it, the change is visible, and there’s a clear record of when it was merged.&lt;/p&gt;

&lt;p&gt;The second is audit trail. Every key addition and removal is a commit. When a compliance team asks “show me every access change in the last six months,” you have an answer - not a pile of Slack threads to go through.&lt;/p&gt;

&lt;p&gt;The actual granting of access - creating the user on the server, installing the key, updating permissions - still happens through addy commands. That part isn’t automatic. But because the keys live in Git, the record of who should have access is always in one place, versioned, and reviewable.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;the-setup&quot;&gt;The setup&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pip install addy

sudo addy config set git-repo git@github.com:your-org/ssh-keys.git
sudo addy install user/alice
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Your key repository needs one thing: a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users/&lt;/code&gt; directory with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pub&lt;/code&gt; files named after each person.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;users/
  alice.pub
  bob.pub
  charlie.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;addy handles creating the Linux user, installing the key to the right location, setting correct file permissions, and validating the key format before doing any of it. For sudo access, it writes a sudoers file and validates it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;visudo&lt;/code&gt; - so a malformed entry doesn’t accidentally lock you out.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;who-this-is-for&quot;&gt;Who this is for&lt;/h2&gt;

&lt;p&gt;Teams of 5 to 50 people. Big enough to have real access management overhead. Small enough that nobody has built internal tooling for it yet.&lt;/p&gt;

&lt;p&gt;If you’re managing server access through Slack messages and shared users, addy is worth an hour of your time.&lt;/p&gt;

&lt;p&gt;The alternative is finding out - during an audit or after an incident - that you don’t actually know who has access to what, and no log to help you figure it out.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/abhinavs/addy&quot;&gt;github.com/abhinavs/addy&lt;/a&gt;&lt;/p&gt;</content><author><name>Abhinav Saxena</name></author><category term="DevOps" /><category term="Git" /><category term="SSH" /><category term="Access Control" /><category term="Automation" /><category term="Technology" /><summary type="html">Introducing addy - a git-driven SSH access control</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Notes on CBDC</title><link href="https://www.abhinav.co/notes-on-cbdc" rel="alternate" type="text/html" title="Notes on CBDC" /><published>2022-10-09T00:00:00+00:00</published><updated>2022-10-09T00:00:00+00:00</updated><id>https://www.abhinav.co/notes-on-cbdc</id><content type="html" xml:base="https://www.abhinav.co/notes-on-cbdc">&lt;p&gt;RBI has recently published a concept note on Central Bank’s Digital Currency (CBDC) - it is available to read &lt;a href=&quot;https://rbidocs.rbi.org.in/rdocs/PublicationReport/Pdfs/CONCEPTNOTEACB531172E0B4DFC9A6E506C2C24FFB6.PDF&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I glanced through it and found it pretty interesting. At a personal level, I’m quite hopeful that a well-implemented CBDC can marry the benefits of cash with current pseudo-digital money.&lt;/p&gt;

&lt;h3 id=&quot;why-cbdc&quot;&gt;Why CBDC&lt;/h3&gt;
&lt;p&gt;At the moment ~3% of GDP is spent on printing, distributing, and securely storing cash. Moreover, India has around 15-30% of its GDP as a shadow economy (not all of the shadow economy is illegal, but much of it is)&lt;/p&gt;

&lt;p&gt;Digital money in its current form (credit card, UPI) has too many entities in the middle to solve for trust. As a result, these entities charge ~2% of the transaction cost from the merchant (which essentially gets passed to customers)&lt;/p&gt;

&lt;p&gt;I also believe, a well-implemented CBDC also has a shot to replace USD as the reserve currency of the world. China has already made some progress in implementing digital Yuan (eCNY) - AFAIK, it is primarily targeting transactions between banks (rightfully so)&lt;/p&gt;

&lt;p&gt;China’s progress is one of the key reasons why India and RBI are also so keen on CBDC&lt;/p&gt;

&lt;h3 id=&quot;cbdc--its-implementation&quot;&gt;CBDC &amp;amp; its implementation&lt;/h3&gt;
&lt;p&gt;Introducing CBDC should not mean that banks lose their relevance, however, it should mean they do high-order things more efficiently. As an example, they should still be the ones doing KYC, however, their recon &amp;amp; settlement process should be way more efficient because of CBDC.&lt;/p&gt;

&lt;p&gt;RBI’s concept note on CBDC distinguishes between retail (CBDC-R) and inter-banking entities (CBDC-W) and their respective implementation details.&lt;/p&gt;

&lt;p&gt;I think,&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;CBDC can be implemented without using blockchain and yet can be distributed with no single point of failure (think about how SSL/HTTPS certificates work)&lt;/li&gt;
  &lt;li&gt;Direct benefit transfer (DBT) scheme launched by the govt could be more efficient with smart CBDC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TODO: update with the design I think can work without blockchain&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://rbidocs.rbi.org.in/rdocs//PublicationReport/Pdfs/CDDP03062019634B0EEF3F7144C3B65360B280E420AC.PDF&quot;&gt;Deepening of Digital Payments Report&lt;/a&gt; (January 2019) - it was written by a committee that worked under the chairmanship of Mr Nandan Nilekani.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://youtu.be/xoXA_mVJ504&quot;&gt;Central Bank Digital Currency – Is This the Future of Money&lt;/a&gt; - another interesting speech by Mr. Rabi Sankar, Deputy Governor, RBI. He talks about the difference between currency &amp;amp; money, then presents RBI’s viewpoint. &lt;a href=&quot;https://www.rbi.org.in/Scripts/BS_SpeechesView.aspx?Id=1111&quot;&gt;Transcript&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content><author><name>Abhinav Saxena</name></author><category term="CBDC" /><category term="India" /><category term="RBI" /><category term="FinTech" /><category term="Ideas" /><summary type="html">My unpolished notes on Central Bank Digital Currency and its relevance for India</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.abhinav.co/assets/images/og-default.png" /><media:content medium="image" url="https://www.abhinav.co/assets/images/og-default.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>