Case Study

Multi-Tenant B2B SaaS Engine (NestJS + Stripe)

Backend Engineering for Trove Gifting — A production multi-tenant platform featuring modular architecture, async worker patterns, and encapsulated integrations.

ProductionBackend Engineering + IntegrationsArvin Kent Lazaga
Module
Per-domain NestJS structure: consistent across all feature areas
Guard
Layer tenant isolation — scoping enforced structurally, not by convention
Worker
App pattern: typed job handlers, idempotency keys, DLQ handling
3
Third-party integrations: Stripe, Shopify, Xero — each encapsulated

Overview

What was built

Trove Gifting is a B2B gifting platform that enables corporate buyers to send curated gifts to multiple recipients globally. The system runs across three applications — a customer storefront, a vendor admin portal, and a centralized NestJS backend — with a dedicated NestJS worker application consuming AWS SQS queues for asynchronous job processing.

As the main backend developer, I was responsible for implementing and structuring the server-side codebase within the defined system architecture. Beyond delivering individual features, I established the module conventions, service layer patterns, and integration abstractions that made the backend consistent and extensible throughout the engagement.

Core areas of implementation included: multi-tenant vendor and storefront handling with repository-level data isolation, a Shopify-level product and variation engine with async bulk operations, vendor-scoped configuration (shipping rules, SMTP, Stripe, AWS S3), the async job worker infrastructure, and complex gifting fulfillment flows including multi-recipient orders, unique redemption codes, and QR-based gift link delivery.

Architecture

System Architecture Overview

End-to-end revenue and fulfillment orchestration across payments, commerce, accounting, and cloud infrastructure.

01

Customer Frontend

React-based storefront where customers browse gifts, build bundles, and initiate checkout.

React · Next.js · Tailwind CSS

02

Stripe Payment Processing

Handles payment intents, subscription billing, webhook event verification, and refund lifecycle.

Stripe CheckoutPayment IntentsWebhooksSubscriptions
03

Shopify Webhooks + OAuth

Syncs product catalog, inventory levels, and order state via Shopify's Admin REST API using OAuth 2.0.

Shopify Admin API · OAuth 2.0 · Webhooks · Inventory Sync

04

NestJS Backend API

Core application layer. Orchestrates all service integrations, enforces business rules, and exposes RESTful endpoints.

NestJSTypeScriptREST APIGuards & Interceptors
05

MySQL via MikroORM

Relational persistence layer. Manages entities for orders, vendors, products, invoices, and audit logs.

MySQL · MikroORM · Migrations · Transactions

06

AWS Queue — Async Processing

Decouples heavy workloads such as email dispatch, PDF generation, and third-party sync into resilient job queues.

AWS SQSBullMQJob WorkersDead-letter Queue
07

Vendor Admin Frontend

Dedicated dashboard for vendors to manage their product listings, review orders, and download packing manifests.

React · Admin Dashboard · Role-based Access

08

Xero Invoice Payments + AWS S3

Auto-generates and reconciles invoices in Xero per vendor payout cycle. AWS S3 handles all document and asset storage.

Xero APIInvoice AutomationAWS S3Presigned URLs
Integration Layer
Standard Layer

Engineering

Technical highlights

Repository-Level Tenant Isolation

Tenant context is resolved at the Guard layer and injected into repositories at request scope. Vendor filters are applied structurally — not by convention — making cross-tenant leakage a compile-time concern rather than a runtime risk.

Standardized Job Handler Pattern

All async jobs implement a shared interface and are registered with a typed dispatcher. Adding a new job type requires one handler class — no changes to queue polling, dispatch, or retry infrastructure.

Shopify-Level Product Variation Engine

Product options, values, variants, attributes, and per-storefront assignment overrides — implemented against a relational schema. Variant generation for large option sets is offloaded to the worker via the same reusable job pattern.

Encapsulated Integration Services

Stripe, Shopify, Xero, SMTP, and S3 are each implemented as injectable services with typed method signatures. No module makes raw HTTP calls or handles credentials directly — integrations are consumed, not re-implemented.

Per-Recipient Fulfillment Model

Multi-recipient orders are split into FulfillmentUnit records at creation within a database transaction. Each unit carries its own items, address, shipping method, and redemption code — keeping downstream logic scoped to the correct unit of work.

Consistent Module-Per-Domain Structure

Every domain area follows the same internal layout: module, controller, service, repository, entities, DTOs. Onboarding a new feature or developer requires no structural judgment calls — the pattern is already established.

Stack

Technologies used

NestJS · TypeScript · MySQL · MikroORM · AWS SQS · AWS S3 · BullMQ · Stripe · Shopify Admin API · Xero API · Next.js · React · DigitalOcean VPS · Docker · Nginx

Need a similar system?

Let's scope your integration and automation requirements.

Discuss your project