Hacker News new | ask | show | jobs
by kgeist 1609 days ago
>The golden rule is to never break API backwards compatibility. If you must, create a new version of the API and leave the old version functional

It also helps with zero-downtime deployments:

1) spawn a new instance of the service with the new API, side by side with the old one

2) now incoming traffic (which still expects the old API) is routed to the new instance with the new API, and it's OK, because it's backward-compatible

3) shut down the old instance

4) eventually some time later all clients are switched to the new API, we can delete the old code

1 comments

How can accumulation of versions be prevented? Now the same team has to maintain two products, and the underlying mechanism is still limited by the older version.

Anecdotally, a robust backward-compatibility has been seen as a hinderance to e.g. Java's progress (so much that a newer language, Kotlin, was created to break free from that burden).

There isn't really a solution to version bloat aside from good processes and general diligence. There's no easy way to handle that sort of thing, unfortunately.

However, I do think it can be easier to deal with for internal services then for something like Java. When the number of users is in the dozens rather then the millions, it's a lot easier to make sure everyone gets moved over to the new version.

That's what makes the whole idea of microservices seems weird to me. If a functionality has merit on its own (e.g. an authentication service), then it will naturally fall outside of the main application. If a service is tightly coupled to other parts of the app, then microservices seems like intentionally hindering yourself: the coupling remains (as evident by the need for backward compatibility), but now we it's harder to keep everything aligned due to the extra separation (e.g. different code bases, multiple databases, no static validation of remote interfaces etc.).

The point of organizations and products is to work as a tightly coordinated machine. The decoupling that microservices create seems opposite to that goal.

Happy to hear different perspectives.

I agree that tightly coupled modules should live inside the same deployment, but:

>it's harder to keep everything aligned due to the extra separation (e.g. different code bases, multiple databases, no static validation of remote interfaces etc.)

It's solvable with appropriate tooling. I.e. you can store API definitions in a separate repository and make the services or CI/CD check API usage is valid at build time.

>tightly coordinated machine

What do you mean by that? For example, we have 10 teams all developing different features in parallel, with a tight release schedule. If there was tight coordination for every change, we'd degrade to a waterfall on the scale of the whole organization. Major API changes are discussed in advance during P/I planning; for minor changes, it's a matter of simply notifying other teams "hey, add this to your backlog, please" (we enforce backward compatibility for zero downtime anyway, so it's not urgent)

> It's solvable with appropriate tooling. I.e. you can store API definitions in a separate repository and make the services or CI/CD check API usage is valid at build time. Makes sense, though it feels somewhat like re-inventing the wheel (same-codebase tooling are generally easier and faster to use).

> What do you mean by that? Data and workflow have to be unified across the company's products to provide the user with a seamless experience. As above, to me this seems may contradict some components of microservices like splitting the database, since one ends up with the same constraints (synchronization, shared schema) while complicating the orchestration (since now cross-system integration is needed).

Sure, something like Reddit or HN can break the unified experience, but any important or productivity system will greatly suffer from such fragmentation. I assume it can be achieved with micro-services, but it seems somewhat harder.

One way is to rewrite version N endpoints to use version N+1 endpoints. You just need to ensure clients can handle null/empty data so that when some requested data is depreciated, you don't break old apps. The increased latency from N conversion calls also encourage the oldest clients to migrate without breaking backwards comparability.
Well we usually coordinate between the teams. I.e. we don't force other teams to make changes as soon as possible (they have their own plans) but we agree to add relevant changes to their backlog, so that it was fixable in a 1-2 month window.
You need to talk to the other teams. Usually the change isn’t so drastic, I often made the change myself in the other teams service and sent them a review.