Skip to content
Mahesh Kadambala
Back to All Case Studies
Enterprise SaaSProduction

EquipOS

Multi-tenant equipment lifecycle & field operations SaaS platform

JavaSpring BootMulti-TenancyPostgreSQLKafkaElasticsearchRedisAWS

My Responsibility

Senior Backend Engineer

Engagement Timeline

2023 — Present

Project Artifacts

GitHub Repository

Project Overview

Enterprise operations teams running complex equipment fleets frequently struggle with fragmented data: warranties tracked on spreadsheets, maintenance requests lost in email threads, and zero real-time visibility across global asset operations.

EquipOS was architected to replace these disconnected legacy tools with a single, highly auditable source of truth. As a core backend engineer, I designed the multi-tenant data layer, built the high-performance search engine, implemented the event-driven messaging pipelines, and developed a declarative workflow engine that eliminated costly custom code deployments for new enterprise tenants.

The Business Problem

Before modernizing the platform, our enterprise clients faced critical business bottlenecks:

  • Revenue Leakage: Missed warranty claims and untracked service contracts caused thousands of dollars in unrecovered vendor costs each quarter.
  • Data Isolation & Compliance Risks: Enterprise clients required strict physical/logical tenant isolation; any cross-tenant data visibility would trigger immediate compliance failure.
  • Search Latency Collapse: As asset inventories surpassed hundreds of thousands of items, standard relational SQL queries with dynamic filters slowed down to 5–10 seconds, stalling daily call-center operations.
  • Rigid Business Lifecycles: Every new enterprise customer had custom approval hierarchies for equipment claims, requiring bespoke code changes and separate deployments.

System Architecture

The backend was built as a clean, event-driven distributed system on Java 17 and Spring Boot, deployed on AWS with Docker and Kubernetes.

EquipOS Core Platform ArchitectureRole-based portals communicate through an API Gateway to domain microservices, synchronized via Kafka event streams.Decouples high-throughput transactional writes from compute-intensive search and analytics read models.

Key Architectural Invariants:

  1. Schema-per-Tenant Isolation: A custom request filter resolves tenant identity from the HTTP header/subdomain and dynamically binds the schema connection pool via a RoutingDataSource. Data isolation is enforced at the database driver level—not via fragile application-level WHERE clauses.
  2. Transactional Outbox for Event Consistency: Domain state updates (e.g., claim approval, asset transfer) and their corresponding event messages are written in the same local database transaction. A dedicated relay publisher polls the outbox and streams messages to Apache Kafka with zero dual-write race conditions.
  3. Dedicated Read Models via Search DSL: We separated transactional OLTP writes from search queries by feeding domain events into Elasticsearch. Client search requests are compiled through a custom Abstract Syntax Tree (AST) parser that injects tenant constraints by construction.

My Specific Contribution

While collaborating with the broader platform team, my direct engineering responsibilities included:

  • Multi-Tenant Routing Engine: Designed and implemented the complete request-scoped tenant resolution filter, ThreadLocal context propagation across worker thread pools (TaskDecorator), and fail-closed security boundaries.
  • Enterprise Search Engine & AST Compiler: Built the search subsystem from scratch—parsing user query strings into validated AST nodes and compiling them into tenant-scoped Elasticsearch queries with Redis facet caching.
  • Declarative Workflow State Machine: Engineered the deterministic state engine that allows administrators to configure custom multi-step claim approval stages via JSON configuration, eliminating per-tenant code branches.
  • Database Query Tuning & Optimization: Profiled slow database queries with EXPLAIN ANALYZE, restructured composite indexes, and optimized connection pool sizes to eliminate database CPU spikes.

Key Engineering Decisions & Trade-Offs

1. Schema-per-Tenant vs. Row-Level Multi-Tenancy

  • Decision: Chose schema-per-tenant isolation for enterprise tiers.
  • Rationale: Eliminates the catastrophic risk of forgotten SQL predicates leaking private data between competitors.
  • Trade-Off: Higher database migration overhead across schemas, managed cleanly via automated Flyway migration pipelines.

2. Custom AST Search DSL vs. Dynamic ORM Specifications

  • Decision: Hand-crafted a recursive-descent query parser compiling to Elasticsearch instead of using complex JPA Specification criteria.
  • Rationale: JPA specifications generated unpredictable SQL joins and full table scans on large tables. The dedicated search index with pre-calculated facets guaranteed sub-150ms p95 latencies regardless of filter count.

3. Lightweight State Machine vs. Heavy BPMN Framework (Camunda)

  • Decision: Built an internal deterministic state engine instead of adopting a full BPMN suite.
  • Rationale: Reduced operational overhead, lowered container memory footprints by 60%, and made state transitions straightforward to debug and test with unit tests.

Verified Production Outcomes


Building something similar for your product?

I help SaaS founders and engineering leaders design, scale, and modernize complex backend architectures. Let's discuss how to apply these patterns to your system.

Case Study published Nov 1, 2025