Resource Revisions
Some APIs need to have resources with a revision history, where users can reason about the state of the resource over time. There are several reasons for this:
- Users may want to be able to roll back to a previous revision, or diff against a previous revision.
- An API may create data which is derived in some way from a resource at a given point in time. In these cases, it may be desirable to snapshot the resource for reference later.
Guidance
APIs may expose a revision history for a resource. Examples of when it is useful include:
- When it is valuable to expose older revisions of a resource via an API. This can avoid the overhead of the customers having to write their own API to store and enable retrieval of revisions.
- Other resources depend on or descend from different revisions of a resource.
- There is a need to represent the change of a resource over time.
APIs implementing resources with revisions must model resource revisions as a subresource of the resource.
-
The
message
must be annotated as a resource (AIP-123). -
The
message
name must be named{ResourceType}Revision
.
- The resource revision must contain a field with a message type of the
parent resource, with a field name of
resource
.- The value of
resource
must be the original resource at the point in time the revision was created.
- The value of
- The resource revision must contain a
create_time
field (see [AIP-142][]). - The resource revision may contain a repeated field
aliases
, which would contain a list of resource IDs that the revision is also known by (e.g.latest
)
Creating Revisions
Depending on the resource, different APIs may have different strategies for creating a new revision. Specifically examples of strategies include:
- Creating a revision when there is a change to the resource
- Creating a revision when important system state changes
- Creating a revision when specifically requested
APIs may use any of these strategies or any other strategy. APIs must document their revision creation strategy.
Resources that support revisions should always have at least one revision.
Resource names for revisions
When referring to the revisions of a resource, the subcollection name
must be revisions
. Resource revisions have paths with the format
{resource_path}/revisions/{resource_revision}
. For example:
The resource must be named {resource_singular}Revision
(for example, BookRevision
).
Server-specified aliases
Services may reserve specific IDs to be aliases (e.g.
latest
). These are read-only and managed by the service.
If specific IDs are reserved, services must document those IDs.
- If a
latest
ID exists, it must represent the most recently created revision. The content ofpublishers/{publisher}/books/{book}/revisions/latest
andpublishers/{publisher}/books/{book}
can differ, as the latest revision may be different from the current state of the resource.
User-specified aliases
APIs may provide a mechanism for users to assign an alias ID to an existing revision with a custom method “alias”:
- The request message must have a
path
field:- The field must be annotated as required.
- The field must identify the resource type that it references.
- The request message must have a
alias
field:- The field must be [annotated as required][aip-203].
- If the user calls the method with an existing
alias
withoverwrite
set to true, the request must succeed and the alias will be updated to refer to the provided revision. Ifoverwrite
is false, the request must fail with an error code ALREADY_EXISTS (HTTP 409).
Rollback
A common use case for a resource with a revision history is the ability to roll
back to a given revision. APIs that support this behavior should do so with
a Rollback
custom method:
- The method must use the
POST
HTTP verb. - The method should return a resource revision.
- The request message must have a
path
field, referring to the resource revision whose configuration the resource should be rolled back to.- The field must be [annotated as required][aip-203].
- The field must identify the [resource type][aip-123] that it references.
Child resources
Resources with a revision history may have child resources. If they do, they should be a subset of the descendants of the original resource, and a given revision’s descendants must be a subset of the descendants of the resource at the time the revision was created.
Standard methods
Any standard methods must implement the corresponding AIPs (AIP-131, AIP-132, AIP-133, AIP-134, AIP-135), with the following additional behaviors:
- List methods: By default, revisions in the list response should be ordered
in reverse chronological order. APIs may support the
order_by
field to override the default behavior. - If the revision supports aliasing, a delete method with the resource path
of the alias (e.g.
revisions/1.0.2
) must remove the alias instead of deleting the resource.
As revisions are nested under the resource, also see cascading delete.
Rationale
For the name “revision”
There was significant debate about what to call this pattern, with the following as proposed options:
- snapshots
- revisions
- versions
Among those, revision was chosen because:
- The term “version” is often used in multiple different contexts (e.g. API version), and using that noun here may result in confusion during conversations where it could mean one or the other.
- The term “snapshot” is also used for snapshots of datastores, which may not follow this pattern.
- The term “revision” does not have many conflicts with terms when describing an API or resource.
History
Switching from a collection extension to a subcollection
In aip.dev prior to 2023-09, revisions were more like extensions of an existing
resource by using @
symbol. List and delete revisions were custom methods on
the resource collection. A single Get method was used to retrieve either the
resource revision, or the resource.
Its primary advantage was allowing a resource reference to seamlessly refer to a resource, or its revision.
It also had several disadvantages:
- List revisions is a custom method (
:listRevisions
) on the resource. - Delete revision is a custom method on the resource.
- Not visible in API discovery documenation.
- Resource IDs cannot use the
@
symbol.
The guidance was modified ultimately to enable revisions to behave like a resource, which reduces users’ cognitive load and allows resource-oriented clients to easily list, get, create, update, and delete revisions.
Changelog
- 2024-08-09: Imported from aip.dev.