I build systems where architecture drives capability. My focus is on AI-assisted, workflow-heavy, multi-tenant environments where data isolation, state management and role boundaries dictate how the software must be built.
- Core Business Systems & Enterprise Platforms
- Agentic AI Systems & RAG Integrations
- Multi-tenant Architecture & RBAC
- CRM Architecture & Workflow Automation
Location
Colombo, Sri Lanka
Focus
Software Engineering · AI
Stack
TypeScript · React · Node.js · Go · Python · Postgres · AWS
Availability
Open to opportunities
"Anyone can ship code now. What's scarce is knowing what's worth building and holding up when it gets hard."
About
Engineering aligned with business reality.

I'm a software engineer based in Colombo. I build systems that run real operational environments: workflow-heavy platforms with strict permissions, complex integrations and the kind of edge cases that only show up in production.
My work spans tenant-isolated architectures, agentic AI systems, deep API integrations and the internal tooling that keeps operations running. I handle the full lifecycle from schema design and backend logic to frontend delivery.
I care about how software functions under constraints: who uses it, what business rules apply, how AI integrates into real workflows and what maintainability actually means for the team inheriting the codebase.
Outside of engineering: football, camping and time with people who don't care about system design. :)
Orientation
- Systems over isolated features.
- Architecture awareness at every layer.
- Designed for operational constraints.
- Secure, multi-tenant and permission-aware.
- AI as a reliable layer, not a demo feature.
- Maintainability over fragile shortcuts.
Location
Colombo, Sri Lanka
Focus
Software Engineering · AI
Platforms
Web · Mobile · AI
Availability
Open to opportunities
Background
Roles and operational background.
2.5+ years industry experience

Augustory, Corp. (Formerly Nerve8)
- Principal Architect of the Elexi Mobility Platform — a polyglot enterprise SaaS spanning 278 backend files, 87 migrations, 6 web portals and a React Native app, with 4-layer PostgreSQL RLS tenant isolation across 41+ tables.
- Architected VentureLk AI Evaluator — scored startup applications against 100+ checkpoints via Google Gemini and an event-driven PostgreSQL trigger engine. Concurrently built the financial model and investor-facing deck that secured approval from a national tech association.
- Built a decoupled ETL and data extraction platform using Vertex AI + Pydantic, reducing manual data entry by ~85% across 3 document domains.
- Architected a Zoho CRM hub connecting SAP ERP, WordPress e-commerce and 3CX Telephony — cutting quotation generation from 48 hours to under 60 seconds.
- Structured an omnichannel support platform across Zoho CRM + Zoho Desk with bi-directional sync, giving 50+ agents a unified view of every contact's lifecycle.
- Delivered an e-commerce web platform with full product management, inventory sync and payment integration from zero to production.

Spectrum Code
Worked across front-end and back-end web development in a remote team, contributing to production features from internship through to a part-time engineering role.

Third Space Global
Delivered online mathematics tutoring, adapting complex analytical concepts for diverse learning levels.

Academic Tutoring
Tutored university students in Software Engineering and Open Source Applications.
Scope
What I build and how I engage.
Fullstack Development
Developing robust, scalable applications with modern frameworks and engineering best practices.
Software Architecture
Designing resilient, high-performance systems tailored to business needs and long-term growth.
Cloud & DevOps
Enabling faster delivery with cloud platforms, CI/CD pipelines, monitoring, and automation.
CRM & Automation
Custom module development, complex scripting and external integrations for enterprise CRM workflows.
Skills
Technologies I work with in production.
Languages
Frontend & Mobile
Backend & APIs
AI & Agentic Systems
Databases & Storage
Cloud & DevOps
Architecture Patterns
Integrations & Platforms
Testing & Observability
Approach
How I think about engineering.
Design for reality
Systems must survive contact with operational reality. I prioritize edge-case handling, data integrity and reliability over surface-level shine.
Map to the workflow
Features that ignore how people actually work accumulate friction. Good architecture maps directly to real business constraints and user habits.
Protect maintainability
Fast delivery built on shortcuts creates compounding debt. I write code that future engineers can quickly understand, debug and safely extend.
Security by design
Multi-tenancy and data isolation are not afterthoughts. Role-based permissions and security boundaries are enforced directly at the database layer.
AI accelerates, fundamentals sustain
Generating code is easy. The real scarcity is the judgment to know what to build, how to structure it and when to hold the line on quality. I use AI to iterate faster but rely on engineering fundamentals to make the architectural trade-offs that tools cannot make.
Field Notes
Real reflections from production.
Why RLS over app-level tenancy
I've learned the hard way that app-layer tenancy is just too easy to forget. Pushing isolation deep into PostgreSQL with RLS makes the database the absolute final guardrail, regardless of what the API does.
What breaks first in multi-tenant systems
It's rarely the database. Multi-tenant systems usually fail right at the seams. A middleware loses context, some shared query becomes noisy or auth state drifts between layers.
Architecture ages faster than code
You can rewrite bad code in an afternoon, but bad architecture takes months to unwind. Knowing exactly when to keep a system dead simple is honestly one of the most underrated engineering skills.
Trust the database for invariants
If a business rule must absolutely never be violated, it belongs somewhere much stronger than application logic.
Idempotency is not optional in unreliable networks
When users inevitably mash the retry button under a poor connection, duplicate submissions are a system design failure, not a frontend problem.
A booking system should fail closed
In production flows where capacity is strictly limited, the safest default is always to reject duplicates before they ever hit the database twice.
Real-time systems need deduplication more than speed
Blazing fast updates are completely useless if the same event gets processed twice and corrupts your entire current state.
Telemetry should be appendable, but state should be current
Raw events belong in history. Operational views, on the other hand, should be the result of carefully controlled merges, not blind overwrites.
Human approval is part of the design
Whenever an external system is allowed to change ownership records, I always build in a pause for human review before anything irreversible commits.
Not every sync should be automatic
Some changes are totally safe to detect on the fly, but wildly unsafe to apply without a real person eyeballing the diff first.
Good automation knows when to stop
A truly reliable automation tool isn't fully autonomous. It deliberately exposes a pause point right before it does something you can't undo.
LLM output is only useful if it is structured
If your AI cannot return strict, evidence-backed, schema-valid output, keep it far away from production data workflows.
Traceability matters more than clever prompting
A genuinely useful AI system doesn't just spit out an answer. It shows its work and points to exactly where that answer came from.
Deterministic validation makes AI usable
The moment you force AI output into a strict schema, it transforms from a parlor trick into something a database can actually trust.
Why RLS over app-level tenancy
I've learned the hard way that app-layer tenancy is just too easy to forget. Pushing isolation deep into PostgreSQL with RLS makes the database the absolute final guardrail, regardless of what the API does.
What breaks first in multi-tenant systems
It's rarely the database. Multi-tenant systems usually fail right at the seams. A middleware loses context, some shared query becomes noisy or auth state drifts between layers.
Architecture ages faster than code
You can rewrite bad code in an afternoon, but bad architecture takes months to unwind. Knowing exactly when to keep a system dead simple is honestly one of the most underrated engineering skills.
Trust the database for invariants
If a business rule must absolutely never be violated, it belongs somewhere much stronger than application logic.
Idempotency is not optional in unreliable networks
When users inevitably mash the retry button under a poor connection, duplicate submissions are a system design failure, not a frontend problem.
A booking system should fail closed
In production flows where capacity is strictly limited, the safest default is always to reject duplicates before they ever hit the database twice.
Real-time systems need deduplication more than speed
Blazing fast updates are completely useless if the same event gets processed twice and corrupts your entire current state.
Telemetry should be appendable, but state should be current
Raw events belong in history. Operational views, on the other hand, should be the result of carefully controlled merges, not blind overwrites.
Human approval is part of the design
Whenever an external system is allowed to change ownership records, I always build in a pause for human review before anything irreversible commits.
Not every sync should be automatic
Some changes are totally safe to detect on the fly, but wildly unsafe to apply without a real person eyeballing the diff first.
Good automation knows when to stop
A truly reliable automation tool isn't fully autonomous. It deliberately exposes a pause point right before it does something you can't undo.
LLM output is only useful if it is structured
If your AI cannot return strict, evidence-backed, schema-valid output, keep it far away from production data workflows.
Traceability matters more than clever prompting
A genuinely useful AI system doesn't just spit out an answer. It shows its work and points to exactly where that answer came from.
Deterministic validation makes AI usable
The moment you force AI output into a strict schema, it transforms from a parlor trick into something a database can actually trust.
The browser is not always a simple input surface
Modern UIs love to hide their real state behind React components. If you're building automation, you have to work with the raw DOM, not just blindly click things.
When WebDriver is not enough, the DOM still is
When standard automation inevitably flakes out, dropping down to direct event dispatch and controlled script execution is the only way to build resilient RPA.
Legacy systems should be modernized without breaking the contract
Shipping a shiny new frontend is completely pointless if it breaks the behavior that all your downstream integrations depend on.
Refactoring should reduce risk, not create new ones
The goal isn't to rewrite everything from scratch. It's to surgically improve the system without disturbing the ugly parts that are actually working fine in production.
Production incidents are architecture feedback
Server crashes, log explosions and sudden resource exhaustion are almost always symptoms of deeper design problems, not just isolated bugs.
Stability is an engineering feature
I'll take a system that survives memory pressure, disk exhaustion and bad dependencies over one that only hums along in ideal conditions any day.
Operational cleanup is part of software work
Sometimes the most critical engineering task you can do isn't shipping a new feature. It's restoring a degraded system so it can keep serving real users.
A good feature respects the real world around it
Whether it's offline users, flaky third-party APIs or live operational dashboards, your design simply has to assume imperfect conditions.
Systems should be built for retries, stale state, and partial failure
Production is never a clean sequence of requests. It's a messy, chaotic stream of duplicates, delays and sudden interruptions.
The hard part is often coordination, not code
Most of the real challenges I face are just about keeping data, the UI, background jobs and external systems perfectly aligned.
Security is strongest when it is layered
One single control is too easy to miss. Stacking multiple, aligned controls makes a catastrophic failure infinitely harder to pull off.
If one layer fails, the next layer should still hold
Good systems are inherently paranoid. They assume mistakes will happen and are built to keep the data safe anyway.
Architecture is really about preserving correctness under stress
Clean architecture diagrams don't matter at all if the system can't behave correctly when requests overlap, jobs retry and integrations lag.
The browser is not always a simple input surface
Modern UIs love to hide their real state behind React components. If you're building automation, you have to work with the raw DOM, not just blindly click things.
When WebDriver is not enough, the DOM still is
When standard automation inevitably flakes out, dropping down to direct event dispatch and controlled script execution is the only way to build resilient RPA.
Legacy systems should be modernized without breaking the contract
Shipping a shiny new frontend is completely pointless if it breaks the behavior that all your downstream integrations depend on.
Refactoring should reduce risk, not create new ones
The goal isn't to rewrite everything from scratch. It's to surgically improve the system without disturbing the ugly parts that are actually working fine in production.
Production incidents are architecture feedback
Server crashes, log explosions and sudden resource exhaustion are almost always symptoms of deeper design problems, not just isolated bugs.
Stability is an engineering feature
I'll take a system that survives memory pressure, disk exhaustion and bad dependencies over one that only hums along in ideal conditions any day.
Operational cleanup is part of software work
Sometimes the most critical engineering task you can do isn't shipping a new feature. It's restoring a degraded system so it can keep serving real users.
A good feature respects the real world around it
Whether it's offline users, flaky third-party APIs or live operational dashboards, your design simply has to assume imperfect conditions.
Systems should be built for retries, stale state, and partial failure
Production is never a clean sequence of requests. It's a messy, chaotic stream of duplicates, delays and sudden interruptions.
The hard part is often coordination, not code
Most of the real challenges I face are just about keeping data, the UI, background jobs and external systems perfectly aligned.
Security is strongest when it is layered
One single control is too easy to miss. Stacking multiple, aligned controls makes a catastrophic failure infinitely harder to pull off.
If one layer fails, the next layer should still hold
Good systems are inherently paranoid. They assume mistakes will happen and are built to keep the data safe anyway.
Architecture is really about preserving correctness under stress
Clean architecture diagrams don't matter at all if the system can't behave correctly when requests overlap, jobs retry and integrations lag.
Writing
Things worth writing down.
Your Auth Middleware Is Too Late. Here's What Should Run Before It.
Most Node.js apps have an auth middleware. You write a protect function, drop it on your routes and call it done. That works fine until you are building a multi-tenant SaaS platform with role-based rate limiting, row-level security, audit trails and a graceful shutdown lifecycle. Then you start realising that auth is not one thing. It is a two-phase pipeline.
We Wrote Our Own Circuit Breaker (And You Probably Should Too)
Building a fast Node.js backend usually means relying heavily on Redis and Postgres. But it doesn't take long to realize that your caching layer is actually a single point of failure. If Redis hangs, socket timeouts pile up, queues exhaust and the entire Node process can get dragged down with it.
How We Got Postgres to Enforce Multi-Tenancy Automatically
The problem with multi-tenancy is that it is easy to do loosely and nearly impossible to do right. Here is how we wired Postgres Row Level Security into our Node.js connection pool using AsyncLocalStorage so that tenant isolation runs automatically on every single query.
Connect
Let's talk.
Whether you need to scale system architecture, build a robust internal platform or discuss engineering operations, I'm open to conversations.