Case study · Tech Health
A real backend in. About 17,000 lines of code out.
Tech Health is a clinical operations portal for a PACE care organisation. It kept its own interface and moved from sample data to a live TechAppForce backend: sign-in, records, access rules, approvals and files came from the platform.
- 81business entitiesdefined as configuration
- 1,200fields, aboutno database code written
- 17lifecycles68 statuses, 78 transitions
- 0backend services writtenthe platform runs the backend
The challenge
A finished interface with nothing behind it
The screens existed. A real backend meant sign-in, roles, approvals, files and audit for every record, which usually means a lot of server code to write and maintain.
- Sign-in and roles
- Records and queries
- Access rules
- Approvals and statuses
- Change history
- Files and reports
How it was built
TAF Studio and AI, in about two weeks
About two weeks from an empty tenant on September 12 to every module on live data on September 27.
- Aug 14 to 26The interface, on sample data
The team ported the existing health system’s screens to a new Angular front end. Every screen ran on sample data: no sign-in, no real records.
- Sep 12An empty platform
The Tech Health tenant on TechAppForce had no objects, no queries and no workflows yet.
- Sep 13 to 19Objects built in TAF Studio, driven by AI
An AI coding agent read the front end’s data types and used TAF Studio’s own object designer to create each object and publish it. Seven medication objects went live in about 15 minutes.
- Sep 13 to 27TAFI inside Studio
TAFI’s Agent mode edited a page live inside Studio, and its Ask mode answered questions from live Tech Health data in 27 seconds.
- Sep 27Every module on live data
All 24 modules of the tenant portal loaded against the live backend with zero console errors and zero failed API calls.
Less code
The app got a backend and lost code
Lines of code written by the Tech Health team, before and after moving to TechAppForce.
| Part | Before (sample data) | After (live backend) |
|---|---|---|
| Whole app | 175,124 | 158,235 |
| Patient data layer | 33,008 | 22,474 |
For each line of data code Tech Health wrote, the platform supplies about twelve lines of server code it never had to write, test or maintain.
Tech Health data code: 11,232 linesPlatform services: about 130,000 linesWhat the platform did
What Tech Health wrote, and what it got
The interface stayed Tech Health’s own. Everything behind it came from TechAppForce.
- Sign-in and rolesTech Health wroteOne 102-line servicePlatform providedThe platform’s identity service
- Records for 81 entitiesTech Health wroteSmall connector files, about 11,000 lines in allPlatform providedOne generic data API for every entity
- Who sees whatTech Health wroteA 154-line roles servicePlatform providedAccess rules enforced by the data engine
- Statuses and approvalsTech Health wroteA 4-line helperPlatform provided17 lifecycles, configured
- Change historyTech Health wroteNothingPlatform providedAudit fields on every record
- File uploadsTech Health wroteTwo upload callsPlatform providedThe platform’s file service
- ReportsTech Health wroteOne 203-line servicePlatform providedThe platform’s report service
- Tenant separationTech Health wroteOne line of configurationPlatform providedTenant context on every call
What the code looks like
A whole data service, in a few lines
Tech Health’s allergy service lists, creates, updates and deletes records. Access, tenant and history rules are not in it, because the platform applies them to every call.
// Allergies: list, create, update and delete, on the platform's data API.
// Sign-in, access rules, tenant separation and change history are applied by the platform.
override async getAllergies(participantId: string) {
const rows = await this.data.entity('Allergy').query()
.select(...ALLERGY_COLUMNS)
.where('ParticipantId', REL_EQ, participantId)
.toArray();
return rows.map((r) => this.toRecord(r /* … */));
}
override async createAllergy(participantId: string, value: AllergyFormValue) {
const { id } = await this.data.entity('Allergy').create(this.toColumns(value, participantId));
await this.applyStatus(id, value /* … */); // the lifecycle decides if the move is allowed
return this.readOne(id /* … */);
}
override async deleteAllergy(participantId: string, id: string) {
await this.data.entity('Allergy').remove(id);
}- No controller, repository or SQL
- No permission checks in the code
- Status changes checked by the lifecycle
Where it stands
What is live, and what comes next
The tenant portal runs on the live backend. The separate admin portal still runs on sample data and is the next part to move.
How we measured: lines of code counted with cloc on the Tech Health repository (generated files excluded), before at the last sample-data version on August 26, 2026 and after on October 8, 2026. Platform figures come from the Tech Health workspace in TAF Studio. Dates come from the project’s commit history.
Bring the app you already have
Keep your interface. Get sign-in, data, access rules, approvals and files from TechAppForce.