01 / Product — SaaSFeaturedCase Study

Synccos | Checkwriter

A live, multi-tenant financial platform modernized incrementally — evolving from a tightly coupled single-tenant system into a scalable architecture while remaining in continuous production with active financial users throughout.

ReactNode.jsMongoDBExpressTypeScriptMongooseStripeSentryTanstack QueryFormikQuickBooksAWS S3OAuth 2.0TwilioGoogle Authenticator

Ongoing · Production modernization · Active financial users throughout

At a Glance

Connection instances

30+→1

MongoDB connections consolidated to singleton

State management

Redux→TQ

server state migrated to TanStack Query

Multi-tenancy

Full

users + orgs sharing financial entities

Downtime

Zero

all changes shipped without taking system offline

* All changes were delivered incrementally under continuous production constraints with no downtime.

The Problem

Synccos Checkwriter was already live and handling real financial operations when new requirements arrived — multi-tenant support, expanded payment workflows, and organization-level banking entities. The system worked, but it had grown into a tightly coupled architecture that made every new feature a risk.

Redux was handling both client and server state, the MongoDB schema embedded financial entities directly inside user documents under a single-tenant assumption, and 30+ MongoDB connection instances had accumulated across modules — a hidden infrastructure fault that only surfaced once the schema was touched. The core constraint was non-negotiable: the system could not go offline, could not be rewritten, and new features had to ship continuously while the architecture underneath was being rebuilt.

Constraints

System was live with active financial users — zero downtime permitted at any point
No rewrites — all changes had to be incremental and backward compatible
New features had to ship continuously while refactoring was in progress
Financial correctness was critical — payment, balance, and reconciliation logic had zero tolerance for inconsistency
Multi-tenant ownership model had to support both users and organizations sharing the same financial entities
Legacy Redux patterns had to be migrated without breaking existing flows

Architecture Overview

Frontend

Redux (client state) + TanStack Query (server state)

Backend

Express + normalized MongoDB collections

Ownership

entityType / entityId unified model

Auth

MFA — email, Twilio OTP, authenticator app

Payments

Stripe + QuickBooks sync

Infra

Singleton DB connection + compound indexes

Key Engineering Decisions

Separating client state from server state

Redux was doing double duty — managing both UI state and remote data fetching. This created deeply coupled reducer logic, redundant synchronization patterns, and brittle loading states scattered across the codebase. I drew a clear boundary: Redux retained ownership of client-only state, while all server interactions moved to TanStack Query. Data-fetching logic became declarative, caching became automatic, and the Redux surface area shrank to only what belonged there.

Eliminated redundant state sync patterns; API interactions became predictable and independently cacheable

Normalizing the MongoDB schema for multi-tenancy

The original schema embedded bank accounts and payees directly within user documents — a clean design for a single-tenant system, but impossible to extend to organizations. I decomposed the schema into separate collections and introduced a unified ownership model using explicit entityType and entityId fields. A single bank account could now be owned by either a user or an organization without duplicating schemas or forking query logic. Compound indexes on these fields kept tenant-scoped queries efficient as data volume grew.

Shared financial entities (bank accounts, payees) work across both user and org contexts from a single schema

Enforcing a singleton database connection

After schema normalization introduced cross-collection dependencies, a previously hidden issue surfaced: 30+ MongoDB connection instances had accumulated across modules, causing inconsistent Mongoose model registration behavior where certain collections weren't being resolved correctly depending on connection context. The embedded single-collection design had masked this entirely. I enforced a singleton connection pattern — all models registered against one shared instance — which immediately stabilized schema resolution across the entire system.

Eliminated model registration inconsistencies; cross-collection queries became reliable

Sequencing refactoring around continuous feature delivery

The hardest part of this project wasn't any single technical decision — it was the ordering. Every architectural change had to be backward compatible with the code still running in production. TypeScript was introduced incrementally: new modules in TypeScript first, legacy modules migrated opportunistically. The API abstraction layer was extracted gradually. Schema normalization happened collection by collection, with dual-read logic bridging old and new shapes during the transition window.

Zero production incidents during the full modernization; system remained stable and shippable throughout

Outcomes

  • Migrated server state from Redux to TanStack Query, eliminating redundant sync logic across the frontend
  • Normalized MongoDB schema from embedded user documents to multi-tenant collections with a unified ownership model
  • Resolved a 30+ connection accumulation bug that had been hidden by the single-tenant schema design
  • Introduced TypeScript incrementally — new modules typed from day one, legacy modules migrated during ongoing development
  • Built and extracted a centralized API abstraction layer, later released as the open-source axios-auth-client npm package
  • Delivered Stripe payment flows, QuickBooks sync, Excel bulk import, and MFA (email + Twilio OTP + authenticator app)
  • Built a check register system maintaining running balances per bank account across both user and org contexts
  • Shipped all of the above with zero downtime under continuous production constraints

Takeaway

“Production systems evolve safely through incremental, constraint-aware refactoring. The most impactful engineering decisions are often about sequencing, ownership modeling, and tradeoff management — not isolated technical implementations. The goal was never to build the perfect architecture. It was to move from the architecture we had to the one we needed, without breaking what was already working.”