Brother DCP-T426W wouldn’t print on Linux/Debian: ipp-usb conflicts with vendor driver

TLDR: If you’re using a manufacturer-provided CUPS driver (Brother, Canon, etc.) and your printer silently refuses to print, check whether ipp-usb is running. It’s a well-intentioned daemon for driverless printing, but it directly conflicts with legacy vendor drivers that expect raw USB access. Mask it, point your queue at the right URI, and you’re done.


I again installed the Brother DCP-T426W driver on my Debian Trixie, connected the printer via USB, sent a test page. The job just sat there with “Waiting for printer to become available.” Occasionally, it gets printed but most of time, it just waiting there. To make matter worse, the scanner was working fine and I could scan using a Debian machine! Printing test page would often work but not always!

Running lpstat -p showed two printer queues had been created:

  • Brother_DCP_T426W_USB — using implicitclass:// (driverless IPP)
  • DCPT426W — using usb://dev/usblp0 (Brother’s native driver)

The CUPS error log showed the driverless queue failing with “No IPP attributes“, and the Brother queue stuck because /dev/usblp0 didn’t exist.

dmesg revealed the real culprit: the kernel device usblp3 was being created and destroyed every 5 seconds in a loop. And systemctl status ipp-usb confirmed the ipp-usb daemon was running.

Modern Linux systems ship with ipp-usb, a daemon that intercepts USB printers supporting the IPP over-USB protocol and exposes them as network printers. The DCP-T426W supports this protocol, so ipp-usb grabbed the device the moment it was plugged in.

This created a conflict: the Brother CUPS driver expected to talk directly to /dev/usblp0, but ipp-usb was sitting in between, cycling the connection every 5 seconds. Neither driver could win. On top of that, the queue URI was pointing to /dev/usblp0 — which never existed. The actual device node was /dev/usb/lp3.

Thanks AI for explaining this to me.

The Fix Three steps:

  1. Stop and mask ipp-usb so it no longer intercepts the printer on this or future boots: sudo systemctl stop ipp-usb and sudo systemctl mask ipp-usb
  2. Find the correct USB URI using lpinfo: sudo lpinfo -v direct usb://Brother/DCP-T426W?serial=XXXXXXXX
  3. Update the printer queue to use the correct URI:
    sudo lpadmin -p DCPT426W -v "usb://Brother/DCP-T426W?serial=XXXXXXXX"
    sudo lpadmin -d DCPT426W

After that, the test page printed immediately.

Weekly Notes 2026/15

  • First two weeks of April are usually the hottest weeks in Bangalore. Its less dry than the 2025 but only one light shower. The mangoes outside my house are growing nicely though.
  • Its been three weeks since I’ve written code by hand (except for a few tweaks). I am using Claude and sometimes qwen cli. Claude is definitely much better but qwen is quite capable at well scoped tasks.
  • I don’t think AI is replacing programmers anytime soon but sure making me dumber. It is becoming harder to focus, read docs and engage with a linear conversation. Also when I ran out of the credits, I had to push myself to open my editor and look at the code and I found it alarming.
    • My TLDR summary of AI is the following. It generates pig-iron and call it steel. You can build a fun Choo-Choo train with it over the weekend but please don’t build a proper train with it that carries hundreds of people. But can you resist?

Reading list

Notes on the C++ memory model: why lock-free DSA are very hard to get right

These examples are from this paper which is inspiration behind this excellent Rust tool loom. This talk Beyond Sequential Consistency is an excellent introduction to this topic.

Following text is written with help of a LLM.

Example 1: The Result That Shouldn’t Be Possible (But Is)

Consider this program. Two threads, two shared variables.

atomic<int> x(0), y(0);
void threadA() {
int r1 = y.load(memory_order_relaxed);
x.store(1, memory_order_relaxed);
}
void threadB() {
int r2 = x.load(memory_order_relaxed);
y.store(1, memory_order_relaxed);
}

Quick question: what are the possible outcomes for (r1, r2)?

Most would say: (0,0), (0,1), or (1,0). ThreadA might run before ThreadB, after it, or interleaved — that covers every case. It doesn’t.

The C++11 standard also allows r1 = 1, r2 = 1! Which seems impossible since for this to happen, both threads must be reading the value that the other thread hasn’t stored yet! This cannot happen under any sequential interleaving of the two threads. There is no ordering of the four statements that produces this result if you run them in sequence. But the C++ memory model isn’t sequential.

memory_order_relaxed is the weakest ordering available, and it explicitly permits memory operations to different locations to be reordered. A compiler is allowed — in fact, encouraged — to reorder the load and store within each thread to optimize performance. On ARM and PowerPC CPUs, this reordering can happen in hardware even without compiler involvement.

So when you write memory_order_relaxed, you’re not just saying “I don’t need a lock.” You’re saying “I’m fine with any possible reordering of my memory operations.”

Example 2: Acquire/Release Doesn’t Mean What You Think

The standard fix is to use memory_order_acquire and memory_order_release to create synchronization pairs. Let’s modify the previous example:

atomic<int> x(0), y(0);
void threadA() {
int r1 = y.load(memory_order_acquire); // changed
x.store(1, memory_order_relaxed);
}
void threadB() {
int r2 = x.load(memory_order_relaxed);
y.store(1, memory_order_release); // changed
}

Now, if r1 = 1 — meaning threadA‘s acquire-load read the value stored by threadB‘s release-store — then a synchronization relationship is established. The standard guarantees that everything threadB did before the release is visible to threadA after the acquire.

This means: when r1 = 1, threadB must have already executed x.load()(which is 0) before doing y.store(1, release). ThreadA‘s load/acquire on y “saw” that store/release, so threadA must observe the effects of everything before it. Therefore r2 = 0. The possible outcomes are now only: (0,0), (0,1), and (1,0). The (1,1) result is gone.

By the way, the load/acquire does not “force” store/release to “happen” before it i.e. threadA load/acquire doesn’t force threadB‘s store/release is complete first. It only says, if I read value from other thread’s store/release then it is safe to assume that I can see everything that happened up to that point in other thread.

Why this is still dangerous

The logic above looks simple but it’s not. It requires you to:

  1. Identify every pair of atomic operations that need to synchronize.
  2. Correctly apply acquire/release to every single one of them.
  3. Reason through the transitive closure of happens-before across the entire execution.

Miss a single pair, or apply the wrong memory order to one operation, and you’re back in the land of (1,1). There’s no compiler warning. The code compiles cleanly. Your tests will almost certainly pass, because the (1,1) outcome might require a specific micro-architectural timing to trigger.

Example 3: The Modification Order Is a Hidden Variable

Here’s a subtler problem. Consider a single atomic variable with two stores and two loads:

atomic<int> x(0);
void threadA() {
x.store(1, memory_order_relaxed); // A
x.store(2, memory_order_relaxed); // B
}
void threadB() {
int r1 = x.load(memory_order_relaxed); // C
int r2 = x.load(memory_order_relaxed); // D
}

The C++11 standard defines a modification order for every atomic object — a total order of all stores to that object that every thread must agree on. This isn’t a lock, and it isn’t sequential consistency — it’s a weaker guarantee that the relative order of stores to a single variable is consistent.

This constraint is invisible in the source code. You can’t annotate it or inspect it at runtime. But it has real consequences. In this example:

  • ThreadA stores 1, then 2, to x. Therefore in the modification order, store A comes before store B.
  • If load C reads the value 2 (from store B), load D cannot read the value 1 (from store A).
  • Why? Because that would require A to appear after B in the modification order — a contradiction.

So an execution where r1 = 2, r2 = 1 is illegal even though both loads are relaxed, even though there’s no acquire/release pair, and even though naive reasoning might suggest any combination is possible.

The problem is that most developers don’t reason about modification order at all. They reason about thread inter-leavings. The memory model is not defined in terms of inter-leavings — it’s defined in terms of relations (reads-from, happens-before, modification order, synchronizes-with). These relations can produce constraints that are deeply non-obvious, and violating them silently yields undefined behavior.

Example 4: The “Satisfaction Cycle” — Values Appearing Out of Thin Air

This one doesn’t just produce surprising results. It breaks the foundations of program reasoning.

// Thread 1
r1 = x.load(memory_order_relaxed);
if (r1 == 42)
y.store(r1, memory_order_relaxed);
// Thread 2
r2 = y.load(memory_order_relaxed);
if (r2 == 42)
x.store(42, memory_order_relaxed);

Question: can r1 = r2 = 42?

Neither x nor y is initialized to 42. Thread 1 stores 42 to y only if it reads 42 from x. Thread 2 stores 42 to x only if it reads 42 from y. The value 42 can only enter the system if it’s already there.

This is a satisfaction cycle — a circular dependency where values manufacture themselves out of nothing. The C++11 standard informally discourages this result but (as of C++11) doesn’t formally prohibit it. The relevant clause (§29.3p9) was discovered to be both over-constraining in some cases and under-constraining in others, and was subsequently removed in C++14 with a note to “just not do this,” without a formal definition of what “this” means.


The paper I linked at the beginning of the paper found many bugs in other papers and real-world implementations. These bugs were not a data race in the classical sense but a violation of the memory model’s modification order constraints: a specific combination of relaxed loads and stores that, under a legal but non-obvious execution, produced an incorrect result. The authors of the original implementation had not found it through testing, because:

  1. The triggering execution requires a specific ordering of memory operations that real hardware only produces under particular timing conditions.
  2. The x86 architecture — where most concurrent C++ is tested — is stronger than the C++ memory model requires, so many illegal executions simply never occur on x86 even when the code is technically wrong.
  3. The bug would surface on ARM or PowerPC, which honor the weaker semantics the standard actually specifies.

This is the core danger of writing to the C++ memory model: you test on x86, which is well-behaved. Your code ships to ARM, which isn’t. The standard permits ARM’s behavior. Your tests don’t catch it.


What You Should Actually Do

1. Default to memory_order_seq_cst

The default when you write std::atomic<T> and don’t specify a memory order is memory_order_seq_cst — the strongest ordering, equivalent to the intuitive sequential model. It’s slower, but it’s correct. Optimize down from there only when you have a concrete performance need and are willing to formally verify the result.

2. Never use memory_order_relaxed without a proof

memory_order_relaxed gives you no synchronization guarantees whatsoever. It is appropriate only for things like counters where you only care about atomicity of individual operations, not their ordering relative to anything else. If you’re using it to communicate between threads, you almost certainly need something stronger.

3. Use a model checker

Tools like CDSChecker (from linked paper, and its successors) can exhaustively explore every legal execution of a unit test under the C/C++ memory model. If your concurrent data structure can be expressed as a small unit test, running it through a model checker is the only way to be confident it’s correct — not just confident it passes your tests.

4. Understand that x86 is “different” — it has stronger memory model

x86 has a stronger memory model than C++ requires. Code that appears correct on x86 may silently break on ARM, PowerPC, or RISC-V. If you write to the C++ standard rather than to x86-specific guarantees, test on architectures that actually exercise the weaker guarantees.

Web utility to digitize old plots

Today, I wrote a small web-utility to digitize old plots. You upload an image or pdf of a plot, and extract data by clicking points on the curve. It is available at https://tools.dilawars.me/tool/plot-extractor. Why do this manually when AI can do it for you? First, because I wanted to write an utility and AI doesn’t always do a better job than a person!

This utility is a web-companion to to a somewhat popular Python utility I wrote a few back to digitize plots in batch mode.

Vibe-coding a GUI to auto-crop dead-zones from a video

I am forcing myself to use Claude to learn vibe coding strengths and limitations. I vibe-cides a moderate complexity app today.

This app does the following. You have a video where most interesting stuff happens in the middle. At the periphery, you don’t have much movement. This app automatically trims these dead or non-interesting zones from the video. For example, if you have a large recording of a arena with no activity in most of the area then you can use this utility to reduce the frame size and store the most interesting bits.

I picked Rust to vibe code https://github.com/dilawar/trim-dead-area for Windows, macos, and Linux. I tested on Linux only. Here is demo video (also available on youtube).

Why Rust? Because real man vibe-code Rust. It also has a very good type system that helps AI. I am sure vibe coded Rust app would be much better than vibe coded Python or C++ app.

It took me almost 10 to 12 hours to complete this version I am blogging about. I didn’t tweak any code by hand even when I knew that Claude is writing very verbose code.

At the start, It was amazing to write a few sentences and have a working GUI in 5 minutes. Perhaps you can do the same with a tool like cookiecutter  but who has time to explore that when you got Claude.

I know the Rust ecosystem very well so I asked it to use certain crates like tracing, anyhow, clap, imgui, and ffmpeg-next.

Then I described pure business logic. I did not write any algorithmic or DSA details. It did pretty well. Whatever it gave me ran ok. I had a demo-able version in an hour.

Today, I spent 8 hours tweaking the app. It became progressively harder to steer Claude. Most of the time, it did something similar to what I wanted but not exactly. I spent an hour replacing the spinner with a progress bar to my taste! But it keeps bringing the spinner back occasionally.

I also learnt internals of ffmpeg while prompting. I asked Claude to give me a tutorial if it used a new ffmpeg API or some new algorithm.

Then I added more features to GUI, added a cli as well, and asked for some refactor. The code it wrote is at least 3x to 5x of what that I’d have written for same features. My UI would have sucked lemon though.

Overall mixed feelings. I manage to finish it well because I’ve experience with algorithms, rust ecosystem, and GUI development. It would have taken me a couple of days of intense work. But I’d have enjoyed those intense session more than these vibe coded session. On the flip side, I’d have not spent that time on this app.

I am still not sure how well Claude would have done in my hands without much experience e.g. when I was fresh out of college. But I am almost sure that I would definitely be a much worse programmer if I had used these tools every day like this.

Weekly Notes 2026/14

  • For last three weeks, I am doing vibe coding for almost everything. It is helping me understand its power and limitation. I feel like everyone is right about AI. This reminds me a saying about India, “Whatever you can rightly say about India, its opposite is equally true.”.
  • Ookie is at her mama place for last two weeks. She will be back this Sunday. She is having very good time in Toranagallu.
  • I vibe coded an app https://github.com/dilawar/trim-dead-area to trim dead areas from a video (auto-crop to most interesting parts). It started off very fast but tweaking is extremely hard with mixed results. Learning about ffmpeg was a joy using Claude. More here https://dilawar.in/2026/vibe-coding-a-gui-to-auto-crop-dead-zones-from-a-video/.

Using Claude in a small C++ library

Long back, I ported LSODA solver to C++ (https://github.com/dilawar/libsoda-cxx) for a neural simulator I was working on during my PhD. This port is almost the same as the reference C code except for STL containers and some other goodies (and some OB1 errors).

Today, I used Claude to improve unit tests and docs and enhance CMake integration.

First, I asked Claude to look in scipy codebase, search for LSODA related tests, and add them to my project. It did a great job and wrote a better commit message than I would have done but that’s not saying much! The tests Claude wrote used assert which is a noop in release build i.e. these assert won’t be there in release build so passing tests in release are meaningless. When I pointed this out, it replaced them with runtime exception that works with both debug and release build. Not cool, Claude but not bad either. Its C++!

Then I ask for a CMake harness so that folks can integrate my library into their CMake based workflow easily. I did OK at first attempt and made a boo-boo which was caught by Coderabbit review bot (free for open source). Claude fixed it later!

All of it took roughly 30 minutes!

If you are very very familiar with existing codebase then I don’t think Claude/AI tools add too much value. With hot cache, I could have done it in one hour. The advantages of 30 minutes of time saving may not be worth losing your touch with something you enjoy i.e. programming and story building in your head. I definitely feel that I am on “opium” when I use it for a long time.

Claude is very very good at things at which I am below average. Which is true for almost all the things I am doing with Claude thee days. So it is not unnatural that these tools enjoy great reputations among users. More objectively, good AI tools are perfect for things that feels like chores e.g. “translate tests from this Python implementation to C++” or “reproduce this bug and when you find it commit it on a branch” or “create a new project with this and that”.

At my last stint at a medium size org that lasted a month, we are asked to use Claude code as much as possible. Sure, I finished a task in half an hour that would have taken a person familiar with the codebase 3 hours but the PR is still pending review after 12 days! So where are the gains? Beware of Amdahl law as well!

As many have pointed out before that AI tools are very eager to achieve success. They will try to achieve it by any means. Once in a while they will stop and ask you but most of time, they will find a plausible solution. Ensure that your prompt has the definition of “success/done” and “properly” articulated. Discuss it with all stakeholders when a ticket is created otherwise you’ll get something that kind of work but it does not.

Weekly Notes 2026/13

Growing mangoes in my neighborhood
  • The mangoes outside my home are growing bigger nicely. It’s finally nice to see fruits grow in the neighborhood.
  • It was a tough month at work. After thinking hard about my team work culture, my interaction with my manager, and his un-willingness to find me a new team (unless I am his relative), and consulting two of my manager friends, I decided to submit resignation.
    • I had a narrow escape at Bellary road while coming back from office. That also significantly contributed to the decision.
    • They are also moving office to a new location and that uncertainty also contributed to the decision.
  • I had another interview just after I submitted my resignation. You should not do both things at the same day, please! It went horribly wrong.
  • One Microsoft interview was in pipeline. I failed the fourth round (I guess). I am not keep on giving more interviews this year.
  • I am planning to do independent consultant work. I have already have two clients and it should be sufficient to get started. Lets see how it evolves.

Reading list

Weekly Notes 2026/12

  • All rounds of Toyota interviews are finally over. The HR discussion lasted 90 minutes. I enjoyed most of it.🤞
    • And they rejected! Apparently I am over qualified. Didn’t they know from the resume? The reason is perhaps something else — a wrong pause between sentences! I was under the impression that things are going very well.
  • Early this week, a light shower. The leaves of the mango tree outside my house are cleaned! It wasn’t strong enough to clean the dust from the road and wash my parked car. Two days later, we had a good enough rain that washed my car. The mangoes on the tree outside my home are big enough to pickle :-). This year March is not as hot as the last one. Already a few showers.
  • Due to LPG shortage, the restaurant near my workplace is serving a few items, mostly dosa, tea, coffee! At least they are open. But only a fraction of people are working. Everyone pays for the war expect for people who started it?
  • At work, use of AI tools are now compulsory. I am learning to use them, begrudgingly!
    • I already have a big win. I was given .NET6 codebase with empty readme file — a language I never wrote. I asked Claude to act as a staff engineer/product manager and walk me though the codebase and quiz me later. The purpose of walk-through: I can contribute to the codebase. It did a much much better job than a co-worker would have done. It saved me so many pings and emails.
  • I learnt more about AI tooling yesterday from a talk by a coworker. This blog post was also pretty helpful explaining how context window size impacts the quality of response.
    • When the context is filled, the quality of response suffers. The context size is typically 20,000 to 1,000,000. An archive paper is roughly 10,000 tokens. So its not very large!
    • Either you drop some of the context (loose information) or do compaction (summarize the context) and loose nuance. While compacting, pinning important information helps. Perhaps claude is already doing all that. For a general purpose chatbot, I see why this could be a hard problem to solve. A single word may have the most nuance.
  • In other news, uv, ruff and ty joins OpenAI. These tools are created by Astral. Many AI companies have been buying tooling (especially cli tooling).

Weekly Notes 2026/11

  • Tim Hoare has died. I re-read his Turing acceptance speech. Following paragraph felt poignant.
    “….At first I hoped that such a technically unsound project would collapse but I soon realized it was doomed to success. Almost anything in software can be implemented, sold, and even used given enough determination. There is nothing a mere scientist can say that will stand against the flood of a hundred million dollars. But there is one quality that cannot be purchased in this way– and that is reliability. The price of reliability is the pursuit of the utmost simplicity. It is a price which the very rich find most hard to pay.”
  • I had less than ideal on-boarding at new job. I was reminded some aspects of “Indian Workspace” I often hear people complaining on Reddit. Most of the things are fine but folks don’t care about notification sound being loud, talking next to you or having long and loud meetings. Moreover, everything lives in people head, not in documents. You must have meetings for doting ‘i’ and crossing ‘t’. Daily standup can last one hour!
  • Bengaluru has flower season. Its a pity that garbage on the road kills the view that could be spectacular. The GKVK campus road is blossoming.
  • Ookie can easily make 3-5 words phrases like “how about this one”. She is now 25 months old.
Ookie is 1 month old on March 17, 2024. These flowers were collected from a neighboring tree.
  • It was a pie day this week and I didn’t do anything. Not a single friend left in Bengaluru who reminded me of or would get excited about it. Last year, we had apple pies at 3:14pm.

Weekly Notes 2026/10

  • US and Israel are killing children again, in a different country this time! Probably doing its standard “decapitate and delegate”.
    • The way English can be used for propaganda is just amazing. This language has so many rich patterns for making horrible things sound normal. This is now seeping into other languages as well especially among IT savvy politicians.
    • NY Times reporting on Gaza where I often user words “young adults under 18” rather than children to refer to deceased children, is not a lone example but serves as an excellent example. You can’t find those screenshot easily using US based search engines.
  • I deleted my ChatGPT account yesterday. You should too.
  • This week, I traveled to work 3 times! It is quite helpful actually despite hating it. I felt getting back in rhythm in sync with the outside world. My energy levels are slightly better.
    • On the first day at work, I planned to take an auto/taxi and read something on the way to office but had tonwait 10-15 minutes for ride to arrive with multiple cancellation. So I started using my scooty.
      • This weekend, I gave scooty for servicing. It’s been 5 years and scooty is only serviced thrice! Only 3000 Km on it so far.
    • Traffic is typical of Bengaluru. But if I leave early around 7:30 am and comes back around 3:45 pm, avoid worst of the traffic. Yet evening traffic is taking its toll — I’ve been inhaling a lot of fumes. I bought some N95 masks this week. Let’s see how it goes from next week.
  • I read some articles by M. Krishnan again (published in Nature’s Spokesman) while traveling to work one day. Lovely stuff!
  • I need to install some wooden slabs on the wall. Got better drills and I was also out of wall-plugs. Ordered!

Reading list

  • More Cows, More Wives . Some interesting excerpts
    • Margaret Mead’s 1928 book Coming of Age in Samoa depicted a society that regarded ‘lovemaking as the pastime par excellence’ and where young women aimed to ‘defer marriage through as many years of casual love-making as possible’. At the same time Bronislaw Malinowski’s 1929 The Sexual Life of Savages in North-Western Melanesia described trial marriage among the Trobriand Islanders, where young lovers would live together for a few years in the bukumatula – the bachelors’ and unmarried girls’ house. If this relationship went well, it would lead to marriage, but it could also easily be dissolved. In other words, it resembled modern dating.
    • In contemporary Western settings, things seem to have changed once again. Many people are monogamous and have children with a single partner, much like our agricultural forbearers. But others divorce and remarry, similar to hunter-gatherers. Young couples often live together before deciding whether to commit, like the trial marriages of the Samoans. True polygamy is usually illegal, yet some rich divorced or widowed men can attract young second wives, who can bear them a new set of children. Ethical non-monogamists are a growing and vocal minority. To an outsider, it may seem like we have no marriage system at all.
  • The Normalization Of Corruption In Organizations is now 23 years old! The corruption in India has only grown worse. Folks have become quite numbs to it. There is hardly any anti-corruption movement. It felt very different during last Congress government which lost to an anti-corruption movement. Though Arvind Kerjiwal appropriated to his own gain (He is an IITian, they do that!), it felt that country is on the right track to call-out and demonize corruption. All seems to have changed now. Its was always typical of fellow Indian to suggest that they can’t survive without corruption since prices of everything is so high. Lately, I’ve been noticing many have started “valorize” corruption as well.

    Abstract
    Organizational corruption imposes a steep cost on society, easily dwarfing that of street crime. We examine how corruption becomes normalized, that is, embedded in the organization such that it is more or less taken for granted and perpetuated. We argue that three mutually reinforcing processes underlie normalization: (1) institutionalization, where an initial corrupt decision or act becomes embedded in structures and processes and thereby routinized; (2) rationalization, where self-serving ideologies develop to justify and perhaps even valorize corruption; and (3) socialization, where naıve newcomers are induced to view corruption as permissible if not desirable. The model helps explain how otherwise morally upright individuals can routinely engage in corruption without experiencing conflict, how corruption can persist despite the turnover of its initial practitioners, how seemingly rational organizations can engage in suicidal corruption and how an emphasis on the individual as evildoer misses the point that systems and individuals are mutually reinforcing.
  • (Almost) Every infrastructure decision I endorse or regret after 4 years running infrastructure at a startup · Jack’s home on the web is a good summary of various tools and solutions you are likely to encounter while developing SaaS solutions these days.
  • Nobody Gets Promoted for Simplicity was hot on HN last week.

Interesting post: REST = FIOH (F**k It, Overlord HTTP)

Interesting post on how REST got misappropriated! Too bad that this blog has stopped publishing. Here are some “least” accurate bits from this post. The post is richer than what I put here as clickbait ;-).

… in the mid-2000s, the people who were sick of SOAP and wanted to do something else needed their own four-letter acronym… Among this crowd, SOAP inspired contempt. Ruby-on-Rails dropped SOAP support in 2007…

If the get-shit-done crowd wasn’t going to use SOAP, they still needed some standard way of doing things. Since everyone was using HTTP, and since everyone would keep using HTTP at least as a transport layer because of all the proxying and caching support, the simplest possible thing to do was just rely on HTTP’s existing semantics. So that’s what they did. They could have called their approach Fuck It, Overload HTTP (FIOH), and that would have been an accurate name, as anyone who has ever tried to decide what HTTP status code to return for a business logic error can attest….

Luckily, there was this dissertation out there, written by a co-author of the HTTP/1.1 specification, that had something vaguely to do with extending HTTP and could offer FIOH a veneer of academic respectability. So REST was appropriated to give cover for what was really just FIOH.

Weekly Notes 2026/09

  • I took a trip to Pondicherry this weekend. It was a rare week when I didn’t open my work email at all! I managed to spend two days without feeling any “withdrawal symptoms.” It’s a bit funny that people are okay with someone spending a couple of days streaming Netflix, but find it concerning when someone works for a few days straight. If you have nothing better to do, you might as well spend time on your work!
  • March 2 is my first day at Veeam. I’m excited to meet my team at their Bengaluru office. The onboarding process has already started. For once, I’m happy to get back to work instead of doing interviews.
  • Many of my open-source projects are now slowly rotting. I find very little motivation to work on them. Most of them are now just a prompt away. But there are still places where AI isn’t welcome because it’s not very effective yet. Many kernel communities are wary of AI slop, and some have outright banned its use. Perhaps I should focus more on developing low-level stuff again!
  • I’ve been migrating slowly to Zoho. Most things work great out of the box. I kind of like Zoho workflows (perhaps it’s just the novelty).
    • I have mixed feelings about Zoho Notebook, though. I’ve started using it heavily now. It’s slow to open on mobile (especially compared to Google Keep). There are other rough edges that will probably go away after a few weeks of usage.
    • Maybe I’ll keep using Notion (free plan) as my personal knowledge-management system. Notion is even slower to open on mobile.
    • I still can’t find a good TODO app like Wunderlist.
  • I’m still looking for a great personal finance system that integrates with HDFC Bank. The current solution I use—Wallet from Budgetbacker—is not bad. I wrote about it earlier in Personal Accounting and Budgeting Apps. The HDFC Bank sync needs a refresh almost every week (maybe an HDFC issue?).
  • I watched a couple of cricket matches. South Africa thrashing India wasn’t very pleasing to watch, but I think a reality check would do the current management some good.
    • Somehow, I don’t like most of the players in the current team. Honestly, I don’t think I like any batsman other than KL Rahul, or any bowlers other than Bumrah, Varun, and Kuldeep.
    • The way Sri Lanka collapsed against New Zealand was equally disappointing.
    • England stole a win from New Zealand. England somehow does pretty well under pressure.
  • I bought a couple of smart plugs for home. One is from Tapo and the other is from BlackT. Tapo requires an app to view data, while BlackT has a built-in LCD display. I kind of like both!
    • The dishwasher uses roughly 1.3 kWh per use, i.e., about ₹8 per cycle. I’ll measure the geyser usage next.

A guy named Gandhi

What if I tell you that I know a guy who accidentally sliced his butt off like a mango? You can’t make this shit up!

He was a much older kid. His name was Rajeev but we called him Gandhi. He was a simpleton, never used a curse word, always smiling, never seen angry, and often wore white khaadi clothes. Hence the nick name. Having first name Rajeev also helped!

The villain in our story is a fodder/chaff cutter or kutti katne ki machine. Here is a picture. Can you imagine youself slice off your butts with it? I can!

Kutti katne ki machine or chaff cutter. You can use it to slice your butt if you try really hard.

So one fine day in March circa 2004, Gandhi took the blunt blades off the machine, got them sharpened at a nearby town Seohara. And then he put the blades back on. So far so good. To check the alignment, you rotate the wheel with blades and hear the swashing sound blades make when they move across the grass feeder opening. He enjoyed listening to metal sound and rotated the machines as vigorously as he could.

Legend has it that as he was picking tools from the ground, he stepped on a stone, lost his balance and fell back, butt extruded onto the rotating blades. The machine shown in the image is pretty high. Imagine a shorter one and imagine someone falling onto the blades butt first when the blades are rotating. The blades sliced his butts and he fell down unconscious.

Fortunately, his bhabhi saw his falling down. She ran towards him and shouted for help. It is said that the brave woman put the slices back on his buttocks .

He was rushed to a nearby hospital in a tractor and trolley. He was put in a charpai, face down of course. It was a 20 minute journey. He was barely conscious. The trolley was filled with well-wishers and family member, not less than 20 people!

He was driven to the closest hospital in Seohara. Hospitals in town typically have one doctor who sits in his room and patiently forms a line to see him. His relatives barged into the doctor’s room and shouted, “emergency hai doctor sahebm hamare admi ne apni gand kaat li hai!”. (Emergency, doctor. Our man has cut his ass!).

The doctor was too curious to know what happened. Instead of asking to bring patient to him, he walked out of his room to see the patient. Some of his patients were also equally fascinated, one of them still had a thermometer in their mouth. He saw him and chuckled. Strangest case of his life, he claimed and then he suddenly became serious.

“it is a police case. You tried to murder him”, he said, “I’ll report this to the Police first”. Gandhi’s father didn’t like the accusations. He found it almost idiotic. “Array doctor, marna hota to gardan katne, haath per katte, gand katte kya?” (Doctor, if we wanted to murder him, we would cut his throat or limbs, not his ass!). I am told he called the doctor chutiya too!

The doctor was convinced and perhaps a bit embarrassed at this own idiocy. Sure, no one would chop off someone butt a little to murder them and bring them to him for treatment. Gandhi was given sedatives and his butt slices were sewn back. For a few months, he was on a liquid diet else you know! He spend a whole month on a charpai listening to his favorite songs on radio.

Every time someone from my village visited this doctor, he would tell this story to all of his patients.  “In there village, there is a boy who chopped off his butts”, he would say. It wasn’t always appreciated but everyone used to get a good laugh.

Gandhi is married with a few kids. He is doing well. He uses his butts normally, just like you and me. He can ride a tractor and a bicycle too.

Personally, I’ve never seen his injury. I heard multiple version of this story with multiple types of masalas applied to it. He is shy. He doesn’t like to talk about it, let alone showing his injuries to anyone. I don’t know how big the slices were. There are rumors about the number of stitches the doctor needed to put.

A Trip to Pondicherry

    This week, we visited Pondicherry on a three days vacation.

    I started when Somya informed her plan to stay there for few weeks and she invited us to stay with her family. She informed dates in advance. I planned to visit this weekend. Later we got to know that Anjali was there as well during the weekend.

    We decided to drive by car. Ookie is now comfortable inside the car. The inflatable bed that I bought when Anu had plaster on her ankle is serving us really well on these trips. Kaalu sometimes gets pretty stressed and anxious inside car, especially during the day time traffic, so we tried calming tablets and they do wonders for her. I should use them during Diwali when the whole country turns into a loud gas-chamber!

    Driving car to Puducherry from Bengaluru wasn’t the most pleasant experience, especially in the late evening. Almost half of the route was two lane highway. Overtaking slow trucks or auto and avoiding overtaking cars and buses from the other side was also tricky. A lot of vehicles have very bright headlights these days, including small autos, which makes is very hard to see anything when these lights flash in your eyes. The roads were in good shape and except of a speed-breaker that I didn’t see, most of the travel was without any bad bump. We lost 30 mins inside Bengaluru traffic and 45 minutes in a sudden jam on highway. It took us more than 8 hours to reach Pondicherry!

    I think I got some “bio-fuel” (ethanol blended) on the way from a BP/Jio petrol pump. That made car pickup worse and it stinks.

    We reached at Somya place around 9pm and slept after having dinner. Next day, we went to a beach. Neither Ookie nor Kaalu enjoyed the beach. It was their first time and both were scared of big waves. Also, late February turns out to be a little too warm to be on the beach during day time. Unlike west coast (e.g. Mangalore, Mumbai), the beaches in Pondicherry are not shallow and waves are bigger, stronger and dangerous.

    Kaalu and Ookie didn’t like wave crashing near them! Kaalu liked the little crabs on the beach but fear of waves took the fun away. Ookie enjoyed playing in the sand though and Kaalu would dig some sand and lay on it.

    I got to meet old friends and more. Ookie enjoyed the night time at Pomegrade beach. Fortunately, city doesn’t allow vehicle on the beach road and it made all the difference. She walked freely on the beach road. We also bought a funny musical instrument from a road-side vendor. She also enjoyed playing with another toddler in the house who taught her how to jump down the bed!!

    (clockwise from top) Dilawar, Kaalu, Anjali, Somya, Anu, and Ookie

    I didn’t find Puducherry to be very exciting. But again, I don’t find cities to be very exciting. Food is good but food is usually good in all cities.

    The botanical garden was OK but has nothing worth really visiting. Great for toddlers though. It didn’t have any especial tree or plant to excite me. The flower garden was lame and poorly maintained — I’ve seen better personal garden. The aquarium was also pretty meh but much better than garden. Ookie enjoyed her time inside the aquarium. Sadly, the choo-choo train is broken and is just a show piece now. Perhaps we need the British back to ensure things work?

    Ookie and Me in a broken choo-choo train at Pondicherry botanical garden. It’s a shame that this train doesn’t work because they have pretty good track inside the park!

    Beaches are not as dirty as in Chennai but they are not clean either. Occasionally you see broken glass in the sad and put your sandals back on. Our civic senses needs to improve a lot! Also, streets are not walk-able in Puducherry as well, except for one street in Pomegrade beach where they don’t allow cars. I found too many bikes parked on the road most of the time. Bengaluru is definitely worse!

    The local food was very cheap and good and the tea was excellent. I am a great fan of tea making in both Tamilnadu and Kerala. Its a shame that Karnataka and rest of the country hasn’t adopt this method.

    While coming back, we left at 12:00pm. Diving was a pretty decent experience in late night. I didn’t feel sleepy since Anjali was awake in the car and we chatted whole way. By early morning, we were barely awake. It took us 5:30 hours to enter south Bangalore where we met with decent traffic at around 5:30am! It took me 45 minutes to reach home after we entered Bengaluru. Kaalu was pretty happy to see Jumbi and other friends.

Feb 21, 2026: Weekly Notes 2026/08

We celebrated Ookie’s second birthday on Feb 17. I found an excellent place for cake, Chiris Patisserie. Pretty costly, Rs. 1700 per kg but totally worth it! For birthday food, I ordered food from Chetty’s Corner from the neighborhood. Decent food. The kids loved the pizza and burgers. As expected, only folks who stay in the neighborhood showed up. Anu sent some gifts for daycare — rainbow pencils and pouches for kids. People shouldn’t send food to the daycare on birthdays especially chocolate or other sugary stuff. I don’t like Ookie eating chocolate at daycare at this age!

  • I had a mild runny nose the whole week! It was very hard to sit at the desk and do any work for a long time.
  • This Friday was my last day at Dognosis. I’ll probably engage with them as consultants occasionally. Before starting my next job, I’ll spend some days at Puducherry this week. I’ll be meeting Somya, her husband and possibly a few more friends. It will be the first time both Kaalu and Ookie will both see the beach and the sea.
  • I am collecting reading materials to prepare for my new job. Mostly about microservices, API design and related DevOps.
  • Someone from datameet group cleaned up data of the Periodic Labour Force Survey (PLFS). It is available at https://india-plf-survey.pages.dev/. The average earnings are still pretty bad <Rs 20,000 per month! Much touted IT/Software doesn’t even break into of professions that employ more than 0.3% of workforce.
Software/IT doesn’t even show up in the top contributor (>=0.3%) to employment in India.

Starting a New Job In March 2026

I’ll be starting a new job this March. At my new job, I’ll be working with distributed data, its security, and its resilience. I do hope that I get to write some Rust! I guess I also need to buy a few more books on distributed systems, microservices, and data engineering. And some pants to go to the office a few days a week.

I’ve made my peace with the fact that I need to specialize now — or rather have a specialized resume. That means saying goodbye to many things I’ve enjoyed indulging in the past, kernel and systems programming, numerical analysis, algorithm development, and more.

Most of my work experience has been in startups and academic labs. I co-founded one startup and spent six good years at it. It didn’t work out but I have no major complaints. I’ll probably try again someday when personal life is a bit less exciting. After that, I worked at another startup for almost a year. Each startup is entirely different and that makes them both exciting and dangerous. Exciting because you may encounter a totally new way of accomplishing something which you’ve never thought about. Dangerous because if something doesn’t work as well as you like, you have no easy escape. Unlike in large organizations where you can try to switch teams, at startups, you navigate the choppy waters or jump ship.

To me, equity and cutting-edge development or engineering work (in no particular order) are two good reasons to work at any startup. Though for every one unit of cutting-edge work you enjoy, there are typically nine to 999 units of drudgery involved. But that is totally fine. Being a professional doesn’t mean you have to like your job all the time to do it well.

So, after seven years in startups, I was looking for a more structured environment to specialize. I am perfectly fine being a small “specialized” cog in a giant machine where I could appreciate the satisfaction of a task well done. And it feels that the grass is greener on the other side? Reddit seems to agree.

Over the years, I’ve done many things: kernel components, patent filings, numerical simulators, web and Android apps, SDKs and libraries, DevOps, and people-ware such as hiring, designing office layouts, finding vendors, and fixing IKEA furniture. I speak Rust, C++, Python, C, PHP, and TeX fluently, and I’m passable in Haskell, Lua, Java, Kotlin, Scheme, and a few HDLs like Bluespec, Verilog, and VHDL. This makes for a good generalist profile, but no “specialized cog” in a giant machine needs most of that.

So, the first and the hardest problem was figuring out what I want to drop from my résumé so that a job application would actually invite interviews. I could see three to four specialised resumes in my current 12 YoE generalist resume with each having 3-6 YoE. I also need to consider the local economy and hiring patterns. Bengaluru isn’t a place where kernel or compiler developer jobs are easy to find compared to backend or app development roles. The former exist mostly in a few large organizations that follow very different hiring models from startups. I had to focus on my most recent experience and eventually settled on security, APIs, and Rust/C++ development work.

I started the process of writing a resume in late November 2025. Not out of ambivalence toward my current job but to prepare for the worst, and to build muscle memory. It took me more than three months of refining. I feel my résumé is in good shape. I’m not the most careful writer, so I need to reread my writing multiple times to ensure it’s readable. This becomes even more important for a résumé, which has to be succinct and speak clearly to a right audience. I worked on it at a slower pace: editing on weekdays, reading on weekends, and repeating the cycle. r/EngineeringResume has great advice on résumé writing. I also fed my résumé to ChatGPT and Gemini and asked for reviews. It was very useful early on—it helped refine things quite a bit and offered generic advice to tweak the résumé for specific job descriptions, which I rarely accepted. I found it very useful many times.

After a couple of months of reading, tweaking, and rereading my résumé, I felt confident enough to start applying more liberally. I shared my résumé with a few friends for referrals. I’m not always comfortable asking for help—I prefer to walk in through the front door.

I also started doing leetcode and enjoyed the challenge for a week. But soon I lost interest. I am never going to use those patterns at work. Earlier, I took courses in cybersecurity and project management and using a Coursera subscription, but only completed ones I genuinely enjoyed—for example, an excellent course in project management and a few others. I’m not sure if anyone ever looked at these certificates. These courses were a better time spent than streaming something on Netflix.

Things started picking up pace in late December. I got a few positive responses, which would fizzled out after I share my expected salary. Still, it gave me enough confidence to apply to larger organizations. In hindsight, I think I applied to Bunny CDN a bit too early with a weaker résumé—I would have loved to interview with them. Surprisingly, several places I thought would be interested never responded at all or responded very late.

In January, I received positive responses from some large or mid-to-large enterprises: Cloudflare, Toyota, Veeam, HPE, and AMD. Cloudflare, Veeam, and Toyota moved quickly. I missed Cloudflare’s second round but didn’t get another chance to reschedule. I’m still embarrassed about that mistake and also disappointed that Cloudflare didn’t respond to the request to reschedule. My interview experiences at Toyota and Veeam were the best. No one showed up for my scheduled interview at HPE (PS: They called again and promise to reschedule again but I didn’t get any email!)! I declined an interview with AMD after accepting the offer from Veeam. I’m still waiting to hear back from Toyota about the final offer. Things can suddenly move very slowly at large enterprises.

After receiving one offer, I stopped applying for similar role but thought of finishing the other ongoing interviews. How I prepared for interviews is another story. The short answer is, you can never over prepare and you must spend enough time preparing. There are some excellent resources on YouTube. I’ve nothing interesting to add here.

I wasn’t planning to resign from my current job even after receiving any offer. I had significant equity, and the founders are genuinely nice people. My issues were with the day-to-day work and the nature of the organization. I never felt like I was in an engineering org, but rather in a “science” org that think in terms of projects. I like to think in terms of “product” and the word “project” sounds almost philosophical to me (full disclaimer: I’ve a PhD in system biology so I know what “project” means.) While engineering is mostly about maintaining and refining a product or a working solution, academia is mostly about “publish and let it rot” (project). And that’s why I don’t get excited about the word “project”! To be fair, academic incentives are mostly “I was here first, don’t pee on this territory” kind and not “lets build a usable product so folks will pay us money” kind! A few minor developments nudged me to resign before having an offer in hand. I thought resigning will help me focus on the interview process. Fortunately, things worked out well for me and I got an offer after a couple of weeks of resigning. I wouldn’t recommend this route to everyone since interviews are social processes and things can go south very easily even when interviews look very promising.

I also interviewed at a few cybersecurity based startups in growing phase for IC roles. I was taken aback by the LeetCode-style questions for senior positions. I had expected discussions around real security problems they were hiring me to solve. Maybe I just hate LeetCode because I don’t do well in live interview settings and it’s easy to criticize what you’re not good at. I also posted on HN (the “Who Wants to Be Hired” thread). Surprisingly, someone from KLA Chennai responded positively. With KLA, I had the most energetic introduction and screening call ever. I felt that they are thinking very highly of me. I was disappointed that I didn’t perform well enough on their technical assessment (HPC, C/C++) to move forward.

There were also some funny—or irritating, depending on your perspective—experiences. At one European startup with an office in Bengaluru, I was interviewed for two different job descriptions in two separate rounds. I was also asked to write code in Google Docs! At another early-stage startup, they asked me for my high-school board and marks (founder worked at Byju’s!). I tried to keep a straight face. I guess it takes all kinds.

Feb 14, 2026: Weekly Notes 2026/07

  • My second round at Fortanix was a failure!
    • It was a medium leetcode question to be solved inside a browser. Yes, a leetcode for senior roles and that too in a browser! I mostly use vim with a buttload of plugins. Maybe I should start asking if leedcode in browser would be used for evaluation and just say no.
  • Review article of a very interesting book. Here is a mindmap from Reddit.
  • An old friend, Somya Mani and her husband John, came to visit Monday morning. Flight from Vienna to Bengaluru took almost half day and both of them super tired. Both slept after having breakfast. I got busy with office meeting and they went to their hotel. We may have dinner sometimes this week.
  • The engineering workflow that I designed for my current employer might get adopted this week. One of the founders is very interested in it and we refined it over the weekend. Tomorrow I need to sell it to the team. Ideally I should practice the presentation. I will if I get some time in the morning before I drop Ookie to the day care.
  • Many of the street lights in my neighborhood don’t have a proper switch. I’d loved a light sensor based but a manual one is also fine since labor is cheap. But the current way is monumentally bad and pretty dangerous. 
  • I opened account on to learn trading! My niece has been sending me screenshots of how much he is making every day. I made 2500 in half an hour from 10k investment and lost 8k next day. This platform requires constant attention which I don’t have. I’ll probably learn a few more things with very little amount of money and move on. Its not for me. It is pretty addictive though.

Using `otelcol` (open-telemetry collector) to collect docker logs and send to a self-hosted signoz

Assuming that your self hosted signoz is at http://signoz.example.com:4317 (gRPC) or at http://signoz.example.com:4138 (json), following is a docker compose setup to scrape logs from docker and send them to a self-hosted signoz. Prefer grpc since it is very efficient when it comes to sending logs.

Using Logspout, a log forwarder

I am going to use gliderlabs/logspout. It collects logs from running containers (using docker.sock) and make them available via a tcp socket for otel-collector to read. One can also use fluentd etc. I found this to be a simpler solution for my needs.

Set up the tcp receiver in your otel-collector-config.yaml to listen for logs. I am going to use port 2255.

otel-collector.yaml
YAML
receivers:
tcplog:
listen_address: "0.0.0.0:2255"
processors:
batch:
send_batch_size: 512
exporters:
debug:
verbosity: detailed
otlp:
endpoint: http://signoz.example.com:4317
tls:
insecure: true
service:
pipelines:
logs:
receivers: [tcplog]
processors: [batch]
exporters: [otlp]
extensions: []

Run the Log Forwarder

In the following docker compose file, a service logspout collects logs from docker containers and make them available on port 2255. We then use the above otel configuration files to read logs from the port 2255 and send it to self-hosted signoz.

compose.yaml
YAML
services:
logspout:
image: docker.io/gliderlabs/logspout
volumes:
- /etc/hostname:/etc/host_hostname:ro
- /var/run/docker.sock:/var/run/docker.sock
networks:
- otel
depends_on:
- otel-collector
command:
tcp://otel-collector:2255
otel-collector:
image: docker.io/otel/opentelemetry-collector-contrib
restart: unless-stopped
volumes:
- ./otel-config.yaml:/etc/otelcol-contrib/config.yaml
networks:
- otel
ports:
- 4317:4317 # OTLP gRPC receiver
- 4318:4318 # OTLP http receiver
- 2255:2255
networks:
otel:
driver: bridge

That’s it. Here is screenshot of collected logs.

Logs inside self-hosted signoz