Category Archives: Notes

Weekly Notes 2026/16

  • Very dry week. No sign of rain. The temperature is high and there is no forecast of rain either. I am hoping for next week to be bit cooler.
  • I gave a talk at a student club at APU.
  • I am joining Toyota Connected India next week. Pretty excited about writing Rust in safety critical systems.
  • I am getting a better grip on AI tools. I am still conflicted if I should continue to use them or go back to good old ways. Lets wait for a few more weeks.

Reading List

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 is hard

Examples in post are from this paper which was the 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.

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.

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

 

Feb 07, 2026: Weekly Notes 2026/06

  • I am getting frustrated with a car mechanic for not fixing my Tata Nano’s gearbox. It has been with him for four months now. Unless I call him, he doesn’t provide any updates. I ended up pinging the person who recommended him who is a genuinely a very warm and nice guy!
    • Apparently (he told me), all car mechanics do this. They never proactively update you unless you ask.
    • He reassured me that the mechanic is very good at what he does and that the car should be fixed in a few more weeks.
    • I felt bad about involving him.
  • My impression of the mechanic is that he’s a good guy and understands what he’s doing, but he doesn’t keep me in the loop.
  • I’ve started migrating away from Notion to other open-source or self-hosted tools. For example, WordPress (this site) is now my platform for blogging. My notes are in Joplin now. I still need to find a good tool for to-do, web clippings, and task management—perhaps Zoho?!
  • Yesterday, we went to Aditya’s place to meet a common friend. The “Hound of Madurai” was in town and feeling extremely lovey-dovey about meeting old friends. Why not? It took only 90 minutes to drive 20 km.
    • Kaalu was so tired after the whole “meeting friends” affair that she slept the entire night in one position. Usually, she keeps changing her sleeping spots throughout the night!

20 km in just 90 minutes. Driving in Bengaluru!
  • I have interviews scheduled for a senior role early next week at Fortanix. I had a manager screening yesterday which I think went well. I felt alive talking about security and the SaaS services built around it. I liked that they started with manager screening for a senior role. So that we both could easily decide if we want to invest further time in the interview process. I had to say no to the HP Enterprise interview because they start with a technical interview first and I am not feeling motivated to prepare for it without knowing what their plans are!
  • I bought this saw for pruning branches. It’s a good saw—very sharp. The pole is quite long and the overall build is fine, but it could be much better. In particular, the grip on the loosening/tightening joints isn’t great. The saw also didn’t come with a safety cover.
  • I used it to cut most of the lantana trees growing in an empty plot next to my house and trimmed some branches from the mango and Jamun trees that were blocking light. My neighbor also enjoyed trimming branches that were blocking his security camera’s view. All in all, a good purchase.

Enumerate applications listening to a computer port

How to figure which application/process is already using a port?

For example, below apache is failing to start because port 80 is already taken by some other application.

Apr 11 21:08:13 ip-172-26-0-194 systemd[1]: Starting The Apache HTTP Server...
Apr 11 21:08:13 ip-172-26-0-194 apachectl[17997]: (98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
Apr 11 21:08:13 ip-172-26-0-194 apachectl[17997]: (98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80

Here is a script which can help you find this info.

application_port_list.sh
# list out the processes using a port.
# This script does not give the exact answer but potential solutions. It uses
# three tools one after another.
#
# - lsof
# - netstat
# - ss
set -e
PORT="$1"
echo "Looking for application using port $PORT"
if command -v lsof &> /dev/null
then
sudo lsof -i :$PORT
fi
if command -v netstat &> /dev/null
then
netstat -tulpn | grep ":$PORT"
exit;
fi
if command -v ss &> /dev/null
then
sudo ss -tulp | grep ":$PORT"
exit;
fi