# Spanner emulator feature reference

> Run Spanner locally with LocalCloud: GoogleSQL and PostgreSQL dialects, gRPC and REST endpoints, persistence, and per-operation limits.
>
> Source: https://local.cloud/docs/spanner-emulator-features/

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.

> **Use the operation boundaries**
>
> The table below retains the runtime’s recorded operation boundaries and limitations. Standalone dependency tests don’t cover the LocalCloud image. Validate the exact client, operation, dialect, and image used by the application.

## Connections and persistence

| Surface | Canonical value | Boundary |
| --- | --- | --- |
| gRPC API | `SPANNER_EMULATOR_HOST=localhost:5386` | Use generated host ports and test the selected SDK/version. |
| REST gateway | `http://localhost:5387` | REST / grpc-gateway, not PostgreSQL wire. |
| PostgreSQL dialect | Queries through the Spanner API | LocalCloud does not package PGAdapter; `psql` and pgJDBC need a separately configured adapter. |
| State | LevelDB rows and JSON metadata under `/var/lib/localcloud/spanner-data` | Mounted 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](https://local.cloud/services/spanner/#workflows). The reference below describes individual API areas.

| Operation area | Status | Boundary |
| --- | --- | --- |
| Native SQL, read, and streaming read | Supported | Native 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 DML | Supported | Sessions (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 write | Supported | PartitionRead, PartitionQuery, partitioned DML (including parameterized PostgreSQL statements), and BatchWrite are supported. |
| Instance, configuration, and instance-partition administration | Supported | Instance and instance-partition administration, custom instance configurations, and MoveInstance (metadata). List operations and instances support AIP-160 filter expressions. |
| Database administration and DDL | Supported | Database 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 policies | Supported | IAM 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 schedules | Supported | With --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 lifecycle | Supported | Native 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](https://local.cloud/docs/sdk-examples/#spanner-python) 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.
