Senne
Senne

Reputation: 183

How to handle database schema update in microservice

We will start with this schema

CREATE TABLE [dbo].[Label]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [Prefix] VARCHAR(50) NOT NULL UNIQUE,
    [ArtistName] VARCHAR(MAX) NOT NULL
)

We also have a microservice that manages "Labels". http://labels.example.com/v1/all will return all labels in this format:

{ Id = xxx, Prefix = xxx, ArtistName = xxx }

How do we handle a schema change that does not affect consumers of this microservice?

We have to do some refactoring and the artist moves to his own table.

CREATE TABLE [dbo].[Label]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [Prefix] VARCHAR(50) NOT NULL UNIQUE,
    [ArtistId] UNIQUEIDENTIFIER NOT NULL,

    CONSTRAINT FK_Label_Artist
        FOREIGN KEY (ArtistId) REFERENCES Artist(Id)
)

CREATE TABLE [dbo].[Artist]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [Name] VARCHAR(MAX) NOT NULL,
    [Country] VARCHAR(MAX) NOT NULL
)

Our microservice will need to return the following object

{ Id = xxx, Prefix = xxx, Artist = { Id = xxx, Name = xxx, Country = xxx } }

We will have to create a v2 api call that returns this new structure. We will also have to migrate the data to the new structure. This means v1 needs a change as well to support the new schema, but it will still return the same object.

Is this the way things are done when you version a microservice? Things to keep in mind? Is there a different way to do this?

Upvotes: 6

Views: 3287

Answers (2)

Oswin Noetzelmann
Oswin Noetzelmann

Reputation: 9545

It sounds like you are on the right track. The microservices architectural style was invented to allow organizations to build logically separated development teams with clearly defined interfaces. The interfaces being the service API or whatever else is exposed to consumers.

The database schema should be service internal and thus develop over time as part of your regular development process. Only if there is an impact to your service consumers (by changing the service interface) you have to make sure there is a formal versioning process.

The formal process should include all aspects that apply to external dependencies as well. You can take facebook as an example, as they release new versions of their public APIs and obsolete old ones after a while. You should have a similar process of notifying your consumers early upfront with a timeline, then deploying both old and new service versions in parallel to give your consumers time to adopt and finally retiring the old service. While you run both services in parallel you should monitor the traffic to both and send your consumers reminders if the traffic is not switching over time.

So in short - treat your internal dependencies like you would do with external dependencies.

Some additional thoughts:

  • Extending is easier than modifying: Sometimes you get away with extending data structures that an API returns without breaking the existing consumers. In your example that could mean to return a structure like the following:

    { Id = xxx, Prefix = xxx,  ArtistName = xxx, Artist = { Id = xxx, Name = xxx, Country = xxx } }
    

    Here you would pay with a redundancy in data for keeping the compatibility.

  • You should only change so often: It is usually better to accumulate a lot of changes in a single version upgrade, rather than upgrade often with little changes.

  • You can use a version schema to indicate breaking changes: For example minor version change 1.1 is compatible with version 1.0 but major version change 2.0 is not compatible with 1.1.

  • Client adapters: Sometimes APIs come with client libraries to make access even easier and independent of transport format etc. In this case the client library needs to be versioned correctly as well and should support all active versions.

  • Tools: Have a look into standards like GraphQL that help with a lot of the API related tasks.

Upvotes: 7

Rob Conklin
Rob Conklin

Reputation: 9446

There are several ways to do this, the most "correct" way that I've found is to use media types so that the client can specify which version it is expecting back. This will allow the implementing rest service to back-port the data-structures such that the old version can still be used. This presupposes that this is not a breaking change, which would require a who

Upvotes: 0

Related Questions