The Go programming language is a great fit for building serverless applications. Go applications can be easily compiled to a single, statically linked binary, making deployment simple and reducing external dependencies. They start up quickly, which is ideal for serverless environments where functions are frequently invoked from a cold start. Go applications also tend to use less memory compared to other languages, helping optimize resource usage and reduce costs in serverless scenarios.Azure Functions supports Go using custom handlers, and you can use triggers and input and output bindings via extension bundles. Azure Functions is tightly integrated with Azure Cosmos DB using bindings (input, output), and triggers.This blog post will walk you through how to build Azure Functions with Go that make use of these Azure Cosmos DB integrations. Bindings allow you to easily read and write data to Azure Cosmos DB, while triggers are useful for building event-driven applications that respond to changes in your data in Azure Cosmos DB.Part 1 of this blog starts off with a function that gets triggered by changes in a Azure Cosmos DB container and simply logs the raw Azure Functions event payload and the Cosmos DB document. You will learn how to run the function and also test it with Cosmos DB locally, thanks to the Azure Cosmos DB emulator and Azure Functions Core Tools. If this is your first time working with Go and Azure Functions, you should find it helpful to get up and running quickly. Although you can deploy it to Azure, we will save that for the next part of this blog.Part 2 dives into another function that generates embeddings for the documents in the Azure Cosmos DB container. This example will use an Azure OpenAI embedding model to generate embeddings for the documents in the container and then store the embeddings back in the container. This is useful for building applications that require semantic search or other generative AI applications.[alert type="note" heading=""]Check out the GitHub repository for the complete code.[/alert]Part 1: Build a simple Azure Cosmos DB trigger-based function and run it locallyJust as the Azure Cosmos DB emulator lets you run Azure Cosmos DB locally, Azure Functions Core Tools lets you develop and test your functions locally.Start by installing the Azure Functions Core Tools – refer to the documentation for instructions for your OS. For example, on Linux, you can:sudo apt-get updatesudo apt-get install azure-functions-core-tools-4Next, start the Azure Cosmos DB emulator. The commands below are for Linux and use the Docker container-based approach - refer to the documentation for other options.[alert type="important" heading=""]You need to have Docker installed and running on your machine. If you don't have it installed, please refer to the Docker installation guide.[/alert]docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latestdocker run \ --publish 8081:8081 \ --name linux-emulator \ -e AZURE_COSMOS_EMULATOR_PARTITION_COUNT=1 \ mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latestMake sure to configure the emulator SSL certificate as well. For example, for the Linux system I was using, I ran the following command to download the certificate and regenerate the certificate bundle:curl --insecure https://localhost:8081/_explorer/emulator.pem > ~/emulatorcert.crtsudo update-ca-certificatesUse the following URL to navigate to the Azure Cosmos DB Data Explorer using your browser: http://localhost:8081/_explorer/index.html. Create the following resources: A database A container with partition key /id – this is the source container A lease container with the name leases and partition key /id – it is used by the trigger to keep track of the changes in the source container.Clone the GitHub repository with the code for the function:git clone https://github.com/abhirockzz/golang_cosmosdb_azure_functions.gitcd golang_cosmosdb_azure_functions/getting_started_guideA local.settings.json file is used to store the configuration settings for your function app when running locally, Create a local.settings.json file and populate it with Azure Cosmos DB related information. Use the same database and container names as you created in the previous step.Here is the format:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "custom", "COSMOS_CONNECTION": "AccountEndpoint=https://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==;", "COSMOS_DATABASE_NAME": "test", "COSMOS_CONTAINER_NAME": "tasks" }}[alert type="note" heading=""]COSMOS_CONNECTION has a static value for the connection string for the Azure Cosmos DB emulator – do not change it.[/alert]Build the Go function binary using the following command. This will create a binary file named main in the current directory:go build -o main main.goStart the function locally:func startThis will start the function app and listen for incoming requests. You should see an output similar to this:[2025-04-25T07:44:53.921Z] Worker process started and initialized.Functions: processor: cosmosDBTriggerFor detailed output, run func with --verbose flag.[2025-04-25T07:44:58.809Z] Host lock lease acquired by instance ID '0000000000000000000000006ADD8D3E'.//...Add data to the source container in Azure Cosmos DB. You can do this by navigating to Data Explorer in the emulator. For example, add a document with the following JSON:{ "id": "42", "description": "test"}The function should be triggered automatically when the document is added to the container. You can check the logs of the function app to see if it was triggered successfully:[2025-04-25T07:48:10.559Z] Executing 'Functions.processor' (Reason='New changes on container tasks at 2025-04-25T07:48:10.5593689Z', Id=7b62f8cf-683b-4a5b-9db0-83d049bc4c86)[2025-04-25T07:48:10.565Z] processor function invoked...[2025-04-25T07:48:10.565Z] Raw event payload: {{"[{\"id\":\"42\",\"description\":\"test\",\"_rid\":\"AxI2AL1rrFoDAAAAAAAAAA==\",\"_self\":\"dbs/AxI2AA==/colls/AxI2AL1rrFo=/docs/AxI2AL1rrFoDAAAAAAAAAA==/\",\"_etag\":\"\\\"00000000-0000-0000-b5b6-6123f4d401db\\\"\",\"_attachments\":\"attachments/\",\"_ts\":1745567285,\"_lsn\":4}]"}} {{processor 2025-04-25T07:48:10.560243Z 4f29b3f3-ba95-4043-9b67-2856a43b4734}}}[2025-04-25T07:48:10.566Z] Cosmos DB document: {42 AxI2AL1rrFoDAAAAAAAAAA== dbs/AxI2AA==/colls/AxI2AL1rrFo=/docs/AxI2AL1rrFoDAAAAAAAAAA==/ "00000000-0000-0000-b5b6-6123f4d401db" attachments/ 1745567285 4}[2025-04-25T07:48:10.566Z] Executed 'Functions.processor' (Succeeded, Id=7b62f8cf-683b-4a5b-9db0-83d049bc4c86, Duration=6ms)//.....How it worksHere is a very high-level overview of the code: main.go – Implements an HTTP server with a processor endpoint. When triggered, it reads a Azure Cosmos DB trigger payload from the request, parses the nested documents, logs information, and returns a structured JSON response. It uses types and helpers from the common package. common package: Contains shared types and utilities for Azure Cosmos DB trigger processing: payload.go: Defines data structures for the trigger payload, documents, and response. parse.go: Provides a Parse function to extract and unmarshal documents from the trigger payload’s nested JSON structure.Part 2: Use Azure OpenAI to generate embeddings for the documents in the Azure Cosmos DB containerIn addition to its low-latency, high-performance, and scalability characteristics, its support for Vector, Full-text, and Hybrid search makes Azure Cosmos DB a great fit for generative AI applications. Consider a use case for managing a product catalog for an e-commerce platform. Each time a new product is added to the system (with a short description like “Bluetooth headphones with noise cancellation”), we want to immediately make that item searchable semantically.As soon as the product document is written to Azure Cosmos DB, an Azure Function is triggered. It extracts the product description, generates a vector embedding using Azure OpenAI, and writes the embedding back to the same document using an output binding. With the embedding in place, the product is now indexed and ready for search queries. PrerequisitesYou will run this example in Azure, so you need to have an Azure account. If you don't have one, you can create a free account. Create an Azure Cosmos DB for NoSQL account and Enable the vector indexing and search feature – this is a one-time operation.Just like before, you will need to create the following resources: A database A container with partition key /id – this is the source container A lease container with the name leases and partition key /id – it is used by the trigger to keep track of the changes in the source container.[alert type="important" heading=""]The lease container needs to be created in advance since we have configured Azure Functions to use managed identity to access the Azure Cosmos DB account – you don't need to use keys or connection strings.[/alert]Create an Azure OpenAI Service resource. Azure OpenAI Service provides access to OpenAI's models including GPT-4o, GPT-4o mini (and more), as well as embedding models. Deploy an embedding model of your choice using the Azure AI Foundry portal (for example, I used the text-embedding-3-small model). Just like the Azure Cosmos DB account, the Azure Function app uses a managed identity to access the Azure OpenAI Service resource.Deploy resourcesMove into the right directory:cd ../embeddings_generatorTo simplify the deployment of the function app along with the required resources and configuration, you can use the deploy.sh script. At a high level, it: Sets up environment variables for Azure resources. Creates an Azure resource group, storage account, and function app plan. Deploys a custom Go-based Azure Function App. Builds the Go binary for Windows. Publishes the function app to Azure. Enables the function app system identity and provides it the required roles for Azure Cosmos DB and Azure OpenAI resource access.Before you deploy the solution, update the local.settings.json. Use the same database and container names as you created in the previous step:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "custom", "COSMOS_CONNECTION__accountEndpoint": "https://ENTER_COSMOSDB_ACCOUNT_NAME.documents.azure.com:443/", "COSMOS_DATABASE_NAME": "name of the database", "COSMOS_CONTAINER_NAME": "name of the container", "COSMOS_HASH_PROPERTY": "hash", "COSMOS_VECTOR_PROPERTY": "embedding", "COSMOS_PROPERTY_TO_EMBED": "description", "OPENAI_DEPLOYMENT_NAME": "enter the embedding model deployment name e.g. text-embedding-3-small", "OPENAI_DIMENSIONS": "enter the dimensions e.g. 1536", "OPENAI_ENDPOINT": "https://ENTER_OPENAI_RESOURCE_NAME.openai.azure.com/" }} COSMOS_CONNECTION_accountEndpoint: Endpoint URL for the Azure Cosmos DB account. COSMOS_DATABASE_NAME: Name of the Azure Cosmos DB database to use. COSMOS_CONTAINER_NAME: Name of the Azure Cosmos DB container to use. COSMOS_HASH_PROPERTY: Name of the property used as a hash in Azure Cosmos DB documents (no need to modify this). COSMOS_VECTOR_PROPERTY: Name of the property storing vector embeddings in Azure Cosmos DB. COSMOS_PROPERTY_TO_EMBED: Name of the property whose value will be embedded. Change this based on your document structure. OPENAI_DEPLOYMENT_NAME: Name of the Azure OpenAI model deployment to use for embeddings. OPENAI_DIMENSIONS: Number of dimensions for the embedding vectors. OPENAI_ENDPOINT: Endpoint URL for the Azure OpenAI resource.Run the deploy.sh script:chmod +x deploy.sh./deploy.shRun the end-to-end exampleAdd data to the source container in Azure Cosmos DB. For example, add a document with the following JSON:{ "id": "de001c6d-4efe-4a65-a59a-39a0580bfa2a", "description": "Research new technology"}The function should be triggered automatically when the document is added to the container. You can check the logs of the function app to see if it was triggered successfully:func azure functionapp logstream You should see logs similar to this (the payload will be different depending on the data you add):2025-04-23T05:34:41Z [Information] function invoked2025-04-23T05:34:41Z [Information] cosmosVectorPropertyName: embedding2025-04-23T05:34:41Z [Information] cosmosVectorPropertyToEmbedName: description2025-04-23T05:34:41Z [Information] cosmosHashPropertyName: hash2025-04-23T05:34:41Z [Information] Processing 1 documents2025-04-23T05:34:41Z [Information] Processing document ID: de001c6d-4efe-4a65-a59a-39a0580bfa2a2025-04-23T05:34:41Z [Information] Document data: Research new technology2025-04-23T05:34:41Z [Information] New document detected, generated hash: 5bb57053273563e2fbd4202c666373ccd48f86eaf9198d7927a93a555aa200aa2025-04-23T05:34:41Z [Information] Document modification status: true, hash: 5bb57053273563e2fbd4202c666373ccd48f86eaf9198d7927a93a555aa200aa2025-04-23T05:34:41Z [Information] Created embedding for document: map[description:Research new technology id:de001c6d-4efe-4a65-a59a-39a0580bfa2a]2025-04-23T05:34:41Z [Information] Adding 1 document with embeddings2025-04-23T05:34:41Z [Information] Added enriched documents to binding output2025-04-23T05:34:41Z [Information] Executed 'Functions.cosmosdbprocessor' (Succeeded, Id=91f4760f-047a-4867-9030-46a6602ab179, Duration=128ms)//....Verify the data in Azure Cosmos DB. You should see an embedding for the description property of the document stored in the embedding property. It should look something like this:{ "id": "de001c6d-4efe-4a65-a59a-39a0580bfa2a", "description": "Research new technology", "embedding": [ 0.028226057, -0.00958694 //.... ], "hash": "5bb57053273563e2fbd4202c666373ccd48f86eaf9198d7927a93a555aa200aa"}Once the embeddings are generated, you can integrate this with generative AI applications. For example, you can use the Vector Search feature of Azure Cosmos DB to perform similarity searches based on the embeddings.How it worksHere is a very high-level overview of the code: main.go: Implements an HTTP server with a cosmosdbprocessor endpoint. When triggered, it reads a Azure Cosmos DB trigger payload from the request, parses the nested documents, generates embeddings using Azure OpenAI, and writes the enriched documents back to the Cosmos DB container. Exposes the cosmosdbprocessor endpoint, which processes incoming Azure Cosmos DB documents. For each document, checks if it is new or modified (using a hash), generates an embedding (vector) using Azure OpenAI, and prepares enriched documents for output. Handles logging and error reporting for the function execution. common package: Contains shared utilities and types for processing Azure Cosmos DB documents embedding.go: Handles creation of embeddings using Azure OpenAI. parse.go: Parses and extracts documents from the Azure Cosmos DB trigger payload. payload.go: Defines data structures for payloads and responses used across the project.The function uses a hash property to check if the document has already been processed. If the hash value is different from the one stored in Azure Cosmos DB, it means that the document has been modified and needs to be re-processed. In this case, the function will generate a new embedding and update the document with the new hash value. This ensures that the function does not get stuck in an infinite loop. If the hash value is the same, it means that the document has not been modified and does not need to be re-processed. In this case, the function will log that the document is unchanged and will not generate a new embedding.You should see logs similar to this:2025-04-23T05:34:42Z [Information] function invoked2025-04-23T05:34:42Z [Information] cosmosVectorPropertyName: embedding2025-04-23T05:34:42Z [Information] cosmosVectorPropertyToEmbedName: description2025-04-23T05:34:42Z [Information] cosmosHashPropertyName: hash2025-04-23T05:34:42Z [Information] Processing 1 document2025-04-23T05:34:42Z [Information] Processing document ID: de001c6d-4efe-4a65-a59a-39a0580bfa2a2025-04-23T05:34:42Z [Information] Document data: Research new technology2025-04-23T05:34:42Z [Information] Document unchanged, hash: 5bb57053273563e2fbd4202c666373ccd48f86eaf9198d7927a93a555aa200aa2025-04-23T05:34:42Z [Information] Document modification status: false, hash:2025-04-23T05:34:42Z [Information] Executed 'Functions.cosmosdbprocessor' (Succeeded, Id=f0cf039a-5de5-4cc1-b29d-928ce32b294e, Duration=6ms)//....Delete resourcesBe sure to clean up the resources you created in Azure. You can do this using the Azure portal or the Azure CLI. For example, to delete the resource group and all its resources, run:az group delete --name ConclusionIn this blog post, you learned how to build Azure Functions with Go that use Azure Cosmos DB triggers and bindings. It started with a simple function that logs the raw event payload and the Azure Cosmos DB document, and then moved on to a function that generates embeddings for the documents in the Azure Cosmos DB container using Azure OpenAI. You also learned how to run the functions locally using the Azure Cosmos DB emulator and Azure Functions Core Tools, and how to deploy them to Azure.You can use these examples as a starting point for building your own serverless applications with Go and Azure Functions. The combination of Go's performance and simplicity, along with Azure Functions' scalability and integration with Azure Cosmos DB, makes it a powerful platform for building modern applications.About Azure Cosmos DBAzure Cosmos DB is a fully managed and serverless distributed database for modern app development, with SLA-backed speed and availability, automatic and instant scalability, and support for open-source PostgreSQL, MongoDB, and Apache Cassandra. To stay in the loop on Azure Cosmos DB updates, follow us on X, YouTube, and LinkedIn.To easily build your first database, watch our Get Started videos on YouTube and explore ways to dev/test free.