LocalCloud Local Spanner Dialects and Endpoints
Get started
local.cloud / agents
Read this page as Markdown ↗
local.cloud — Local Spanner Dialects and Endpoints .md Open tab
Browse documentation Spanner emulator features
Services Spanner emulator features

Spanner emulator feature reference

LocalCloud integrates an extended Cloud Spanner emulator. GoogleSQL and PostgreSQL dialects run through the Spanner API; dialect support does not imply complete SQL, transaction, graph, search, authorization, backup, or change-stream parity.

Connections and persistence

SurfaceCanonical valueBoundary
gRPC APISPANNER_EMULATOR_HOST=localhost:5386Use generated host ports and test the selected SDK/version.
REST gatewayhttp://localhost:5387REST / grpc-gateway, not PostgreSQL wire.
PostgreSQL dialectQueries through the Spanner APILocalCloud does not package PGAdapter; psql and pgJDBC need a separately configured adapter.
StateLevelDB rows and JSON metadata under /var/lib/localcloud/spanner-dataMounted storage is required for retained state; see the recovery limits below.

Use localcloud env for the actual mapped endpoints. Provision the instance, database, and schema before querying; a code example that refers to an uncreated database is not a complete quick start.

Current operation contract

For task-oriented examples, use the Spanner documented workflows. The reference below describes individual API areas.

Operation areaStatusBoundary
Native SQL, read, and streaming readSupportedNative ExecuteSql and ExecuteStreamingSql in both GoogleSQL and PostgreSQL dialects. StreamingRead and ExecuteStreamingSql stream whole rows with resume tokens at row boundaries. Unary ExecuteSql intentionally retains the emulator's rejection of change-stream queries. Full-text search (TOKENIZE_*, SEARCH, SNIPPET, SCORE), vector search (APPROX_* / ScaNN), and 13 graph algorithms (PageRank, ShortestPath, etc.) compute locally. Rows with TOKENLIST columns and PostgreSQL-dialect NUMERIC and JSONB values are kept in the data directory, so full-text and substring search also answer over rows written before a restart.
Sessions, transactions, and batch DMLSupportedSessions (including batch create and multiplexed), read-write, read-only and single-use transactions. SERIALIZABLE (default) and REPEATABLE_READ isolation. Conflicts follow wound-wait lock waits (--lock_wait_timeout_ms). Exclusive locks via SELECT ... FOR UPDATE and LOCK_SCANNED_RANGES=exclusive. Commit timestamps (PENDING_COMMIT_TIMESTAMP) and commit stats (mutation count). Deadlock aborts exactly one transaction. Unique indexes are re-checked at commit.
Partition query/read and batch writeSupportedPartitionRead, PartitionQuery, partitioned DML (including parameterized PostgreSQL statements), and BatchWrite are supported.
Instance, configuration, and instance-partition administrationSupportedInstance and instance-partition administration, custom instance configurations, and MoveInstance (metadata). List operations and instances support AIP-160 filter expressions.
Database administration and DDLSupportedDatabase creation, DDL execution for both GoogleSQL and PostgreSQL, drop protection (UpdateDatabase), ListDatabaseOperations, split points (AddSplitPoints persisted to SPANNER_SYS.USER_SPLIT_POINTS), and fine-grained access control database roles (CREATE/DROP ROLE, GRANT/REVOKE, ListDatabaseRoles).
Instance and database IAM policiesSupportedIAM policies are stored durably in LevelDB and returned through native endpoints with etags guarded. Fine-grained access control (FGAC) is enforced for sessions created with a creator_role on queries, DML, reads, mutations, and change stream reads. Unauthenticated emulator connections bypass network IAM.
Backup, copy, restore, and backup schedulesSupportedWith --data_dir, CreateBackup, CopyBackup, GetBackup, ListBackups (with AIP-160 filter precedence), UpdateBackup, DeleteBackup, RestoreDatabase, and ListBackupOperations are supported. version_time backups and full/incremental backup schedules persist cursors across restarts.
Long-running operation lifecycleSupportedNative long-running operations lifecycle across instance, database, backup, copy, and restore calls, with AIP-160 filter support.

Exercise a transactional workflow

  1. Follow the Python SDK example to create an instance, database, and schema before opening the application client.
  2. Insert a small order and inventory fixture. Update both in one transaction and query the committed values.
  3. Run conflicting updates with the isolation level your application selects. Assert wound-wait conflict handling, retries, and the final inventory value.
  4. If the application uses database roles, create a session with creator_role and check both allowed and denied operations.

Follow committed changes

  1. Create a change stream for the fixture table and read it through ExecuteStreamingSql; unary ExecuteSql does not read change streams.
  2. Commit a write while the reader is active. Check the data-change record, transaction metadata, and heartbeat handling.
  3. Resume at the stream’s row-boundary token and assert the consumer’s handling of repeated records. Use persistent storage when testing retained stream state across restart.

Runtime and recovery limits

Backups and durable stream recovery require the mounted Spanner data directory. Back up known rows, restore into a separate database, and compare schema and data. A successful backup operation alone does not validate recovery.

Unauthenticated emulator connections bypass network IAM. Database-role checks do not establish Google IAM authority; CMEK and Google-managed regional behavior require cloud validation.

Verify production IAM, managed replication, regional availability, performance, and required functional behavior in Google Cloud before release.

Maintained by LocalCloud

Desktop view