Library / SDK
googleapis/google-cloud-rust avatar
googleapis/google-cloud-rust

google-cloud-rust: generated clients, hand-written crates, and what breaks between them

Google Cloud Rust Client Libraries

963 stars153 forksRustApache-2.0

At a glance

What is it?
The google-cloud-rust repository packages Rust client libraries for Google Cloud services, mixing hand-written crates with code generated from service specifications, and it publishes an explicit stability policy for each of those two very different kinds of code.
Who is it for?
Adopt google-cloud-rust when you want first-party Rust bindings for BigQuery, Spanner, Pub/Sub, Storage, Firestore, Datastore, or Bigtable and can live with a generated API surface that may shift on a service specification change. Do not adopt it if your project pins an old Rust toolchain, needs a stable async iterator API without the unstable-streams feature, or depends on symbols that live in google-cloud-gax-internal.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Generated crates and hand-written crates share one Cargo workspace

The root Cargo.toml of google-cloud-rust declares a workspace with resolver = "3" and a long default-members list. The names reveal the structure of the library: src/auth, src/bigquery, src/bigtable, src/datastore, src/firestore, src/gax, src/gax-internal, src/lro, src/pubsub, src/spanner, src/storage, and src/wkt sit alongside a src/generated tree that holds paths such as src/generated/cloud/language/v2, src/generated/cloud/secretmanager/v1, src/generated/cloud/speech/v2, and src/generated/cloud/workflows/v1.

That split is the single most important fact about the project, because the two families behave differently. The README states that many of the crates are automatically generated from the service specification, and that from time to time those specifications may introduce breaking changes. A hand-written crate such as the storage or bigquery client is shaped by hand and can be held to a stable promise, while a generated crate inherits whatever the service team publishes in the spec.

The workspace also lists a large set of test crates, including tests/integration, tests/integration-auth, tests/lro, tests/o11y, tests/protobuf, tests/openapi, tests/pubsub, and tests/endurance. These are workspace members rather than a separate test binary, which means cargo test at the root exercises a meaningful slice of the library.

The alternative to a generated client is a hand-rolled REST client

The realistic alternative to using this repository is to skip it and write the HTTP layer yourself. The difference in approach is not really about which one has more features. A hand-rolled client means you pick an HTTP crate, build the request signing and token refresh yourself, map response fields into your own structs, and then maintain that mapping every time the service adds or renames a field. Nothing gets regenerated for you, and nothing breaks when a spec changes, but the work never ends either.

google-cloud-rust takes the opposite bargain. You accept a code generator upstream of you, so the field mapping is refreshed on a schedule, and you accept that a spec change can move your public API out from under a minor version bump. The repository keeps a librarian.yaml at the root, a tools/ directory, and scripts/ and ci/ directories, which is what you would expect from a pipeline where the code is produced from an upstream description rather than typed by hand.

For a service where you need exactly one endpoint and a custom retry policy, hand-rolling is cheaper. For a service you intend to use broadly, a generated surface with a stated breaking-change policy is the better trade.

Rust 1.91 is the floor, and raising it is never a breaking change

The project states a minimum supported Rust version of 1.91 and says it plans to update that floor periodically. There is a second commitment that matters more in practice: the development branch will always compile with the rustc versions released within the previous year.

The README is explicit that a change to the MSRV is not considered a breaking change. The stated reason is timing. The MSRV is only bumped after the rustc version has been end-of-life for a while, and therefore out of support itself. So the sequence is predictable: a Rust release reaches end of life, the floor moves after that point, and the move arrives without a major version bump for the crates.

Two other categories are also excluded from the breaking-change definition. Changes to the dependencies of the libraries, and changes to the features enabled in those dependencies, are not treated as breaking. The README gives the practical instruction that follows from that: you should add any dependencies to your application directly, and enable any non-default features of these dependencies explicitly. If you rely on a transitive dependency or an implicit feature flag, an upgrade of the client library can change behaviour underneath you without any version signal on the client crate itself.

Semver holds after 1.0, but a generated spec can still move

The versioning promise is a conditional one. The project says it will make every effort to avoid breaking changes once a library reaches 1.0. The qualifier matters: the effort is applied to hand-written surface, and the README immediately notes that many crates are automatically generated, where upstream specifications may introduce breaking changes from time to time.

How those breaks are handled is spelled out. The project uses tooling to detect them, and when a breaking change is detected it bumps the major version, or the minor version for crates still at 0.x. That is a workable model for consumers on Cargo, since Cargo.lock and semver-compatible ranges will pick up patch and minor releases automatically but hold you back at a major boundary.

The practical reading is that a major bump in a generated crate signals a service specification change rather than a redesign by the library authors. If a generated crate you use reaches 1.0, you can expect the major version to move when the spec moves, so plan for that upgrade as a routine one rather than an incident.

google-cloud-gax-internal can change without notice

One crate in the workspace has an explicit warning attached to it. The README describes google-cloud-gax-internal as holding internal-only types, chief among them all the symbols that crate exports, and states that no application should take a direct dependency on it or use its types in its code. The project reserves the right to make changes to it without notice, and its major version will be 0.x for the foreseeable future while its minor version may change without notice.

Two related escape hatches exist elsewhere in the crates. Any public symbol that is not part of the public API carries the #[doc(hidden)] attribute, which is the conventional Rust signal that a symbol is off limits and may change without a major version bump. The project also uses crate features prefixed with _internal-, none of which are intended for application developers. Those features may change without notice as well, though the stated intention is to raise the major version of the corresponding library when they do.

The practical rule is that anything reaching for these symbols is outside the contract. In a large codebase this is where upgrades hurt, since a helper function that quietly depends on a hidden type turns a dependency bump into your own compile failure.

unstable-streams covers the async iterator gap Rust still has

Rust does not have a stable API for asynchronous iterators, also known as asynchronous streams, and the project works around that in a specific way. Where needed, the libraries provide implementations of the futures::stream::Stream trait rather than a native async iterator.

The functionality is gated behind a crate feature named unstable-streams. The naming is deliberate. The README says that when Rust stabilizes the streams trait, the project may choose to rename the feature, and may even need to change the trait implementation. In other words, enabling the feature buys you streaming pagination today at the cost of accepting that the surface may be renamed or rewritten once the language catches up.

This is worth planning around before you write a consumer loop. If your application code is generic over a stream, or if you have a policy of avoiding unstable features, then the paginated list calls in these libraries need a different shape, and the README does not document a stable replacement. The bounded option is to request pages explicitly instead of depending on the streaming API.

Your first client starts in the user guide, not in this repository

The README itself does not give an install command or a first snippet, and it does not pretend to. It points to the User Guide, hosted at googleapis.github.io/google-cloud-rust, which it describes as holding basic tutorials for getting started with the Google Cloud client libraries for Rust. The project homepage sits at docs.cloud.google.com/rust. For contributors rather than consumers, the README points at CONTRIBUTING.md, the set up development environment guide under doc/contributor, and ARCHITECTURE.md.

If you want to see the shape of the library before writing anything, the workspace file answers more than the prose does. Opening Cargo.toml at the root shows the members that make up the library:

toml
[workspace]
resolver = "3"

default-members = [
  "guide/samples",
  "src/auth",
  "src/bigquery",
  "src/bigquery-derive",
  "src/bigtable",
  "src/datastore",
  "src/firestore",
  "src/gax",
  "src/gax-internal",
  "src/lro",

That list is also the fastest way to tell which services have hand-written clients and which ones you will find only under src/generated. Note the guide/samples entry, which indicates that the tutorials live as sample crates inside the workspace rather than as separate code snippets in a document.

Apache 2.0, a last push on 2026-10-19, and the cost of moving with a spec

The repository is licensed under Apache 2.0, with the full text in the LICENSE file. That licence is permissive and requires that notices and the licence text travel with redistribution; the other file in the root that matters for consumers is SECURITY.md, which is where vulnerability reporting for the libraries is described. Nothing in the licensing terms changes the fact that the API surface is generated, so a copyleft-style reciprocal obligation does not arise from linking these crates into a service.

On activity, the last push was on 2026-10-19, and the recent releases are named by date rather than by version, with release-20260930, release-20260924, and release-20260826 appearing in sequence. Date-based release names make the cadence visible in the tag list, and they also mean you cannot read a semver story from the tag itself for the repository as a whole, only from the individual crates.

The upgrade cost falls on two shoulders. Hand-written crates give you a normal semver contract. Generated crates give you a semver contract with the upstream service specification attached, so the change that matters to you can arrive without a change in your code. The presence of Cargo.lock, a pinned rust-toolchain.toml, deny.toml for dependency policy, and a codecov.yml tells you the project expects careful pinning on the consumer side too.

Editorial conclusion

Adopt google-cloud-rust when you want first-party Rust bindings for BigQuery, Spanner, Pub/Sub, Storage, Firestore, Datastore, or Bigtable and can live with a generated API surface that may shift on a service specification change. Do not adopt it if your project pins an old Rust toolchain, needs a stable async iterator API without the unstable-streams feature, or depends on symbols that live in google-cloud-gax-internal. Verify three things before the first pull: that your rustc meets the 1.91 floor, that the crate you need is hand-written rather than generated, and that your lockfile and rust-toolchain.toml are set up to move with the release tags such as release-20260930.

Frequently asked questions

What Rust version do I need to build the google-cloud-rust client libraries?

The project requires Rust >= 1.91. It also states that the development branch always compiles with the rustc versions released within the previous year, and that the MSRV is only raised after the rustc version has been end-of-life.

Are google-cloud-rust crates semver stable after version 1.0?

The project says it will make every effort to avoid breaking changes once a library reaches 1.0, and that tooling is used to detect breaking changes coming from generated service specifications. When a breaking change is detected, it bumps the major version, or the minor version for crates still at 0.x.

Why should I not depend on google-cloud-gax-internal directly?

The README states that the crate holds internal-only types, that no application should take a direct dependency on it, and that the project reserves the right to change it without notice. Its major version stays at 0.x and its minor version may change without notice.

How do I stream paginated results from a google-cloud-rust client?

Rust has no stable API for asynchronous iterators, so the libraries implement futures::stream::Stream instead and gate that functionality behind the unstable-streams crate feature. The project warns that the feature may be renamed or the trait implementation changed once Rust stabilizes the streams trait.

Where do I find the tutorials for using google-cloud-rust?

The README points to the User Guide at googleapis.github.io/google-cloud-rust for basic tutorials, and the project homepage is docs.cloud.google.com/rust. Sample crates also live in the workspace under guide/samples, listed as a default member of the root Cargo.toml.

Official sources

  1. googleapis/google-cloud-rust on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/googleapis-google-cloud-rust.svg)](https://hysenlabs.com/projects/googleapis-google-cloud-rust)

Was this useful?