Skip to content

Latest commit

 

History

History
2632 lines (2407 loc) · 47.4 KB

report.md

File metadata and controls

2632 lines (2407 loc) · 47.4 KB

Schema Evolution Compatibility

Generated on 2022-11-16T17:32:07.993486

Summary

Backwards Compatibility

Forwards Compatibility

Full Compatibility

Backwards Compatibility

Forwards Compatibility

Full Compatibility

Backwards Compatibility

Forwards Compatibility

Full Compatibility

Details

Avro

Backwards Compatibility

A new schema is backward compatible if it can be used to read the data written in the previous schema.

Add optional field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

Delete optional field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Delete required field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Make required field optional

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

Make optional field required

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

Rename field with alias

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1_new",
      "type": "string",
      "aliases": ["f1"]
    }
  ]
}

Make non-nullable field nullable

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

Add type to union

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string", "int"]
    }
  ]
}

Changes that break Backwards Compatibility

Add required field (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

Make nullable field non-nullable (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Remove type from union (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string", "int"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

Forwards Compatibility

A new schema is forward compatible if the previous schema can read data written in this schema.

Add optional field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

Delete optional field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Add required field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

Make required field optional

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

Make optional field required

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

Make nullable field non-nullable

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Remove type from union

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string", "int"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

Changes that break Forwards Compatibility

Delete required field (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Rename field with alias (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1_new",
      "type": "string",
      "aliases": ["f1"]
    }
  ]
}

Make non-nullable field nullable (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

Add type to union (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string", "int"]
    }
  ]
}

Full Compatibility

A new schema is fully compatible if it's both backward and forward compatible.

Add optional field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

Delete optional field

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Make required field optional

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

Make optional field required

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string",
      "default": "foo"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

Changes that break Full Compatibility

Add required field (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

Delete required field (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    },
    {
      "name": "f2",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Rename field with alias (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1_new",
      "type": "string",
      "aliases": ["f1"]
    }
  ]
}

Make non-nullable field nullable (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

Make nullable field non-nullable (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": "string"
    }
  ]
}

Add type to union (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string", "int"]
    }
  ]
}

Remove type from union (not permitted)

V1

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string", "int"]
    }
  ]
}

V2

{
  "namespace": "test",
  "name": "myrecord",
  "type": "record",
  "fields": [
    {
      "name": "f1",
      "type": ["null", "string"]
    }
  ]
}

Protocol Buffers

Backwards Compatibility

A new schema is backward compatible if it can be used to read the data written in the previous schema.

Add Field

V1

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

V2

syntax = "proto3";
message Example {
  optional string f1 = 1;
  optional string f2 = 2;
}

Delete Field

V1

syntax = "proto3";
message Example {
  optional string f1 = 1;
  optional string f2 = 2;
}

V2

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

Rename Field Number

V1

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

V2

syntax = "proto3";
message Example {
    optional string f2 = 1;
}

Changes that break Backwards Compatibility

(none)

Forwards Compatibility

A new schema is forward compatible if the previous schema can read data written in this schema.

Add Field

V1

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

V2

syntax = "proto3";
message Example {
  optional string f1 = 1;
  optional string f2 = 2;
}

Delete Field

V1

syntax = "proto3";
message Example {
  optional string f1 = 1;
  optional string f2 = 2;
}

V2

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

Rename Field Number

V1

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

V2

syntax = "proto3";
message Example {
    optional string f2 = 1;
}

Changes that break Forwards Compatibility

(none)

Full Compatibility

A new schema is fully compatible if it's both backward and forward compatible.

Add Field

V1

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

V2

syntax = "proto3";
message Example {
  optional string f1 = 1;
  optional string f2 = 2;
}

Delete Field

V1

syntax = "proto3";
message Example {
  optional string f1 = 1;
  optional string f2 = 2;
}

V2

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

Rename Field Number

V1

syntax = "proto3";
message Example {
    optional string f1 = 1;
}

V2

syntax = "proto3";
message Example {
    optional string f2 = 1;
}

Changes that break Full Compatibility

(none)

JSON Schema

Backwards Compatibility

A new schema is backward compatible if it can be used to read the data written in the previous schema.

Delete optional field (open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Add optional field (closed content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add optional field (closed to open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

Make required field optional (closed content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": []
}

Delete optional field (closed to open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (closed to open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Changes that break Backwards Compatibility

Add optional field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

Add required field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1", "f2"]
}

Add optional field (open to closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add required field (open to closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

Delete optional field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Delete required field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add required field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

Make optional field required (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": []
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Forwards Compatibility

A new schema is forward compatible if the previous schema can read data written in this schema.

Add optional field (open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

Add required field (open content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1", "f2"]
}

Add optional field (open to closed content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add required field (open to closed content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

Delete optional field (closed content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Make optional field required (closed content model)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": []
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Changes that break Forwards Compatibility

Delete optional field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Add optional field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add optional field (closed to open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

Make required field optional (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": []
}

Delete optional field (closed to open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (closed to open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add required field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

Full Compatibility

A new schema is fully compatible if it's both backward and forward compatible.

Changes that break Full Compatibility

Delete optional field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Add optional field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

Add required field (open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1", "f2"]
}

Add optional field (open to closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add required field (open to closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

Add optional field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add optional field (closed to open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "required": ["f1"]
}

Make required field optional (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": []
}

Delete optional field (closed to open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete required field (closed to open content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
"required": ["f1"]
}

Delete optional field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Delete required field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

Add required field (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"},
    "f2": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1", "f2"]
}

Make optional field required (closed content model) (not permitted)

V1

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": []
}

V2

{
  "type": "object",
  "properties": {
    "f1": {"type": "string"}
  },
  "additionalProperties": false,
  "required": ["f1"]
}