Back to BlogCode Rescue & Fixes

You Outgrew Spreadsheets and a Half-Built App: the Rescue Path

Rupak Amin

Founder & Lead Engineer, RAITHub

8 min read

RAITHub ships and tests production software. See QA as a Service or talk to us.

When property management outgrows spreadsheets and a half-built app, the fix is not a rewrite. Back up the data and secure every account first, audit what the app actually does, migrate the spreadsheet data into a clean schema, and build the missing pieces in stages. Keep running throughout. A full restart loses the one asset you have: your real data.

If you would rather hand this to a team, see how RAITHub would fix this below. First, the order of operations that keeps you running.

How do you know you have outgrown spreadsheets?

A few signals, and most growing portfolios hit them between 20 and 300 units: two people edit the rent sheet and overwrite each other; a lease renewal is missed because the reminder lived in someone's head; a tenant disputes a payment you cannot trace; you copy the same data between a sheet, an email and an accounting tool by hand. Spreadsheets are a fine start. They fail as a system of record once more than one person edits them, money moves through them, or dates must trigger actions.

The half-built app usually arrived as the first attempt to escape the sheets, then stalled when the freelancer left or the budget ran out. You now run both, in parallel, and trust neither fully. That is a rescue, not a new build.

What should you secure in the first 48 hours?

Before changing any code, make sure you can never be locked out and never lose data. This mirrors the general code rescue playbook, applied to property data.

  • Get owner access to the code repository, the hosting account, the database and the domain, in your own name, not the freelancer's.
  • Take a full backup of the database and every spreadsheet, dated, stored somewhere only you control. Property data is tenants' home addresses, lease terms and payment history; treat it as sensitive.
  • Write down what runs where: which sheet is the source of truth for rent, which for leases, what the app is actually used for today.
  • Change shared passwords and remove access for anyone no longer involved.

What does the audit of the half-built app find?

A two-week diagnostic answers one question: is the app a foundation to build on, or scaffolding to replace? It looks at whether the code runs and deploys, whether there are any tests, how the data is modelled, and whether the critical paths (rent, leases, who-can-see-what) are safe. The output is a short report and a staged plan, not a verdict shouted on day one.

What the audit checksGood signWarning sign
Does it build and deploy?One documented commandOnly the original developer could deploy it
TestsAny automated tests for money or accessNone; every change is a gamble
Data modelClear tables for units, leases, tenants, paymentsEverything in one table, or data duplicated per sheet
Access controlRoles separate owner, manager and tenantOne login shared by everyone
Money pathPayments recorded once, reconciledRent status edited by hand, no audit trail

Keep or replace is a per-module decision, not all-or-nothing. A sound data model with a weak UI is worth keeping; a tangled model where a payment can be silently overwritten usually is not.

How do you migrate spreadsheet data without losing it?

Migration is where rescues succeed or fail, because spreadsheets are inconsistent: the same tenant spelled three ways, dates in two formats, a "paid?" column with "yes", "Y" and "✓". Model the target schema first (units, leases, tenants, payments, with the money stored in minor units as integers, never floats), then write a repeatable import script, not a one-time hand copy.

// A migration is a script you can run, check and re-run, not a hand copy.
// Store money as integer minor units; parse dates once; fail loudly on bad rows.
import { parse } from 'csv-parse/sync'

type RawRow = { tenant: string; unit: string; rent: string; paidOn: string }

function toLeaseRow(r: RawRow) {
  const amountMinor = Math.round(parseFloat(r.rent.replace(/[^0-9.]/g, '')) * 100)
  if (!Number.isFinite(amountMinor) || amountMinor <= 0) {
    throw new Error('Bad rent value for ' + r.tenant + ' / ' + r.unit)
  }
  return { tenant: r.tenant.trim(), unit: r.unit.trim(), amountMinor, paidOn: new Date(r.paidOn) }
}

const rows = parse(csv, { columns: true }) as RawRow[]
const clean = rows.map(toLeaseRow) // throws on the first bad row, so nothing silent slips in

Run it against a copy, reconcile the totals (does the sum of imported rent match the spreadsheet?), fix the source data, and re-run. Only cut over once the counts and money totals match exactly. Keep the spreadsheets read-only as a reference for a while after.

Buy, build or hire?

OptionWhat you getChoose this when
An off-the-shelf property management toolA ready product; you import your data and adopt its workflowYour process fits a standard tool and you are happy to change to match it
Finish the half-built app yourselfKeep what exists; add the missing featuresThe code is sound, documented and someone can maintain it
A rescue, then a staged custom buildStabilise, migrate the data, then build the pieces you actually needYou run on spreadsheets plus stalled code and cannot risk a big-bang switch
A managed team afterwardsThe build plus the tests that keep rent and access safeYou want the product maintained and extended over time

How long does a rescue take, and what is the risk of doing it yourself?

A diagnostic and stabilisation pass sits in the 2 to 4-week code-rescue range; the staged build of the missing pieces follows in fixed-scope phases. The main risk of doing the migration yourself is a silent data error: a mis-parsed date that moves a lease end, or a rent figure read as a float and rounded wrong. Because money and legal dates are involved, every import needs reconciliation against the source totals before you trust it. If an off-the-shelf tool fits your process, buying one and importing cleanly is often the cheaper answer; this rescue path is for when your workflow needs software built around it.

How RAITHub would fix this

  • Scope: secure owner access and back up everything; a two-week audit of the half-built app with a keep-or-replace plan per module; a reconciled migration of the spreadsheet data into a clean schema; then the missing features (leases, rent, roles, reminders) built in stages.
  • Timeline: 2 to 4 weeks for the audit and stabilisation; each build phase in the 4 to 6-week fixed-scope range.
  • What you receive: the audit report, migration scripts with reconciliation, tests in CI for the money and access paths, handover docs, the work on accounts you own, IP assigned to you and an NDA as standard.
  • Next step: a free 15-minute technical audit, then a fixed written quote.

RAITHub built PropDesk, property-management software with four roles, Stripe rent collection, leases, maintenance and 1,024 tests, and BlockEstate, a multi-tenant listings platform (6-week MVP, no MLS). See the code rescue service, the real-estate industry page, how a multi-tenant build is tested in multi-tenant property management SaaS, and the sibling post on validating a PropTech idea before building. To start, book the free 15-minute audit.

Frequently asked questions

Should I rewrite the half-built app or finish it?

Decide per module after a short audit, not up front. A sound data model with a weak interface is worth keeping; a tangled model where a payment can be silently overwritten usually is not. Most rescues keep some parts and replace others, so you never throw away working code or your real data.

How do I move my rent and lease data out of spreadsheets safely?

Model the target schema first, store money as integer minor units, and write a repeatable import script rather than copying by hand. Run it against a copy, reconcile the totals against the spreadsheet, fix the source data, and re-run until the counts and money match exactly before cutting over.

Can I keep running my properties during the migration?

Yes, and you should. Keep the spreadsheets as the live system until the new one is reconciled and proven, then cut over and keep the sheets read-only as a reference. A rescue stabilises what works before it changes anything, so day-to-day management never stops.

What should I secure before anyone touches the code?

Owner access to the repository, hosting, database and domain in your own name; a dated full backup of the database and every spreadsheet, stored where only you control it; a note of which sheet is the source of truth for what; and changed passwords with former contributors removed.

Is buying an off-the-shelf tool cheaper than a custom build?

Often, if your process fits a standard tool and you are willing to adopt its workflow. A custom build pays off when your workflow is the product, you serve other landlords or agencies, or no tool fits. The honest answer comes from the audit, which compares both against what you actually do.

property management rescueoutgrew spreadsheetscode rescuedata migrationproptechhalf-built app

Ready to discuss your project?

Book a free 15-minute technical audit with our engineering team.