Rescuing a Stalled Loyalty Platform with JSON:API and CI/CD
Executive Summary: A loyalty startup’s in-house build had been stuck for months with no working product. I put together a small team, chose the JSON:API specification over hand-documented REST, required tests for every change and automated delivery to the mobile side. The product was largely rewritten, reached about 20,000 active users in 9–10 months, and the team ended up running and deploying it without me.
Context
In 2016 a loyalty startup, where users earned points when they shopped, had been building its product in-house for months. There was no working product, and the developers on it had never taken one to release. The founder asked me to get it moving.
The engagement was contracted through my company. I worked at the client’s office and my team worked remotely. I was responsible for the result: a working product, and a way of building it that would keep working after me.
The main client of the API was a mobile app, and its developer needed an interface that was predictable and documented.
Decision
A team of my own. I hired two backend developers and outsourced the UI and UX design to a designer I had worked with before and trusted.
JSON:API instead of hand-built REST. On Rails, designing, maintaining and documenting REST endpoints by hand would have been a heavy load for a small team. I also looked at GraphQL, which was still young in 2016. JSON:API made integration easier, and it was easier to understand for everyone involved, the mobile team most of all. Before settling the schema, I sat down with the mobile developer, listened to what the app needed and shaped the schema around it.
Tests for every change, delivery on every pass. Every piece of code came with tests, and the API was documented properly. I set up CI/CD so that code that passed the tests went out to the mobile side automatically.
Learning by doing. Later, developers from another of the founder’s ventures joined the team. They had not worked with tests, CI/CD or linters before, and most of the reading material was in English, which not everyone read comfortably. Instead of waiting until they felt ready, I gave them work in a set order: RuboCop warnings first, which are small and quick and got them into the code on the first day; then the missing tests; then features.
Consequences
- Positive: The stalled project became a predictable delivery line. Once releases could be planned, marketing could plan campaigns around them, and the product went from zero to about 20,000 active users in 9–10 months.
- Positive: The two groups of developers became one team working to the same standards. The team could run and deploy the product on its own, and I moved to management and planning.
- Negative / Cost: The product was largely rewritten, so little of the earlier months of work carried over.
- Negative / Cost: Every client had to follow one specification’s document format, including its conventions for relationships and includes.
When to revisit
If clients need deeply nested or very different data in a single request, JSON:API’s fixed document shape leads to over-fetching or extra round trips, and GraphQL is worth another look. The same applies when the API serves many clients with different needs instead of one mobile app.
This case note is an anonymized Architecture Decision Record (ADR) from a real-world engagement.