GrahAI Systems logo
GrahAI Systems
Back to BlogEngineering Notes

Lessons From Building Four AI Products

GrahAI EngineeringMay 27, 202610 min read

Lessons From Building Four AI Products

We run several AI products out of one studio: GrahAI (astrology and Jyotish reports), OptionsGyani (options analytics), AasanKhata (accounting), and AgencyPitch (AI-written agency proposals). They serve completely different users in India and the World, but underneath they share more infrastructure than they don't. Running them in parallel taught us where reuse pays and where it quietly bites.

One Razorpay account, many brands — the webhook bleed

Here is the lesson that cost us the most embarrassment. All of our products take payments through a single Razorpay account, because separate accounts mean separate KYC, settlements, and reconciliation we did not want to multiply. Razorpay lets you register webhook URLs, and the trap is this: every payment on the account fires every registered webhook.

So a customer buying an astrology report would trigger the accounting product's webhook and the proposal product's webhook too. Early on, that meant a buyer on one brand could receive a confirmation email from a sibling brand. Cross-brand bleed is a trust disaster.

The fix is a brand guard at the very top of every webhook handler. We stamp `notes.product_brand` on every order at creation time, and every webhook rejects anything that is not its own brand before doing any work:

```js export async function POST(req) { const event = verifySignature(req); // always verify first const brand = event.payload.payment.entity.notes?.product_brand; if (brand !== 'grahai') { return new Response('not my brand', { status: 200 }); } // ...handle only grahai payments } ```

Note it returns 200, not an error — you do not want Razorpay retrying a webhook that correctly decided to do nothing. If you ever share one payment account across brands, brand-guard every webhook on day one.

Shared infra: standardize the boring layer, vary the product layer

The thing that made four products tractable for a small team is that we standardized the layer that is identical everywhere and let the product layer diverge freely.

Standardized across all four: auth (Firebase), the payment-order creation and webhook skeleton, the idempotency convention (`rzp_` doc ids), structured event logging, the email-sending wrapper, geo and currency detection (INR vs USD per visitor), and the deployment pipeline on Vercel. These never change between products, so we maintain them once.

Deliberately not shared: the prompts, the domain models, the UI, the pricing, and the LLM grounding data. A kundli chart has nothing in common with a tax form or an options payoff diagram. Trying to abstract those into a 'universal AI engine' would have produced a leaky god-object that fits nothing well.

Reuse vs duplication: copy until it hurts three times

We are not dogmatic about DRY across products. Our rule of thumb: the first time, write it. The second time, copy it. The third time, only then extract a shared module. Premature shared libraries across products create coupling that turns a tweak in one product into a regression in another.

Geo-currency detection is a good example of something that earned its way into a shared module — every product needs to show INR to Indian visitors and USD to the rest of the world, the logic is fiddly (cookie + geo API + a pre-paint cookie read to avoid the 'US sees rupees' flash), and getting it wrong loses sales. That hit the bar. A 'shared report generator' did not, because each product's report is its own beast.

Cost-smart model routing is a product decision

Across products we route between a cheaper model and a stronger one based on the task, not a global default. Classification, extraction, and short structured outputs go to the cheap, fast model. Long-form reasoning — a full astrology narrative, a nuanced proposal — escalates to the stronger model. The router lives in shared infra; the policy of which task goes where lives per product. We never expose model names or routing strategy in customer copy; users buy outcomes, not vendor logos.

Multi-tenant observability

With several products on one logging substrate, every event carries a `product` tag from the start. Without it, a spike in failures is unattributable. With it, the daily digest can say 'AasanKhata had 4 generation failures, everyone else was clean.' Tag your telemetry by product before you have a second product, not after.

What we would tell another studio

Run the shared layer like a platform team runs a platform: small, stable, well-tested, and identical everywhere. Run the product layer like product teams: fast, divergent, and free to break its own rules. The mistake is mixing them — sharing what should diverge (prompts, domain logic) and duplicating what should be shared (payments, auth, idempotency). And if you ever share a payment account, guard every webhook by brand before you ship.

If you are weighing whether to build several AI products on shared infrastructure, GrahAI Systems has done it across four and can help you avoid the bleed — reach us at support@grahai.com.

Project Consultation

Interested in deploying custom AI systems?

We custom-engineer AI agents, databases, and LLM integrations that replace tedious administrative tasks.

Get In Touch