Balaji Arumugam
Back to Projects
MES Systems

MES Production Suite

A unified React platform that became the operational core of Amway India's production facility — I owned the Machine Line and Master modules from scratch, built a three-tier component-level access control system used across the entire app, and drove the lazy loading strategy that cut initial load time by 60%.

🏢 Emphatic Sense Technologies2022
🔒 Source & live demo not available — built under NDA

About the Project

The Chrysalis MES grew into the central operations platform for Amway India's facility, covering production planning, machine calibration, behavioral safety audits, quality inspection, and purchase requisition. I built the Machine Line module and the Master module from scratch — the reference data foundation that every other module depended on. Across the remaining modules I contributed bug fixes and feature maintenance throughout the product's lifecycle.

Two cross-cutting concerns I drove across the full application: access control and performance. The permission system I built enforces access at three levels — route, tab, and individual component — using a server-driven Module → Submodule → Component hierarchy with FULL, RESTRICTED, and DENIED states. Route-level code splitting and lazy loading reduced the initial bundle by 60%, with each module's code loading only on first access.

Core Concepts

🔒

Three-Tier Access Control

A server-driven permission model with three enforcement layers — ProtectedRoute guards pages by module and submodule key, usePermittedTabs filters tab visibility, and usePermittedComponents resolves component-level access — giving each role a purpose-built view without duplicating pages.

🏭

Machine Line Module

Built end-to-end: production planning, real-time shift dashboards, task management, log book, AMC, and centerline compliance — across five machine line variants sharing a single component architecture.

📝

Dynamic Checklist Forms

Calibration checklist forms in the Master module use React Hook Form's useFieldArray to support runtime addition and removal of parameter rows — accommodating variable instrument specifications without bespoke form components.

📦

Nested Table Components

Line and machine master tables in the Master module render parent-child row relationships through a children prop interface — machines nested under lines, sub-items under machines — through a single reusable table component.

Lazy Loading Strategy

Route-level code splitting via React.lazy and Suspense isolates each module into its own chunk. The initial bundle shrank by 60% — each module's code loads only when first accessed, keeping the app shell and sign-in fast regardless of how many modules exist.

Key Challenges & Solutions

Challenge: Access Control Across 9 Modules

A single permissions payload from the auth server had to enforce access at the route, tab, and individual button level — consistently — across every module in the application, for every role.

Solution: Built a three-layer system: ProtectedRoute checks the allowedSubModules list from the auth token to gate pages; usePermittedTabs filters which tabs render for a given user; usePermittedComponents returns an access map (FULL / RESTRICTED / DENIED) for every named component in a submodule. useGetAccessByKey does recursive tree traversal for ad-hoc checks at any depth. All permission data is loaded at login and AES-encrypted in localStorage.

Challenge: Growing Bundle as Modules Multiplied

Each new module added to the application increased bundle size, pushing initial load times to the point where floor operators noticed the delay before they could start work.

Solution: Introduced React.lazy with Suspense at the route level across all module entry points, isolating each module into its own chunk. The initial bundle shrank by 60% and each module's code only loads when first accessed.

Challenge: Runtime MFE Integration

The FormBuilder and Ticket systems were developed by separate teams as independent Vite apps and needed to be surfaced inside the main shell without being bundled with it.

Solution: Configured Vite Module Federation on the shell side — the main app declares FormBuilder and Ticket as runtime remotes, loading their JS bundles from environment-configured URLs at runtime. Shared libraries (React, RSuite, react-redux) are declared as singletons to prevent version conflicts across the MFE boundary.

Tech Stack

Frontend

ReactChakraUIZustandReact Hook FormReact Query

Visualization

ChartJSApex Charts

Tools

ViteVite Module FederationMSWGit

Impact Metrics

↓ 60%

Initial Load Time

3-tier

Component-level RBAC

2

Modules Built End-to-End

My Role

Title

Systems Engineer

Duration

May 2022 – Nov 2025

Key Responsibilities

  • Machine Line module — owned end-to-end: dashboards, tasks, log book, AMC, sub-plans, centerline, reports
  • Master module — built from scratch: PR master data, calibration instruments and checklists, machine line master with nested line/machine tables
  • Three-tier access control system: ProtectedRoute (route), usePermittedTabs (tab), usePermittedComponents (component) — used across all 9 modules
  • Lazy loading strategy: React.lazy at all route entry points, 60% reduction in initial bundle size
  • Vite Module Federation shell configuration — integrated FormBuilder and Ticket as runtime remote MFEs
  • Bug fixes and feature maintenance across PR, BOS/BOQ, Calibration, Yield, Admin Service, Task, and Ticket modules

Up Next

MES Production Analytics

Real-time KPI dashboards and multi-chart data visualizations built on top of Amway India's MES production data.

Next Case Study