Event Equipment ERP Platform
A business management system that grew alongside its client for 20 years
Context
In 2004, an event production company in São Paulo was running its entire equipment rental operation from spreadsheets and phone calls. Every event required manually coordinating which lights, sound systems, and staging equipment were available, which trucks were scheduled, and who owed what to whom. As they grew, the spreadsheets broke. Things got lost. Double-bookings happened.
I had been working with them on a small web project. They asked if I could build something to track rental orders. That “something” became a 20-year engagement.
This is not a project I designed once and deployed. It’s a system I redesigned several times, migrated twice, and extended continuously — each phase teaching me something the previous one didn’t.
The Problem
The first version of the problem was simple: track which equipment goes to which event, on which dates, and whether it came back. But as soon as you solve that, the real problems reveal themselves:
- How do you prevent the same item from being booked twice on overlapping dates?
- How do you track damage and assign costs to the right client?
- What happens when one event needs items from a job that’s running late?
- How do you invoice 80 clients per month without it taking a full week?
By 2010, the company had grown from one team to three. By 2015, five distinct business units — each with its own team, revenue stream, and reporting needs, but sharing the same equipment pool and some staff.
The technical problem became: how do you build a system that feels like one product to the people using it, but correctly separates data, permissions, and financials by business unit?
Approach
I didn’t know what multi-tenancy was when I started. I learned it the hard way — first by building the wrong thing (a single shared database where “units” were just a tag on records), watching that fall apart under real use, and then rebuilding it properly.
Phase 1 (2004–2008): Classic ASP + SQL Server First version was Classic ASP with a single SQL Server database. It tracked orders, items, and clients. No user roles, no financial logic, no mobile. Built fast, worked well for the size they were.
Phase 2 (2009–2014): Rebuilt as a proper web application The company started hiring more people and needed role-based access. I introduced proper authentication, user roles (admin, manager, field crew, finance), and the first version of financial tracking. Still Classic ASP on the server, but the frontend got a complete rewrite — structured JavaScript for the first time.
Phase 3 (2015–2020): Multi-tenant architecture + Node.js API When they split into 5 business units, I had to rethink the whole data model. I moved to a separated API layer (Node.js) with the frontend consuming JSON. The database was restructured around tenant isolation — each business unit has its own schema, but a central auth layer and shared equipment pool across units, with explicit booking/transfer logic.
Phase 4 (2020–present): Material Design UI + banking integration A full frontend rebuild using a structured component system inspired by Material Design — still vanilla JS, no framework. Added real-time notifications (WebSockets), banking system integration for payment reconciliation, and automated background jobs for financial reporting.
Technical Decisions
Why Classic ASP at the start? In 2004, ASP was the server technology I knew, the client’s server was IIS, and the job was to ship something that worked. I didn’t fight the environment. If I had insisted on learning something new first, the project would have taken six months instead of six weeks.
Why not migrate to a framework when rebuilding? Every time I considered a framework (Rails, Django, later React), I came back to the same constraint: I was the only developer, and frameworks introduce dependencies that can strand a project if the developer changes. Vanilla JavaScript and a clear internal structure meant anyone moderately experienced could maintain it. That mattered for a 20-year relationship.
Why Node.js for the API? By 2015, I was already comfortable with JavaScript everywhere. Node let me share validation logic between client and server, and the async model suited the way the app worked — lots of concurrent users checking availability, not a lot of heavy computation.
The multi-tenant database design
Each business unit has its own SQL Server schema (unit_a.orders, unit_b.orders, etc.) but a shared core schema for users, equipment catalogue, and cross-unit bookings. This meant:
- A finance user at unit A cannot accidentally see unit B’s financials
- Equipment can be transferred between units with full audit trail
- Central reporting across all units is a single query against the shared schema
The tradeoff: schema migrations become more complex. Any structural change to orders has to be applied to 5 schemas. I solved this with migration scripts that loop across tenant schemas.
Screenshots
Screenshots coming — need to capture from the live system.
Outcome
- 400+ active users across 5 business units
- System has been in continuous production since 2004 — ~20 years
- Replaced a team of 3 doing manual coordination with automated scheduling and conflict detection
- Banking integration eliminated manual payment reconciliation (previously ~2 full days/month)
- Survived two complete technology migrations (ASP → Node API, single DB → multi-tenant) with zero data loss
The company grew significantly over this period. Whether the system enabled the growth or simply kept up with it is hard to say — but it never became the bottleneck.
Lessons
Long-running systems teach you things short projects never do. The features I thought were important in 2004 barely matter today. The things that mattered most — audit trails, data integrity, migration safety — I didn’t fully appreciate until I needed them.
“Boring” choices age well. Every time I didn’t use a framework, I was making a bet on longevity over convenience. That bet paid off. The 2008 code, cleaned up, still runs parts of the system.
Build for the next developer, even if that’s just future you. The hardest parts of maintaining this system are the parts where I tried to be clever. The easiest parts are where I was obvious.