Web Applications

Membership renewals rebuild for a professional association

Built by Ronnel Ilagan

Replaced an annual renewal process that ran on a spreadsheet, two staff members' memory and a lot of January overtime.

  • Builder email verified

    Verification

Type
Professional
Category
Web Applications
Published
Jul 26, 2026
Updated
Jul 26, 2026
Built withPHPLaravelMySQLJavaScriptNginxGit
TopicsCommunityProductivity

About this project

The problem

Members renewed once a year and the association had no reliable way to say who had actually paid. The membership team kept a spreadsheet reconciled by hand against bank statements, and every January two people worked through a few thousand rows while members phoned in asking where their certificate was. Money leaked at both ends: members who quietly lapsed and nobody chased, and members who paid twice because the first payment was not visible anywhere they could see. What they wanted was for the renewal window to stop being a crisis, and to be able to answer "am I current?" without a person looking it up.

My role

Contract full-stack developer for about nine months. The team was four — me, a business analyst who had been with the association for years, a part-time designer, and a junior developer from their own IT staff who was learning the codebase alongside the work. I reported to a product owner on the operations side who was not technical and was very good at describing what actually happened in the office. For the first four months I was the only person writing backend code.

What I owned

I owned the renewal state machine and everything around it: the model of what a membership period is, the transitions between current, in grace and lapsed, and the nightly job that moves people between them. I built the admin screens the membership team lives in — look someone up, apply a manual adjustment, and read the history of why a status changed — which turned out to matter more than the member-facing side. I also owned the data migration, folding eleven years of spreadsheet rows and two older systems into one member timeline, which I ran and re-ran about thirty times before it was clean. The card processing itself was specified by me but implemented by a specialist contractor who held the certification.

Technical & product decisions

The big call was refusing to migrate the old member database during the project. It held addresses, chapters and qualifications that other things fed off, and every plan to move it added months, so I proposed leaving it as the source of truth for identity and writing renewal state alongside it with a narrow two-way sync on the fields we touched. The analyst pushed back because two sources of truth is a smell and she was right in principle; what settled it was that the alternative put a migration inside the renewal window. I also argued for a status history table rather than a status column, because the first question the office ever asks is "why is this person lapsed?" and a column cannot answer that.

Constraints

The renewal window runs November to February and nothing ships during it — non-negotiable, so we had one deployment slot in October and a rollback plan we rehearsed twice. Card payments had to stay with the processor the association was already certified against, which was slow to answer questions and whose sandbox differed from production in exactly one behaviour that cost us a week. Anything outside agreed scope went through a change request to a committee that met fortnightly, so we batched requests and lost two weeks doing it. The budget was fixed and had been quoted before anyone looked at the state of the old data.

Result & impact

The first renewal window after go-live was handled by the same two staff with no overtime, and the manual reconciliation went from roughly three weeks of work to a report someone glances at on a Monday. About nine per cent of members who would have lapsed silently renewed after the automated reminders, which covered the cost of the project inside the first year. Duplicate payments went to almost nothing because members could finally see their own status. I handed over to their in-house developer across two weeks of pairing and he has maintained it since, including features I would not have thought to build.

Who else worked on it

The business analyst wrote the rules the state machine encodes and caught at least four cases I had modelled wrong, including how grace periods work for members on parental leave. The junior developer built most of the member-facing screens with me reviewing, then took the whole system over. The membership officer sat with us for two afternoons and narrated a year of her job, which was the most useful requirements session I have ever been in.