Case Study • Deovise
Back to portfolio

Deovise
Platform Architecture

A multi-service food product insights platform combining multi-tenant admin governance, emissions analytics, ingredient alternatives, and scenario tooling across React, Express, Postgres, and Python Azure Function Apps.

React 18 (CRA)MUI 7 + MUI X Data Grid ProRedux Toolkit + redux-persistNode.js + Express (ES modules)PostgreSQL (pg)Python Azure FunctionsSQLAlchemy + pandasJWT auth

Executive Summary

Core Pattern

React UI + Node API boundary + Python analytics services

Data Strategy

Postgres + denormalized emissions read models + JSONB version history

Governance

Multi-tenant RBAC, soft delete lifecycle, admin-only category controls

Resilience

Proxy fallback handling and local Postgres compute paths

Overview

Problem, opportunity, and role.

The Problem

Teams needed a single platform to manage product composition, maintain governed ingredient/emissions master data, and run emissions-driven comparisons and alternatives without exposing backend keys or fragmenting workflows across tools.

The Opportunity

Build a product-first admin platform that combines multi-tenant governance, auditable product versioning, and resilient emissions/alternatives analytics behind a secure API boundary.

My Role

Product architect and hands-on builder across system design, API patterns, data modeling, admin workflows, proxy/fallback strategy, and alignment of Python analytics services with the Postgres-backed platform.

Key Constraints

  • Multi-tenant access control and system-admin exceptions
  • Analytics endpoints living in separate Python function services
  • Some environments missing deployed proxy/function routes
  • Migration alignment from historical Azure SQL assumptions toward Postgres
  • Need for auditable change history in product composition edits

Architecture Decisions

Layered platform with a deliberate API security boundary.

Deovise uses a pragmatic split between the admin application, the Node API, and Python analytics services. The Node layer is not just CRUD middleware; it acts as the security and resiliency boundary for analytics integrations.

Frontend Web App

React 18 (CRA) + MUI 7 with MUI X Data Grid Pro for admin-heavy CRUD, table workflows, and inline detail/compare views. Redux Toolkit manages global state with persisted auth/user/UI mode.

Node API Boundary

Express API with CORS, Helmet, Morgan, JSON parsing, centralized 404/error handling, JWT middleware, role checks, and proxy routes that keep Function App keys private from the browser.

Postgres Data Layer

Primary datastore via pg, wrapped in a small abstraction that supports MSSQL-like @param query ergonomics while safely binding Postgres positional params, plus a lightweight transaction helper.

Python Function Services

Azure Function Apps for emissions aggregation and category-based ingredient alternatives, implemented with SQLAlchemy + pandas, reading Postgres credentials from environment variables.

Request / Compute Flow

  1. 1Browser requests admin/product/emissions workflows via React app
  2. 2Express validates JWT and resolves user context (organisation + roles)
  3. 3Express serves CRUD data from Postgres and/or proxies emissions calls
  4. 4Proxy injects Function App keys server-side and forwards requests
  5. 5If function routes are unavailable, Express can compute from local denormalized Postgres views
  6. 6UI degrades gracefully for unavailable alternatives routes while keeping core workflows functional

Why These Decisions

Security boundary at Express

Why: Function keys remain server-side and client integrations stay stable even if analytics endpoints move.

Impact: Improves security posture and allows fallback logic/caching in one place.

JSONB snapshots for product versioning

Why: Version history needed to be auditable, diffable, and restorable without brittle per-field patch logic.

Impact: Enabled restore flows and structured diffs with transaction-safe writes.

Denormalized emissions views

Why: Emissions reads and comparisons are repeated, analytics-heavy workloads that benefit from optimized read models.

Impact: Reduced query complexity and improved practical responsiveness for grid/compare workflows.

Soft-delete lifecycle pattern

Why: Admin systems need reversibility, governance, and clean auditability across entities.

Impact: Consistent behaviour across organisations, users, roles, categories, and master data.

Cached role and mapping lookups

Why: Role checks and subcategory mapping resolution were repeated frequently in admin and emissions flows.

Impact: Lower DB roundtrips while keeping authorization and mapping logic centralized.

Postgres-first migration path

Why: Some ancillary tooling historically assumed Azure SQL/Key Vault, but platform direction aligned around Postgres + env-driven secrets.

Impact: Cleaner operational model and more consistent local/dev/deploy parity.

Key Features

Core functional areas built for admin governance and analytics work.

The platform combines standard admin capabilities with domain-specific emissions and alternatives tooling. The important part is how these workflows connect across governance, composition data, and analytics.

Authentication + Account Flows

01

JWT login, admin-mediated user registration, password reset tokens with generic initiation responses, and Gmail OAuth2 email delivery with branded templates.

  • Account enumeration-resistant reset initiation
  • Role payload included in login response
  • Admin-created user flow with bcrypt + optional welcome email

Multi-tenant Organisations + RBAC Admin

02

Organisations, users, roles, and user-role assignments with soft delete and role-aware filtering behaviour.

  • Paginated list/search/sort admin endpoints
  • DB-backed user context helper + cached role-name checks
  • Assignment count views for role governance

Product Library + Composition

03

Scoped product CRUD with category hierarchy tagging and ingredient composition percentages, returned via server-built snapshots for consistent responses.

  • System admin vs organisation member scoping
  • 3-level product category hierarchy
  • Joined product + ingredient composition snapshots

Product Versioning / Audit / Restore

04

Dedicated product_version table with JSONB snapshot + changes, structured diffing, and restore support built around transactions.

  • Stable compare format for diffing
  • Restore creates a new version record
  • Created/updated by metadata retained

Ingredient Emission Factors

05

Grid-style master data workflows for ingredients/emissions with subcategory normalization, country resolution helpers, and org/system scope rules.

  • Human-ish key normalization to subcategory IDs
  • Subcategory mapping cache with TTL
  • Country match by ID, ISO, or name

Category Governance + Swap Options

06

3-level product and ingredient category hierarchies with admin-only mutation, soft delete + reassignment, and ingredient swap mappings for alternatives logic.

  • Governed category delete + reassignment workflows
  • Ordered swap options mapping with max count cap
  • Direct feed into recommender logic

Emissions Proxy + Fallbacks

07

Express proxy under /emissions-data/* injects keys and forwards to Python services, with path/URL fallbacks and local Postgres compute fallback when functions are unavailable.

  • Browser never sees Function App keys
  • Practical resiliency and 404 handling
  • Local fallback preserves user workflows

Frontend Emissions Workflows

08

Product library emissions views, compare flows, expanded details, and client-managed swap scenario state with graceful degradation in partially deployed environments.

  • Per-product and per-kg style metrics
  • Limited side-by-side compare interactions
  • Draft/saved swap state + tabbed analytics

Insights & Coffee Data/ML Utilities

09

Python function apps, scenario composer tooling, notebooks, and a Streamlit upload helper for ingestion validation, fuzzy matching, and repeatable mapping workflows.

  • SQLAlchemy engine caching + env-based Postgres creds
  • Category-based alternatives grouped by swap class
  • Upload validation with Postgres-first and Azure SQL fallback paths

Tradeoffs & Constraints

Practical engineering decisions over idealized purity.

The platform decisions prioritized secure integration boundaries, operator usability, and resilient analytics workflows. That required accepting some complexity in the API and data layers.

CRA frontend vs immediate Next.js migration

Rationale: CRA allowed fast delivery of admin-heavy workflows with MUI Data Grid Pro while architecture effort focused on data/model reliability and analytics integration.

Tradeoff: SSR/SEO is not a priority benefit for internal/admin workflows, but migration to Next would later improve app shell consistency and deployment ergonomics.

Proxy + fallback complexity vs direct function calls

Rationale: Centralizing function access in Express protects keys and enables resiliency patterns that client apps should not own.

Tradeoff: More server code and operational paths to test, but significantly better security and failure handling.

Denormalized read models vs pure normalized queries

Rationale: Emissions analytics and compare flows are read-heavy and repeated; denormalized views simplify query logic and improve response times.

Tradeoff: Higher maintenance burden on data definitions and validation, but improved UX for data-heavy screens.

Soft delete everywhere vs hard delete simplicity

Rationale: Admin/governance systems benefit from reversibility and audit context, especially with dependent category/product relationships.

Tradeoff: Extra filtering and lifecycle logic across endpoints, but safer operational behaviour.

Outcomes / Metrics

Portfolio-worthy outcomes, with metrics disclosure kept pragmatic.

This portfolio version emphasizes architecture and delivery signals. Quantitative metrics are not publicly disclosed here, but the implementation outcomes and quality signals below reflect production-minded engineering decisions.

Outcomes / Delivery Signals

  • Established a pragmatic multi-service architecture with clear boundaries between UI, API security layer, and analytics services.
  • Delivered governed admin workflows across organisations, users, roles, categories, product library, and emissions master data.
  • Implemented a portfolio-worthy audit/versioning model with JSONB snapshots, diffs, and restore actions wrapped in transactions.
  • Created operational resilience via proxy fallbacks and UI graceful degradation instead of all-or-nothing analytics dependencies.
  • Improved data-read ergonomics for emissions workflows through denormalized views and cache-assisted lookup patterns.

Testing & Quality Signals

  • Server Jest unit + smoke tests (including protected-route smoke coverage for key admin/proxy endpoints)
  • Client CRA/Jest tests for key flows/admin actions
  • Test setup suppresses expected noisy console output for intentional error-path tests

What I'd Improve Next

Hardening the platform for scale, consistency, and clearer insight loops.

The platform foundation is strong. The next gains come from contract consistency across services, deeper observability, and sharper product analytics on scenario usage and outcomes.

Expand public case-study metrics once acceptable commercial disclosure boundaries are defined.

Complete migration alignment for all ancillary tooling to Postgres + env-driven secrets.

Formalize API contracts/shared schemas across Node and Python services to reduce drift.

Add deeper observability on proxy fallback frequency and analytics endpoint performance.

Continue extracting reusable product/admin domain modules as the platform footprint grows.

Contact

Need this level of architecture thinking on your platform?

I work best on product platforms where data models, delivery constraints, and system boundaries matter as much as UI polish.