The beginning
We've been eagerly developing a service called qrop, aimed at farmers.
I'm primarily in charge of backend development, such as the API, and when we started building this service, we decided the API would be built with GraphQL.
At the time, there wasn't really a strong need for GraphQL specifically, and we didn't have anyone on the team who was deeply experienced with it either—the reasoning was more along the lines of "it'd be good to get some exposure to new technology."
While we were at it, we decided we might as well build it in Golang and run the infrastructure on GCP—packing in everything we wanted to try at the time—and that's how development got started.
As we learned these new technologies, there was a lot we didn't understand at first, and we often got stuck. Even so, the enjoyment of somehow piecing it all together outweighed the struggle, at least emotionally.
How we ended up deciding to migrate
At some point, though, I started to feel that continuing development this way might be difficult.
Since we do contract development work, each team member is generally involved in multiple projects at once. During periods when more resources were allocated to contract work, we sometimes ended up postponing development on our internal projects.
As a result, we weren't able to keep up with the technology or allocate tasks effectively as a team, and the time needed to implement the required features kept growing and growing.
Realizing that development costs would just keep ballooning if we continued this way, we decided to change our tech stack.
One reason for this decision was that, around the same time, development using OpenAPI on another project was working really well as a team.
- Schema-first API development with committee, OpenAPI, and Rails
- A rich client experience protected by auto-generated types, powered by OpenAPI Generator + TypeScript
Looking back
On the migration itself
Since the foundation for developing with Rails and OpenAPI was already well established on another project, we ran into almost no trouble rebuilding the API.
We prioritized the migration to the new API, which meant development on the existing GraphQL API came to a stop, but the migration itself was ultimately completed without any major issues.
Since I think this will let future development go more smoothly, I believe migrating was the right call.
Why things didn't go well
One factor was that the team wasn't able to fully commit to the project.
Understanding of the tech stack varied across the team, which also affected how tasks were assigned. On top of that, since the resources allocated to each person's projects shifted depending on the period, we weren't able to follow the development schedule we'd envisioned. We tried to secure a consistent amount of development resources, but I feel that catching up on the technology and aligning our understanding ended up taking up a large portion of our time.
We also hadn't clearly recognized just how much complexity the system would ultimately require.
If the functionality had stayed simple, I think we could have seen it through with GraphQL. But the features required of the system turned out to be more complex than I had originally anticipated, and making that a reality gradually became harder and harder.
This may be a common pitfall when adopting new technology, but I also think we were chasing an "ideal form" too hard.
There are all sorts of ideals out there—"this is how a GraphQL implementation should be," "this is how Golang development should be done," and so on. Pursuing these ideals isn't a bad thing in itself, but I felt that being too fixated on them can leave you unable to move forward. I think another cause was that, being unfamiliar with the tech stack, we weren't able to figure out where the right compromise was.
How we should approach adopting new technology
This time, as a team, we newly adopted GraphQL and other technologies, but honestly, I felt that maintaining development performance was difficult given the state we were in.
That said, there were good things too, like having deepened our understanding of GraphQL and the rest of the tech stack. If you look at it positively, even the experience of failure is something we gained.
When starting a new project, if you think purely in terms of efficiency, adopting whatever approach is already working well tends to be the right call in most cases—but at the same time, if you never consider new options, you can't expand your range either.
I think getting hands-on with new technology is important as an engineer, and honestly, I just find it fun. That said, I've come to realize once again—even though I thought I understood this—that there's a lot to think through when adopting a new technology.
- What does the development actually need?
- A sense of speed
- Complexity
- Stability
- Enjoyment
- How will the team commit to it?
- Securing development resources
- Where responsibility lies
I'm sure there's more to it than this, but I want to take this reflection to heart while still keeping an open attitude toward adopting new technology going forward.