Employer · Nexzen Solution

SaleBee CRM

Multi-tenant CRM · end-to-end ownership

Pages 10× faster and a zero-downtime move to .NET 10 and PostgreSQL, on a live CRM I have maintained since 2023 and now own end to end.

Role
Full-stack engineer · owns frontend, backend and database
Status
In production
Period
Jul 2023 – present
  • 5 s → 500 mscritical page loads
  • Zerodowntime during the database move
  • 2 stackskept running in parallel during the migration

SaleBee is a CRM that business clients use every day. It ran on ASP.NET 4.8 MVC, SQL Server and jQuery, and loaded each tenant’s full dataset into application memory to filter it in .NET. Pages got slower and memory grew as clients’ data grew, and the stack was getting harder to change, but clients could never be taken offline.

My work on SaleBee has had three stages. First I built features and kept the legacy ASP.NET MVC product healthy in production. Then I planned and carried out its migration to .NET 10, PostgreSQL and Next.js, one phase at a time, while continuing to maintain the old stack alongside it. Today I own the whole live product: frontend, backend, database and deployment.

  • Built and maintained features on the legacy ASP.NET MVC, SQL Server and jQuery stack, including production fixes, deployments and backups.
  • Planned and executed the strangler-fig migration to .NET 10, routing features to the new stack incrementally while maintaining the legacy system alongside it.
  • Built a data-transfer tool and moved the production database from SQL Server to PostgreSQL with zero downtime.
  • Rebuilt the frontend as a Next.js / TypeScript app on REST APIs, and built the endpoints for the Flutter mobile app.
  • Now own the live product end to end: frontend, backend, database, release pipelines and production servers.

Strangler-fig migration instead of a rewrite and cut-over

Clients depend on the CRM daily. Moving one area at a time meant every step could go live, be checked, and be rolled back on its own.

Move filtering into PostgreSQL instead of caching more

The legacy design cached each tenant’s whole dataset in memory, so cost grew with every client. Database-side filtering, pagination and materialized views made pages fast and memory flat.

A separate Next.js frontend on REST APIs

Retiring Razor and jQuery behind an API-first design let the web app, the Flutter mobile app and the new MCP server share the same backend.

  • Fixed recurring high-concurrency deadlocks in the legacy stack by redesigning locking behaviour; no incidents since.
  • Ported years of SQL Server stored procedures to PostgreSQL functions and materialized views.
  • Added an MCP server so customers can manage leads and follow-ups from AI assistants.
  • A .NET background service on RabbitMQ handles bulk email, SMS and push notifications.
  • Maintaining the legacy system for live clients while building and rolling out its replacement.
  • Keeping behaviour identical for clients while the code and data underneath them changed.
  • Moving live production data between two database engines without a maintenance window.
  • SaleBee now runs on .NET 10, PostgreSQL and Next.js, and I own it end to end.
  • Critical pages load in about 500 ms instead of 5 s, and memory no longer grows with tenant data.
  • The API-first backend serves the web app, the mobile app and AI assistants through MCP.
  • Knowing the old system from the inside, from years of maintaining it, is what made a safe migration possible.
  • Changing a system people depend on is mostly about sequencing: small, reversible steps that each prove themselves in production.

Want something similar built? Get in touch →