How do you balance rapid iteration and merging/upgrading?
More specifically, I'm thinking about two different modes of development for a library (private to the company) that's already relied upon by other libraries and applications:
Rapidly develop the library "in isolation" without being slowed down by keeping all of the users in sync. This causes more divergence and merge effort the longer you wait to upgrade users.
Make all changes in lock-step with users, keeping everyone in sync for every change that is made. This will be slower and might result in wasted work if experimental changes are not successful.
As a side note: I believe these approaches are similar in spirit to the continuum of microservices vs monoliths.
Speaking from recent experience, I feel like I'm repeatedly finding that users of my library have built towers upon obsolete APIs, because there have been multiple phases of experimentation that necessitated large changes. So with each change, large amounts of code need to be rewritten.
I still think that approach #1 was justified during the early stages of the project, since I wanted to identify all of the design problems as quickly as possible through iteration. But as the API is getting closer to stabilization, I think I need to switch to mode #2.
How do you know when is the right time to switch? Are there any good strategies for avoiding painful upgrades?
I'd say the ideal thing to aim for is case 2-ish.
Building in isolation isn't great and dog-fooding your lib (via their projects) can help reduce the amount of future breaking changes (getting things right the first time). I.e. Ideally your helping people upgrade when needed and seeing their problems. Even if your forking their projects to try your experimental changes out for them and then provide a PR? That's probably a lot easier said than done though xD
A dependecy management system to let consumers know when a new version is available could go a long way, or you pushing for them to update by talking to them (as this is all internal?).
Basically reducing the distance between teams and getting the tightest possible feedback loops should be the goal.
That's my rushed 2p while waiting for a haircut anyway ;)