Create a Cloud Run function that returns Spanner results
Stay organized with collections
Save and categorize content based on your preferences.
This tutorial shows you how to write an HTTP Cloud Run function
that returns Spanner results.
Objectives
Write, deploy, and trigger an
HTTP function that accesses
Spanner.
Costs
This document uses Spanner and Cloud Run,
which are billable components of Google Cloud.
For information on the cost of using Spanner, see
Spanner pricing.
For information on the cost of using Cloud Run, including free
invocations, see Cloud Run pricing.
Before you begin
This document assumes you have a Spanner instance named
test-instance and a database named example-db that uses the music
application
schema.
For instructions on creating an instance and database with the music application
schema, see Quickstart using the console or
the tutorials for Getting Started in Node.js,
or Python.
Change to the directory that contains the Cloud Run functions
sample code for accessing Spanner:
Node.js
cdnodejs-docs-samples/functions/spanner
Python
cdpython-docs-samples/functions/spanner
Take a look at the sample code:
Node.js
// Imports the Google Cloud client libraryconst{Spanner}=require('@google-cloud/spanner');// Imports the functions framework to register your HTTP functionconstfunctions=require('@google-cloud/functions-framework');// Instantiates a clientconstspanner=newSpanner();// Your Cloud Spanner instance IDconstinstanceId='test-instance';// Your Cloud Spanner database IDconstdatabaseId='example-db';/** * HTTP Cloud Function. * * @param {Object} req Cloud Function request context. * @param {Object} res Cloud Function response context. */functions.http('spannerQuickstart',async(req,res)=>{// Gets a reference to a Cloud Spanner instance and databaseconstinstance=spanner.instance(instanceId);constdatabase=instance.database(databaseId);// The query to executeconstquery={sql:'SELECT * FROM Albums',};// Execute the querytry{constresults=awaitdatabase.run(query);constrows=results[0].map(row=>row.toJSON());rows.forEach(row=>{res.write(`SingerId: ${row.SingerId}, `+`AlbumId: ${row.AlbumId}, `+`AlbumTitle: ${row.AlbumTitle}\n`);});res.status(200).end();}catch(err){res.status(500).send(`Error querying Spanner: ${err}`);}});
Python
importfunctions_frameworkfromgoogle.cloudimportspannerinstance_id="test-instance"database_id="example-db"client=spanner.Client()instance=client.instance(instance_id)database=instance.database(database_id)@functions_framework.httpdefspanner_read_data(request):query="SELECT * FROM Albums"outputs=[]withdatabase.snapshot()assnapshot:results=snapshot.execute_sql(query)forrowinresults:output="SingerId: {}, AlbumId: {}, AlbumTitle: {}".format(*row)outputs.append(output)return"\n".join(outputs)
The function sends a SQL query to fetch all Albums data from your
database. The function is executed when you make an HTTP request
to the function's endpoint.
Deploy the function
To deploy the function with an HTTP trigger, run the following
command in the spanner directory:
Note the url value returned when your function finishes deploying. You will
use it when you trigger the function.
You can view your deployed functions on the
Cloud Run page in the
Google Cloud console. You can also create and edit functions on that page, and get
details and diagnostics for your functions.
Trigger the function
Make an HTTP request to your function:
curl URL
Replace URL with the URL value returned when your function
finishes deploying.
You should see output that shows the results of the
SQL query, assuming you worked through a Getting Started tutorial
and populated the database:
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-25 UTC."],[],[],null,["# Create a Cloud Run function that returns Spanner results\n\nThis tutorial shows you how to write an HTTP Cloud Run function\nthat returns Spanner results.\n\nObjectives\n----------\n\nWrite, deploy, and trigger an\n[HTTP function](/run/docs/write-http-functions) that accesses\nSpanner.\n\nCosts\n-----\n\nThis document uses Spanner and Cloud Run,\nwhich are billable components of Google Cloud.\n\n- For information on the cost of using Spanner, see\n [Spanner pricing](/spanner/pricing).\n\n- For information on the cost of using Cloud Run, including free\n invocations, see [Cloud Run pricing](/run/pricing).\n\nBefore you begin\n----------------\n\n1. This document assumes you have a Spanner instance named\n `test-instance` and a database named `example-db` that uses the music\n application\n [schema](/spanner/docs/schema-and-data-model#creating-interleaved-tables).\n For instructions on creating an instance and database with the music application\n schema, see [Quickstart using the console](/spanner/docs/create-query-database-console) or\n the tutorials for Getting Started in [Node.js](/spanner/docs/getting-started/nodejs),\n or [Python](/spanner/docs/getting-started/python).\n\n | **Note:** After this step, you should have two tables, [`Singers`](/spanner/docs/schema-and-data-model#creating_a_table) and [`Albums`](/spanner/docs/schema-and-data-model#creating_multiple_tables), in your database with the sample data specified in the music application schema.\n2. Enable the Cloud Run, and Cloud Build APIs.\n\n [Enable the APIs](https://console.cloud.google.com/flows/enableapi?apiid=cloudrun.googleapis.com,cloudbuild.googleapis.com)\n3. [Install and initialize the gcloud CLI](/sdk/docs).\n\n If you already have the gcloud CLI installed, update it by running the\n following command: \n\n gcloud components update\n\n4. Prepare your development environment:\n\n ### Node.js\n\n See the [Node.js setup guide](/nodejs/docs/setup).\n\n ### Python\n\n See the [Python setup guide](/python/docs/setup).\n\nPrepare the application\n-----------------------\n\n1. Clone the sample app repository to your local machine:\n\n ### Node.js\n\n git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git\n\n Alternatively, you can [download the sample](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/archive/main.zip)\n as a zip file and extract it.\n\n ### Python\n\n git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git\n\n Alternatively, you can [download the sample](https://github.com/GoogleCloudPlatform/python-docs-samples/archive/main.zip)\n as a zip file and extract it.\n2. Change to the directory that contains the Cloud Run functions\n sample code for accessing Spanner:\n\n ### Node.js\n\n cd nodejs-docs-samples/functions/spanner\n\n ### Python\n\n cd python-docs-samples/functions/spanner\n\n3. Take a look at the sample code:\n\n ### Node.js\n\n // Imports the Google Cloud client library\n const {Spanner} = require('https://cloud.google.com/nodejs/docs/reference/spanner/latest/overview.html');\n\n // Imports the functions framework to register your HTTP function\n const functions = require('@google-cloud/functions-framework');\n\n // Instantiates a client\n const spanner = new https://cloud.google.com/nodejs/docs/reference/spanner/latest/spanner/spanner.html();\n\n // Your Cloud Spanner instance ID\n const instanceId = 'test-instance';\n\n // Your Cloud Spanner database ID\n const databaseId = 'example-db';\n\n /**\n * HTTP Cloud Function.\n *\n * @param {Object} req Cloud Function request context.\n * @param {Object} res Cloud Function response context.\n */\n functions.http('spannerQuickstart', async (req, res) =\u003e {\n // Gets a reference to a Cloud Spanner instance and database\n const instance = spanner.instance(instanceId);\n const database = instance.database(databaseId);\n\n // The query to execute\n const query = {\n sql: 'SELECT * FROM Albums',\n };\n\n // Execute the query\n try {\n const results = await database.run(query);\n const rows = results[0].map(row =\u003e row.toJSON());\n rows.forEach(row =\u003e {\n res.write(\n `SingerId: ${row.SingerId}, ` +\n `AlbumId: ${row.AlbumId}, ` +\n `AlbumTitle: ${row.AlbumTitle}\\n`\n );\n });\n res.status(200).end();\n } catch (err) {\n res.status(500).send(`Error querying Spanner: ${err}`);\n }\n });\n\n ### Python\n\n import functions_framework\n from google.cloud import https://cloud.google.com/python/docs/reference/spanner/latest/google.cloud.spanner_v1.services.spanner.html\n\n instance_id = \"test-instance\"\n database_id = \"example-db\"\n\n client = https://cloud.google.com/python/docs/reference/spanner/latest/google.cloud.spanner_v1.services.spanner.html.https://cloud.google.com/python/docs/reference/spanner/latest/google.cloud.spanner_v1.client.Client.html()\n instance = https://cloud.google.com/python/docs/reference/spanner/latest/google.cloud.spanner_v1.client.html.https://cloud.google.com/python/docs/reference/spanner/latest/google.cloud.spanner_v1.client.Client.html#google_cloud_spanner_v1_client_Client_instance(instance_id)\n database = instance.database(database_id)\n\n\n @functions_framework.http\n def spanner_read_data(request):\n query = \"SELECT * FROM Albums\"\n\n outputs = []\n with database.snapshot() as snapshot:\n results = snapshot.execute_sql(query)\n\n for row in results:\n output = \"SingerId: {}, AlbumId: {}, AlbumTitle: {}\".format(*row)\n outputs.append(output)\n\n return \"\\n\".join(outputs)\n\n The function sends a SQL query to fetch all `Albums` data from your\n database. The function is executed when you make an HTTP request\n to the function's endpoint.\n\nDeploy the function\n-------------------\n\nTo deploy the function with an HTTP trigger, run the following\ncommand in the `spanner` directory: \n\n### Node.js\n\n gcloud run deploy nodejs-spanner-function \\\n --source . \\\n --region \u003cvar translate=\"no\"\u003eREGION\u003c/var\u003e \\\n --function spannerQuickstart \\\n --base-image \u003cvar translate=\"no\"\u003eRUNTIME_ID\u003c/var\u003e \\\n --log-http\n\n### Python\n\n gcloud run deploy python-spanner-function \\\n --source . \\\n --region \u003cvar translate=\"no\"\u003eREGION\u003c/var\u003e \\\n --function spanner_read_data \\\n --base-image \u003cvar translate=\"no\"\u003eRUNTIME_ID\u003c/var\u003e \\\n --log-http\n\nReplace:\n\n- \u003cvar translate=\"no\"\u003eREGION\u003c/var\u003e with the name of the [Google Cloud region](/run/docs/locations) where you want to deploy your function\n (for example, `us-west1`).\n\n- \u003cvar translate=\"no\"\u003eRUNTIME_ID\u003c/var\u003e with the appropriate runtime ID (for\n example, `nodejs22`). See [Supported language runtimes and base images](/run/docs/configuring/services/runtime-base-images).\n\nFunction deployment might take up to two minutes.\n\nNote the `url` value returned when your function finishes deploying. You will\nuse it when you trigger the function.\n\nYou can view your deployed functions on the\n[Cloud Run](https://console.cloud.google.com/project/_/run) page in the\nGoogle Cloud console. You can also create and edit functions on that page, and get\ndetails and diagnostics for your functions.\n\nTrigger the function\n--------------------\n\nMake an HTTP request to your function: \n\n curl \u003cvar translate=\"no\"\u003eURL\u003c/var\u003e\n\nReplace \u003cvar translate=\"no\"\u003eURL\u003c/var\u003e with the URL value returned when your function\nfinishes deploying.\n\nYou should see output that shows the results of the\nSQL query, assuming you worked through a [Getting Started tutorial](/spanner/docs/create-query-database-console)\nand populated the database: \n\n SingerId: 2, AlbumId: 2, AlbumTitle: Forever Hold Your Peace\n SingerId: 1, AlbumId: 2, AlbumTitle: Go, Go, Go\n SingerId: 2, AlbumId: 1, AlbumTitle: Green\n SingerId: 2, AlbumId: 3, AlbumTitle: Terrified\n SingerId: 1, AlbumId: 1, AlbumTitle: Total Junk\n\nYou can also visit the function's URL in your browser to see the result of\nyour SQL query.\n| **Success:** You created an HTTP Cloud Run function that returns Spanner results.\n\nClean up\n--------\n\nTo avoid incurring additional charges to your Google Cloud account for the\nSpanner and Cloud Run functions resources used in\nthis document:\n\n1. Delete the instance:\n\n gcloud CLI instances delete test-instance\n\n2. Delete the Cloud Run service you deployed in this tutorial:\n\n ### Node.js\n\n gcloud run services delete nodejs-spanner-function\n\n ### Python\n\n gcloud run services delete python-spanner-function\n\nWhat's next\n-----------\n\n- [Learn more about writing Cloud Run functions](/run/docs/write-functions).\n- [Learn more about deploying Cloud Run functions](/run/docs/deploy-functions).\n- [Learn more about triggering Cloud Run functions](/run/docs/function-triggers)."]]