Case Study · Industrial Operations

Industrial Operations Platform

Industrial Manufacturing Client · Santa Catarina, Brazil

A modular, on-premise MES/WMS platform for an injection-moulding manufacturer. It began as a solution for managing storage and the finishing area and grew into warehouse management, production planning and a machine-monitoring pilot, spanning web and mobile.

Role
Sole engineer, discovery to production
Platforms
Web · iOS · Android
Domain
Manufacturing / warehouse operations

Context

The client manufactures using injection moulding. Materials and moulds move through storage and a finishing area in high volume, and their location was tracked informally — spreadsheets, labels, and the memory of the people who work there. That works until it doesn’t: as volume grew, finding a specific material or mould, knowing what had happened to it, and holding movements accountable all became slower and less reliable.

The engagement started narrow — manage storage and the finishing area — and was deliberately kept that way until the core model proved itself. It then grew, one validated step at a time, into an operational platform.

Problem

I framed the problem in three layers, because each one pulls the design in a different direction:

  • Operational. Where is a given material or mould right now? What happened to it — every move, in order? Who moved it, and from where to where?
  • Structural. The physical layout is not fixed. Rows are added, levels are re-sized, whole areas are re-purposed. The system has to absorb that without a code change or a developer in the loop.
  • Organisational. Several roles touch the same data with different rights, and every change has to leave an auditable trail.

Constraints

  • One engineer, working directly with the stakeholders. Every decision had to be legible to me later and reversible if it turned out wrong. No room for architecture that needs a team to maintain.
  • It runs on a factory floor. Mobile connectivity is intermittent, devices are shared, and the people using it are operators, not analysts. The UI has to be fast, forgiving, and hard to get wrong; the mobile client has to tolerate a bad network.
  • The floor changes faster than software releases. Configuration has to win over code wherever a layout or a process might shift.
  • Auditability is not negotiable. “What happened to this?” must always have a complete, ordered answer.
  • It has to stay cheap to run. A small managed database and static hosting — no heavy infrastructure to justify.

Approach

  • Model the warehouse as a tree the client owns: area → row → grid → level → slot, with structure types so different physical layouts share one model. Operations staff re-shape the tree themselves.
  • Make every state change an event. Current position and full history are both derived from an append-only movement log — there is one source of truth for “what happened”.
  • Keep two read paths: fast lookups for day-to-day operations, and paginated, filterable reporting with export for the office.
  • Give the layout a visual form — 2D for speed, 3D for spatial understanding — both driven by the same structure data, not a separate drawing.
  • Deliver it where the work is: web for administration and reporting, a mobile client for the floor, with synchronisation and explicit handling of conflicting edits.

Architecture

Clients

Web app React · TypeScript — administration, parameterisation, reporting
Mobile app React Native · Expo · Zustand · Zod — shop-floor use, sync

Application

REST API Spring Boot · Java 21 — domain rules, validation
Auth & access JWT (stateless) · profile-based RBAC · login rate limiting
Realtime channel Domain events → pushed to connected clients
Export Reports → PDF · CSV · Excel

Data

PostgreSQL Flyway-managed schema
Movement events Append-only — the record of what happened
Read projections Indexed views for operational lookups & paginated reports
Clients talk to one Spring Boot API over REST; a WebSocket channel pushes domain events back so the floor and the office converge on the same state. Current position and history are derived from an append-only event log in PostgreSQL.

The clients are thin. The domain rules — what a valid structure looks like, what a valid movement is, who may do what — live in one place, in the API’s service layer, and are covered by tests. Everything the floor and the office see is the same data, kept in step by a realtime channel rather than by people refreshing.

Engineering decisions

Decision Why Trade-off accepted Reconsider when
Model the location hierarchy as data, not as a fixed schema per layout Operations can re-parameterise areas, rows, levels and slots themselves — no deployment, no developer. Richer validation and recursive queries; the model is more abstract to reason about. If layouts stabilise for good and the flexibility goes unused, a flatter model would be simpler.
Optimistic locking on stock items (a version on each row), not pessimistic locks Several devices edit concurrently without holding database locks; a conflict surfaces as a 409 the client resolves. Clients must implement version-conflict handling and a retry/merge UX. If write contention concentrates on a few hot rows, a queue or per-aggregate serialisation may beat retries.
Append-only movement history as the source of truth Complete audit trail and time-travel; current position is a projection, never a value that can be silently overwritten. The event table grows; reporting needs indexed projections now and an archival strategy later. At data volumes where projection queries degrade despite indexing.
Server-pushed events over WebSocket for cross-client sync The floor and the office converge on the same state within seconds, without polling. A stateful channel to run and scale; needs reconnection and backfill handling. If near-real-time turns out not to matter operationally, periodic polling is less to operate.
Stateless JWT auth with profile-based RBAC Simple horizontal scaling and a clear per-role permission model. Token revocation is coarse; a permission change takes effect on the next token refresh. If instant, fine-grained revocation becomes a requirement.

Implementation

Work went in small, verifiable slices, each with tests that prove a behaviour rather than chase a coverage number:

  • Domain rules in the service layer, with contract tests around structure validation, movement integrity, concurrency, and authorization boundaries.
  • The optimistic-locking contract is verified by tests that simulate two clients editing the same item, asserting that the second gets a conflict rather than a lost update.
  • Baseline hardening from the start: login rate limiting, a locked-down CORS policy with correct preflight handling, and authorization checks on every write endpoint.
  • Every schema change is a migration. The database shape is versioned and reproducible from zero.
  • The mobile client keeps local state and reconciles on reconnect, so an operator can keep working through a network gap.

Current capabilities

What is running in production today:

  • Configurable location structures with parameterisation (area → row → grid → level → slot)
  • Material and mould location tracking
  • Auditable movement history — every move, with who and when
  • Role-based access and permissions
  • Reports with filtering and export to PDF, CSV and Excel
  • Attention alerts for stock that needs review
  • 2D and 3D visualisation of the physical layout, from the same structure data
  • Web and mobile clients with synchronisation
  • Real-time updates across connected clients

Selected views

Outcome

The operations team can locate materials and moulds, see exactly how stock has moved and who moved it, and re-shape the storage structure themselves as the floor changes — without waiting on a release. The platform is in active use and continues to evolve with the operation.

Machine monitoring and production planning

  • Edge application (Node.js). Reads the machine’s digital inputs and outputs every 300 ms over HTTP and Modbus-TCP, detects cycles, and raises delay alerts at +10% and +15% over the target cycle time.
  • Offline first. Events are buffered in SQLite on the edge and resent automatically when the connection returns.
  • Idempotent ingestion. The backend validates events by sequence, so a resend never counts a cycle twice.
  • Production planning (PCP). Work-order lifecycle, a per-machine drag-and-drop queue, PDF work-order import from the ERP, downtime and scrap tracking, live progress against target cycle time, and completion estimates.

Tests and documentation

The platform was built with an AI-assisted workflow (Claude Code and Codex) and carries 2,400+ automated tests: 80+ on the edge app, 490+ on the backend (JUnit 5 / Mockito) and 1,900+ on the UI (Jest).

The client also has a documentation site: a user manual in plain language, built from the real screens, and a full API reference with the OpenAPI specification. Scope changes go through versioned proposals with acceptance criteria and change control.

Roadmap

  • Scaling machine monitoring from the pilot machine to the full fleet
  • Moving machine communication from HTTP to MQTT
  • Multi-machine production planning
  • OEE / MTBF / MTTR indicators

The current architecture — events as the source of truth, a realtime channel already in place, a configurable structure model — was chosen partly so this direction stays open without a rewrite. That is a design intent, not a promise.


Technologies

Backend
Java 21 · Spring Boot · PostgreSQL · Flyway · JWT
Frontend
React · TypeScript
Mobile
React Native · Expo · Zustand · Zod

This case omits confidential operational, financial, infrastructure and machine-specific information. Shown with the client's permission.