← Back to case studies

· 2 min read

Migrating an AppSheet CRM to Express + PostgreSQL

Replaced a no-code AppSheet CRM hitting its limits with a typed Express + PostgreSQL backend and a React front-end — without losing a single record.

Problem

A small sales team outgrew AppSheet: slow syncs, no real relational integrity, impossible to integrate with billing, and per-user pricing scaling badly. They needed ownership of their data and an API other tools could call.

Result

Cut manual data-sync from ~6 hrs/week to near-zero; eliminated the daily row-count reconciliation.

Stack

  • TypeScript
  • Express
  • PostgreSQL
  • React
  • Drizzle ORM
  • Vitest

TL;DR

AspectBefore (AppSheet)After (Express + PG)
Data modelFlat Google Sheets, duplicatedNormalized relational tables
IntegrityNoneForeign keys + constraints
IntegrationGoogle Apps Script hacksREST API
Cost scalingPer AppSheet userFlat hosting

Architecture

A clean split: Express API + PostgreSQL as the source of truth, React SPA for the team, and a one-time ETL bridge that pulled AppSheet’s sheets into relational tables.

AppSheet (Google Sheets) ──ETL──▶ PostgreSQL (normalized)


                              Express API (REST)

                          ┌───────────┴───────────┐
                          ▼                       ▼
                    React SPA              Billing / webhooks

Interesting decisions

Lessons learned

Pros & cons

Pros: full data ownership, an API other services can call, predictable flat cost. Cons: you now operate a database (backups, monitoring) — AppSheet hid that from you.

Work with me

I build business software like this — fast, with AI-assisted delivery. Open to remote (US/EU) roles and freelance.

Get in touch · See my AI workflow →