Skip to content

Singleton resources

APIs sometimes need to represent a resource where exactly one instance of the resource always exists within any given parent. A common use case for this is for a config object.

Guidance

An API may define singleton resources. A singleton resource must always exist by virtue of the existence of its parent, with one and exactly one per parent.

For example:

message Config {
option (google.api.resource) = {
type: "api.example.com/Config"
pattern: "users/{user}/config"
};
// additional fields including name
}

The Config singleton would have the following RPCs:

rpc GetConfig(GetConfigRequest) returns (Config) {
option (google.api.http) = {
get: "/v1/{name=users/*/config}"
};
}
rpc UpdateConfig(UpdateConfigRequest) returns (Config) {
option (google.api.http) = {
patch: "/v1/{config.name=users/*/config}"
body: "config"
};
}
  • Singleton resources must not have a user-provided or system-generated ID; their resource name includes the name of their parent followed by one static-segment.
    • Example: users/1234/config
  • Singleton resources are always singular.
    • Example: users/1234/thing
  • Singleton resources may parent other resources.
  • Singleton resources must not define the Create or Delete standard methods. The singleton is implicitly created or deleted when its parent is created or deleted.
  • Singleton resources should define the Get and Update methods, and may define custom methods as appropriate.
    • However, singleton resources must not define the Update method if all fields on the resource are output only.
  • Singleton resources may define the List method, but must implement it according to AEP-159. See the example below.
    • The trailing segment in the path pattern that typically represents the collection should be the plural form of the Singleton resource e.g. /v1/{parent=users/*}/configs.
    • If a parent resource ID is provided instead of the hyphen - as per AEP-159, then the service should return a collection of one Singleton resource corresponding to the specified parent resource.
rpc ListConfigs(ListConfigsRequest) returns (ListConfigsResponse) {
option (google.api.http) = {
get: "/v1/{parent=users/*}/configs"
};
}
message ListConfigsRequest {
// To list all configs, use `-` as the user id.
// Formats:
// * `users/-`
// * `users/{user}`
//
// Note: Specifying an actual user id will return a collection of one config.
// Use GetConfig instead.
string parent = 1 [
(google.api.resource_reference).child_type = "api.example.com/Config"];
// other standard pagination fields...
}

Rationale

Support for Standard List

While Singleton resources are not directly part of a collection themselves, they can be viewed as part of their parent’s collection. The one-to-one relationship of parent-to-singleton means that for every one parent there is one singleton instance, naturally enabling some collection-based methods when combined with the pattern of Reading Across Collections. The Singleton can present as a collection to the API consumer as it is indirectly one based on its parent. Furthermore, presenting the Singleton resource as a pseudo-collection in such methods enables future expansion to a real collection, should a Singleton be found lacking.