Lessons From Building and Scaling DietGhar and NyayX
Building two products eleven years apart taught me that the engineering decisions which matter least at launch are the ones that matter most at scale — and that almost none of them are about which framework you pick. DietGhar went live in 2014 as a health and wellness platform and now serves over a million users on Node.js microservices with MongoDB and Redis. NyayX launched in 2025 as a legal-tech platform where real law firms keep live client data, which made security an architectural constraint rather than a feature. The two could not be less alike as products, and the lessons that transferred between them were never about technology choices. They were about what you can change later and what you cannot.
Lesson 1: Boring technology wins, and the reason is not what people think
DietGhar runs on Node.js, MongoDB, and Redis. NyayX runs on Node.js, PostgreSQL, and Redis. Neither stack would win an argument on technical merit alone, and that is the point.
The usual defence of boring technology is that it is well documented and widely known. True, but secondary. The real argument is failure familiarity. When something breaks at 2am, what matters is whether you have seen this specific failure before — whether you recognise the shape of the error, know which metric to check first, and can predict what the fix will break next.
Novel technology has no failure familiarity, and you accumulate it at the worst possible time. Every hour spent learning a new database's replication quirks during an incident is an hour not spent fixing the incident.
The corollary is that the boring choice is only boring if it is boring to you. A team that has run Postgres for a decade should not adopt MongoDB because it is the safer, more mainstream option in the abstract. Pick the technology whose failure modes you have already survived.
Lesson 2: Observability has to exist before you need it
The instinct is to add monitoring after the first incident, because before the first incident you do not know what to monitor. That reasoning is backwards. After the incident, you have lost the data that would have explained it.
The minimum that has to be in place at launch is structured logging with a request identifier that follows a request across services, error tracking that alerts on rate rather than occurrence, and uptime checks that test a real user path rather than whether the process is running. A health endpoint returning 200 while checkout is broken is worse than no health endpoint, because it is actively misleading.
The specific thing I would tell my 2014 self is to log the decisions, not just the outcomes. Knowing that a request failed tells you very little. Knowing which branch it took, which cache it missed, and which downstream call it made turns a two-hour investigation into a two-minute one.
Lesson 3: Infrastructure choices are product choices
NyayX is the clearest example. Because law firms store privileged client information, the architecture was constrained before a line of product code existed: AES-256 encryption at rest and in transit, PostgreSQL row-level security for multi-tenant isolation, and an append-only audit trail implemented with database triggers rather than application code.
That last detail is the one worth generalising. The audit trail lives in triggers because application-level audit logging is only as reliable as the developer who remembers to call it. A trigger cannot be forgotten, cannot be bypassed by a direct database write, and cannot be skipped by a migration script run by hand. The guarantee is structural rather than procedural.
Row-level security works the same way. Multi-tenant isolation enforced in application code is one missing WHERE clause away from a data leak, and that clause will eventually go missing, because every query is written by a person. Pushed into the database, isolation holds regardless of what the application does.
Neither decision was reversible. Both had to be made before there was a product to test them against, and both would have been prohibitively expensive to retrofit.
Lesson 4: Automate the things you will do while tired
Automation is usually framed as a time saving, which undersells it. The real value is that automation removes judgement from moments when judgement is unreliable.
DietGhar deploys through GitHub Actions with zero-downtime rolling deploys under PM2. The saving is not the few minutes a manual deploy would take. It is that a deploy at midnight after a long day is identical to a deploy at 10am on a Monday. Manual deploys are fine until the day someone skips a step because they are tired, and that day is the day it matters.
The rule I use for what to automate: anything you will do more than three times, and anything you will do under stress. The second category matters more. A rollback procedure that lives in someone's head is not a rollback procedure.
Lesson 5: Your unfair advantage is rarely the code
Both products taught the same uncomfortable lesson. The engineering was necessary and it was never sufficient.
DietGhar's advantage was not its microservice architecture. It was understanding that rigid meal plans fail because people's schedules are irregular, and building around that observation. NyayX's advantage was not row-level security. It was understanding what a law firm's day actually looks like and how much of it is lost to paperwork.
The reason this matters to an engineer is that it changes what you optimise. Time spent understanding the domain compounds; time spent optimising code that solves the wrong problem does not. The most valuable thing I did on both products was run them — watching real usage, seeing where people gave up, and knowing that the gap was mine to close.
That is also the honest argument for founders staying technical, and for engineers spending time close to the product. The feedback loop between building something and watching it fail in front of a real user is the fastest way to learn what to build next. Everything else is a slower proxy for it.
What transferred between the two, and what did not
Eleven years apart, on different stacks, in unrelated domains — the surprise was how little of the specific knowledge carried over and how much of the structural knowledge did.
Nothing about MongoDB document design helped with PostgreSQL row-level security. Nothing about consumer health-app usage patterns predicted how a law firm uses software. Every domain assumption had to be rebuilt from scratch, and the second time I was faster only because I knew to distrust the assumptions earlier.
What transferred was the shape of the work: which decisions are cheap to defer and which have to be right at the start, how to tell a scaling problem from a modelling problem, what to instrument before launch, and how much of a founder's time gets spent on things that are not engineering at all. That knowledge is portable in a way that stack expertise is not, and it is the reason the second product took less calendar time to reach production despite being architecturally stricter.
What I would do differently
Three things, in order of how much they cost me.
I would define the data model's isolation and audit requirements before writing product code, on both products rather than only the second. NyayX got this right because the domain forced it. DietGhar did not, and the retrofit was more expensive than the original build would have been. Isolation and auditability are the two properties that cannot be added cleanly later, because adding them means rewriting every query that already exists.
I would instrument the funnel before optimising the infrastructure. On DietGhar I spent time making things faster before I could see where people actually gave up. Some of that work mattered and some of it optimised a step most users never reached. Without funnel visibility you cannot tell which is which, so you optimise what is easy to measure instead of what is costing you.
And I would treat the first hundred users as a research programme rather than a milestone. The clearest signal either product produced came from watching a small number of people use it badly — hitting paths I had not anticipated, and giving up at steps I thought were obvious. That signal is available very early and it gets harder to see as volume grows and individual behaviour disappears into aggregate metrics.
Running two products at once
The constraint nobody mentions is that a live product does not pause while you build the next one. DietGhar was serving real users throughout NyayX's build, and its incidents did not schedule themselves around it.
What made that survivable was the automation from Lesson 4 and the observability from Lesson 2, in combination. Automated deploys and rollbacks meant routine changes did not require my attention. Alerting on error rate rather than on individual errors meant I heard about the problems that mattered and not the ones that self-resolved. The two together are what turn a live product from a full-time obligation into a background one.
The decision I would defend most strongly from both builds is spending disproportionate early effort on that operational layer. It does not ship a single user-facing feature, and it is the reason there was capacity to build anything else at all.
Need help applying this to your project?
Book a free consultation →