Loading image 1...

01/04

SmartGymSystemMaintenance

Maintaining and Extending a Multi-Tenant Gym Management System on Live Production Data

Client
SmartGym, Indonesia
Year
2026
Timeline
3 weeks
Category
App Development / Legacy System Maintenance
UI Goal
Change a system that is already running without damaging the member, payment and attendance data already inside it.
VISUAL STYLE
Dense, fast-to-fill staff interfaces sitting alongside a mobile-native member portal built on the same login theme.
LAYOUT SYSTEM
Role decides the surface: back office, cashier, member and trainer each get their own subdomain and layout from one codebase.
PRIMARY DEVICE TARGET
Gym staff working the same screen all day, and members opening their portal from a phone.
SmartGym System Maintenance
Featured Work

SmartGym System Maintenance

Maintaining and Extending a Multi-Tenant Gym Management System on Live Production Data

Overview

Maintaining and Extending a Multi-Tenant Gym Management System on Live Production Data

Javapixa carried out maintenance and feature work on SmartGym, a gym management system already running with real members, payments and attendance records. The system is three separately-deployed CodeIgniter 4 applications, a staff back-office, a member and trainer portal, and a public website, that all read and write the same MySQL database. One codebase serves several gyms, each with its own database, asset tree and subdomains, with routing branching on the HTTP host. Across 101 commits and 492 application files, the work covered class booking, a cashier subdomain, a tenant schema upgrade and a public site rework, and none of it was allowed to damage the data already there.

Challenge

The Problem

This was not a greenfield build. Model classes are duplicated across the three applications, so a schema change in one can break the other two. The schema itself cannot be reconstructed from the repository: only three migrations exist, and three views the code queries daily are created by none of them, which makes the database dump the real disaster recovery. Hosting is shared, so SUPER and SET_USER_ID are unavailable, yet the existing export carried DEFINER clauses demanding exactly those privileges. The application also depends on a permissive database configuration, so legacy SQL is rejected outright by a server running only_full_group_by.

Solution

Every change was verified against a restored copy first, never speculatively on production. The tenant schema upgrade was built and tested through a fixed cycle: restore the client dump, reshape it to the live server's exact state, apply the upgrade, run the failing migration's real SQL on top, then finish with an information_schema diff against the reference schema that had to come back empty. A renamed enum value was migrated by widening the enum to hold both values, moving the data, then narrowing, so 404 member rows were not blanked. The created_at column was added as NULL rather than DEFAULT CURRENT_TIMESTAMP, so years of history were not stamped with today's date. On the front end, the public site was rebuilt so every section draws from the database, with sample content that marks itself in the delivered HTML so nothing invented can quietly stay in production.

VisualJourney

Project Showcase

Loading image 1...

Screenshot 1

Project visualization and interface design

01/04
Navigate

TechStack

01

CodeIgniter 4

PHP Framework

02

PHP 8.3

Language

03

MySQL / MariaDB

Database

04

Tailwind CSS

Styling

05

JavaScript

Frontend

06

LiteSpeed

Shared Hosting

KeyFeatures

[01]

Class Booking Subsystem

Class booking built end to end: a new table, two per-line subscription views, and the member-facing flow. This is where the subscription model's real shape surfaced, because a subscription container can hold several products with different end dates, so status has to be judged per line rather than per container, and the reporting that depends on it was corrected to match.

[02]

Isolated Cashier Subdomain

The cashier subdomain serves the point-of-sale screen and nothing else, on a minimal layout, so till staff cannot reach the back office from the same terminal.

[03]

Tenant Schema Upgrade Script

One ordered script bringing an older-generation tenant database up to the schema the current application expects: 23 missing tables, 74 column statements, 8 type and enum differences, and 7 views, with a view dependency order that must not be rearranged.

[04]

Enum Migration Without Data Loss

The enum value mahasiswa became pelajar while 404 member rows still held the old one. Narrowing the enum first would have blanked them, so the script widens the enum to hold both, migrates the data, then narrows.

[05]

A Public Site Driven by Real Data

Every section of the public site draws from the database. A newly-provisioned gym with an empty database still renders a whole page through sample content, and every fallback is marked in the delivered HTML with the route to replace it, so nothing invented can be mistaken for real content.

[06]

Defensive Rendering and Versioned Caching

Filenames in the database outlive files, so every image URL is checked on disk before it is emitted. Logos, favicons, PWA icons and uploaded photos carry a version stamp taken from the file's own modification time, so there is no manual cache-busting step to forget.

OurProcess

A detailed look at how we brought this project from concept to reality through our proven methodology.

01
Duration
6 days

Consolidation and Correctness

Brought three applications and a shared asset tree under one repository, with a local development harness: a host-dispatching router, because production serves each app from its own document root with the front controller at the app root, which makes the standard framework dev server unusable. Substantive fixes followed: subscription status, attendance records, member photographs, and a dynamic QR code for gate access.

Deliverables
Single Repository
Local Development Harness
Subscription & Attendance Fixes
02
Duration
2 days

Class Booking and the Schema It Needed

Class booking added end to end with a new table, per-line subscription views and the member-facing flow, across three migrations. Also in this stretch: per-app PWA manifests, privacy fixes, and a full revamp of the member portal onto a mobile-native design.

Deliverables
Booking Table
Per-Line Subscription Views
Member Portal Revamp
03
Duration
5 days

Product Management and Interface Systems

The heaviest single area in the history: the class-product editor, with fourteen commits into its form and schedule builder, covering day cards, time chips, native time inputs, and layered pop-ups that clipped. Alongside it, per-channel product visibility, show on website or show in member app, and an icon rebrand for a second gym.

Deliverables
Class Product Editor
Per-Channel Visibility
Scoped Design System
04
Duration
1 day

Point of Sale and a Class of Database Bug

A dedicated cashier subdomain carved out, public per-class product pages added with a booking CTA, and the member dashboard reworked around them. Three fixes on this day share one root cause worth naming: the application depends on a permissive database configuration, and legacy SQL is rejected outright by a server running only_full_group_by.

Deliverables
Cashier Subdomain
Public Class Product Pages
Strict SQL Mode Fixes
05
Duration
1 day

Onboarding a New Gym

Bringing a third gym onto the current code, the largest single piece of diagnosis in the engagement. The failing migration turned out to be a symptom: that tenant's schema was an older generation entirely, and the application requires a deleted_at column independently of any migration because every model uses soft deletes. Resolved with an upgrade script tested against a restored copy.

Deliverables
Schema Upgrade Script
Portable DEFINER-Free Dump
Installation Runbook
  • 01Tenant schema upgrade covering 23 tables, 74 column statements and 7 views, verified against a restored copy with zero remaining differences.
  • 023,198 member records and 3,198 distinct UUIDs survived the backfill, with 404 biodata rows and 33 product rows migrated across enum values without data loss.
  • 03Class booking delivered end to end, with per-line subscription views that judge status per product rather than per container.
  • 04Point of sale isolated to a dedicated cashier subdomain, so till staff cannot reach the back office.
  • 05Fabricated ratings, reviews and stock avatars removed from the public site, replaced with a live member count from the database and a rating sourced from configuration.
  • 06The database export made portable by stripping DEFINER clauses, so it imports under any shared-hosting user.

Want something like this?

These are the Javapixa services behind this project.

SmartGym System Maintenance - Portfolio | Javapixa Creative Studio