← All work
Healthcare Ireland - Enterprise Platform - cover
01 / 04
Healthcare
Case study

Healthcare · Healthcare Ireland Group

Role: Architected the frontend; contributed to the NestJS backendLive ↗
React 19Vite 7TanStack SuiteZustandSocket.ioNestJS 11Prisma 6PostgreSQLBullMQMinIO

Problem

A major Irish healthcare group needed a unified platform to run patient management, scheduling, clinical notes, billing, and analytics across multiple branches and departments - with real-time data synchronization and AI-assisted clinical documentation. Existing tools were fragmented, slow, and forced clinicians to context-switch between disconnected systems.

Your scope

I architected the frontend end to end - composition, state, routing, real-time integration, data-table system, and the shared design language - and contributed key modules on the NestJS backend including the AI agent service for SOAP-note generation. Honest framing: this was a team build; my slice was the frontend architecture plus the AI module.

System architecture

Client-server with persistent WebSocket channels for real-time sync. The frontend (Vite 7, React 19, TanStack Router) communicates with a NestJS 11 backend through REST endpoints and Socket.io. The backend implements a three-tier multi-tenant hierarchy (Organization → Branch → Department) with tenant-scoped data isolation enforced at the Prisma layer. Background processing runs through BullMQ; file storage uses MinIO (S3-compatible).

Fig. 1 - Org → Branch → Department isolation with Socket.io rooms mapped to the tenant hierarchy.

Key decisions

  • Tenant isolation in Prisma middleware, not application code. Considered enforcing tenant scope per-query in service code; rejected - too easy to miss one branch and leak data across organizations. Centralised in middleware so isolation can't be forgotten.
  • Socket.io rooms mapped 1:1 to tenant hierarchy. Considered a broadcast-and-filter approach; rejected - too noisy for clinicians with hundreds of concurrent connections. Room-based broadcasting puts the filter at the source.
  • TanStack Table with server-side sorting/filtering/pagination, not client-side. Patient rosters routinely run into tens of thousands of rows; client-side filtering melts laptops. Server-side keeps the UI responsive at any scale.

Engineering challenges

  • Multi-tenant isolation at the ORM layer without sacrificing query performance.
  • Real-time synchronization for clinical data where consistency matters and stale UI is unacceptable.
  • Encapsulating LLM calls (SOAP-note generation from audio) inside the NestJS module system with structured output validation and audit logging.

Solutions

  • Tenant-scoped Prisma middleware injects organizationId/branchId context into every query - invisible to service code, impossible to miss.
  • Socket.io room-based architecture mapped to tenant hierarchy for targeted real-time broadcasts.
  • NestJS agent module that encapsulates LLM calls with Zod-validated structured output and full audit logging - type-safe AI inside a typed backend.
  • Comprehensive Winston logging with daily rotation for regulatory compliance.

What I'd change

Stack

  • Frontend - React 19, Vite 7, TanStack Router/Query/Table/Form, Zustand, Socket.io client
  • Backend - NestJS 11, Prisma 6, PostgreSQL, BullMQ, Winston, Swagger
  • Infra & AI - MinIO (S3-compatible), Passport.js/JWT, Zod-validated structured LLM output

Links