Install & Compatibility
Where this runs
tested against v1.20.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.95 runs
installs and imports cleanly · install 0.0s · import 0.704s · 113.5MB
glibcpy 3.10–3.95 runs
installs and imports cleanly · install 9.3s · import 0.610s · 109MB
113MB installed
● package 113MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
create_engine
✓ from sqlalchemy import create_engine
The Spanner dialect is typically loaded via the connection string, not direct import of a dialect class.
This quickstart demonstrates how to establish a connection to a Google Cloud Spanner database, define a table, insert data, and query it using the SQLAlchemy ORM. Ensure you have a GCP project, Spanner instance, and database set up, and that your application has appropriate authentication (e.g., via `GOOGLE_APPLICATION_CREDENTIALS`). The example shows direct DDL for table creation, as DDL is not transactional in Spanner.
import os
from sqlalchemy import create_engine, text, MetaData, Table, Column, String, Integer
# Set these environment variables or replace directly
project_id = os.environ.get('SPANNER_PROJECT_ID', 'your-gcp-project-id')
instance_id = os.environ.get('SPANNER_INSTANCE_ID', 'your-spanner-instance-id')
database_id = os.environ.get('SPANNER_DATABASE_ID', 'your-spanner-database-id')
# For SQLAlchemy 1.4+ and 2.0, use 'spanner+spanner:///'
# For SQLAlchemy 1.3, use 'spanner:///'
db_url = f"spanner+spanner:///projects/{project_id}/instances/{instance_id}/databases/{database_id}"
try:
engine = create_engine(db_url)
# Example: Define a table for demonstration
metadata = MetaData()
users = Table(
'users',
metadata,
Column('user_id', String(36), primary_key=True),
Column('name', String(255), nullable=False),
Column('age', Integer)
)
# Create tables (DDL operations are not transactional in Spanner)
with engine.connect() as connection:
connection.execute(text("CREATE TABLE IF NOT EXISTS users (user_id STRING(36) NOT NULL, name STRING(255) NOT NULL, age INT64) PRIMARY KEY (user_id)"))
connection.commit()
print("Table 'users' ensured.")
# Insert data
with engine.begin() as connection:
connection.execute(users.insert(), {"user_id": "user1", "name": "Alice", "age": 30})
connection.execute(users.insert(), {"user_id": "user2", "name": "Bob", "age": 24})
print("Data inserted.")
# Query data
with engine.connect() as connection:
result = connection.execute(users.select().where(users.c.age > 25)).fetchall()
print("Users older than 25:", result)
except Exception as e:
print(f"An error occurred: {e}")
print("Ensure Cloud Spanner project, instance, and database are correctly configured and `GOOGLE_APPLICATION_CREDENTIALS` is set or default credentials are available.")
Debug
Known issues
gotchaThe database URL format for `sqlalchemy-spanner` differs between SQLAlchemy 1.3 and 1.4+/2.0. For SQLAlchemy 1.3, use `spanner:///...`. For SQLAlchemy 1.4+ and 2.0, use `spanner+spanner:///...`.fixAdjust the connection string based on your SQLAlchemy version. E.g., `create_engine("spanner+spanner:///projects/...")` for newer SQLAlchemy versions. affects: <1.4.0 (for older URL style)
gotchaCloud Spanner does not support DDL (Data Definition Language) statements within transactions. Any DDL operations performed will not be rolled back upon transaction failure.fixBe mindful that DDL statements are implicitly committed and irreversible in the context of a transaction. Consider using `connection.execute(text('DDL_STATEMENT'))` followed by `connection.commit()` outside of explicit transaction blocks for DDL. affects: All
gotchaThe dialect and the underlying DB API driver do not support Spanner mutations directly; only DML (Data Manipulation Language) statements are supported for updates.fixUtilize SQLAlchemy's ORM or Core DML statements (INSERT, UPDATE, DELETE) which are translated into Spanner-compatible DML.
affects: All
gotchaWhen using Alembic for migrations, setting `version_table_pk` to `False` in your Alembic environment configuration is highly recommended to avoid issues with Spanner's primary key restrictions on the `alembic_versions` table.fixIn your `env.py` or Alembic configuration, ensure `version_table_pk = False` for Spanner migrations.
affects: All
gotchaThe `sqlalchemy-spanner` dialect is currently synchronous only. There is no official asynchronous dialect available, which can be a blocker for projects requiring an async engine with SQLAlchemy 2.0+'s async features.fixConsider using thread pools or synchronous execution within an async application, or explore third-party async wrappers. A native async SpannerSessionService is a feature request for the underlying `google-cloud-spanner` client.
affects: All
gotchaUsing `autoload=True` with `MetaData` in a highly concurrent environment can lead to `sqlalchemy.exc.CompileError: Unconsumed column names` due to race conditions during table reflection. It's an anti-pattern to reflect tables on every statement.fixReflect all necessary `Table` objects upfront, once, before your program begins processing requests, rather than dynamically reflecting them within hot code paths.
affects: All
gotchaThe dialect does not currently propagate the `timeout` execution option to the underlying gRPC client, causing all queries to use the default gRPC timeout of 3600 seconds regardless of `execution_options(timeout=...)`.fixBe aware of the default long timeout. For specific timeout control, you may need to apply it at the underlying `google-cloud-spanner` client level if direct access is available, or await a future update to the dialect.
affects: All current versions (as of 1.17.3)
breakingThe `sqlalchemy-spanner` dialect relies on Google Cloud Application Default Credentials (ADC) or explicit credentials (e.g., via `GOOGLE_APPLICATION_CREDENTIALS`) to authenticate with Spanner. Without proper authentication, connection attempts will fail.fixSet up Application Default Credentials (ADC) in your environment (e.g., `gcloud auth application-default login` if using the gcloud CLI) or ensure the `GOOGLE_APPLICATION_CREDENTIALS` environment variable points to a valid service account key file. Consult Google Cloud's authentication documentation for detailed setup instructions: https://cloud.google.com/docs/authentication/external/set-up-adc
affects: All
gotchaThe `sqlalchemy-spanner` dialect, like all Google Cloud client libraries, requires Application Default Credentials (ADC) to authenticate. If not configured, you will encounter 'Your default credentials were not found' errors.fixEnsure Application Default Credentials are set up in your environment. Refer to `https://cloud.google.com/docs/authentication/external/set-up-adc` for guidance. This typically involves setting the `GOOGLE_APPLICATION_CREDENTIALS` environment variable to the path of a service account key file or authenticating via `gcloud auth application-default login`.
affects: All
Errors
Common errors & fixes
sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:spanner
The `sqlalchemy-spanner` package is not installed or not accessible in the current Python environment, preventing SQLAlchemy from finding the 'spanner' dialect.
fixpip install sqlalchemy-spanner
sqlalchemy.exc.OperationalError: (google.api_core.exceptions.NotFound: 404 Not found: projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID)
The Spanner project, instance, or database specified in the connection string does not exist, or the authenticated service account/user lacks the necessary IAM permissions to access it.
fixVerify the project ID, instance ID, and database name in your connection string are correct, and ensure the authenticated user or service account has appropriate IAM roles (e.g., `roles/spanner.databaseUser`) for the Spanner resource.
sqlalchemy.exc.CompileError: Spanner does not support auto-incrementing primary keys.
Cloud Spanner does not natively support auto-incrementing integer primary keys, and the `sqlalchemy-spanner` dialect prevents their definition in SQLAlchemy models.
fixRemove `autoincrement=True` from primary key column definitions; instead, generate unique primary key values client-side (e.g., using UUIDs) before insertion, or configure Spanner's `GENERATE AS ROW ID` for `BYTES(16)` primary keys.
sqlalchemy.exc.CompileError: Spanner does not support the RETURNING clause.
The `sqlalchemy-spanner` dialect does not support the `RETURNING` clause in `INSERT` or `UPDATE` statements, as Cloud Spanner DML does not provide immediate return of affected rows or generated values.
fixRemove the `.returning()` clause from your SQLAlchemy `insert()` or `update()` statements. If you need generated IDs, generate them client-side before insertion or query the table separately afterward.
Upgrade
Version history
1.20.0latest on PyPI · released Aug 25, 2026
Audit
Dependencies
SQLAlchemyrequiredThis package provides a dialect for SQLAlchemy, requiring SQLAlchemy itself. Compatible with SQLAlchemy 1.x (>=1.1.13) and 2.0.
google-cloud-spannerrequiredThe dialect is built on top of the Google Cloud Spanner DB API (PEP-249 compliant).
AlembicoptionalRecommended for database migrations with SQLAlchemy and Spanner.