Deploy to Any Platform
Genkit has built-in integrations that help you deploy your flows to Cloud Functions for Firebase and Google Cloud Run, but you can also deploy your flows to any platform that can serve an Express.js app, whether it’s a cloud service or self-hosted.
This page, as an example, walks you through the process of deploying the default sample flow.
Before you begin
Section titled “Before you begin”- Node.js 20+: Confirm that your environment is using Node.js version 20 or
higher (
node --version
). - You should be familiar with Genkit’s concept of flows.
1. Set up your project
Section titled “1. Set up your project”-
Create a directory for the project:
Terminal window export GENKIT_PROJECT_HOME=~/tmp/genkit-express-projectmkdir -p $GENKIT_PROJECT_HOMEcd $GENKIT_PROJECT_HOMEmkdir src -
Initialize a Node.js project:
Terminal window npm init -y -
Install Genkit and necessary dependencies:
Terminal window npm install --save genkit @genkit-ai/google-genainpm install --save-dev typescript tsxnpm install -g genkit-cli
2. Configure your Genkit app
Section titled “2. Configure your Genkit app”-
Set up a sample flow and server:
In
src/index.ts
, define a sample flow and configure the flow server:import { genkit, z } from 'genkit';import { googleAI } from '@genkit-ai/google-genai';import { startFlowServer } from '@genkit-ai/express';const ai = genkit({plugins: [googleAI()],model: googleAI.model('gemini-2.5-flash'),});const helloFlow = ai.defineFlow({name: 'helloFlow',inputSchema: z.object({ name: z.string() }),outputSchema: z.object({ greeting: z.string() }),},async (input) => {const { text } = await ai.generate('Say hello to ${input.name}');return { greeting: text };},);startFlowServer({flows: [helloFlow],});There are also some optional parameters for
startFlowServer
you can specify:port
: the network port to listen on. If unspecified, the server listens on the port defined in the PORT environment variable, and if PORT is not set, defaults to 3400.cors
: the flow server’s CORS policy. If you will be accessing these endpoints from a web application, you likely need to specify this.pathPrefix
: an optional path prefix to add before your flow endpoints.jsonParserOptions
: options to pass to Express’s JSON body parser
-
Set up model provider credentials:
Configure the required environment variables for your model provider. This guide uses the Gemini API from Google AI Studio as an example.
Get an API key from Google AI Studio
After you’ve created an API key, set the
GEMINI_API_KEY
environment variable to your key with the following command:Terminal window export GEMINI_API_KEY=<your API key>Different providers for deployment will have different ways of securing your API key in their environment. For security, ensure that your API key is not publicly exposed.
3. Prepare your Node.js project for deployment
Section titled “3. Prepare your Node.js project for deployment”Add start and build scripts to package.json
Section titled “Add start and build scripts to package.json”To deploy a Node.js project, define start
and build
scripts in
package.json
. For a TypeScript project, these scripts will look like this:
"scripts": { "start": "node --watch lib/index.js", "build": "tsc"},
Build and test locally
Section titled “Build and test locally”Run the build command, then start the server and test it locally to confirm it works as expected.
npm run build
npm start
In another terminal window, test the endpoint:
curl -X POST "http://127.0.0.1:3400/helloFlow" \ -H "Content-Type: application/json" \ -d '{"data": {"name": "Genkit"}}'
Optional: Start the Developer UI
Section titled “Optional: Start the Developer UI”You can use the Developer UI to test flows interactively during development:
genkit start -- npm run start
Navigate to http://localhost:4000/flows
to
test your flows in the UI.
4. Deploy the project
Section titled “4. Deploy the project”Once your project is configured and tested locally, you can deploy to any Node.js-compatible platform. Deployment steps vary by provider, but generally, you configure the following settings:
Setting | Value |
---|---|
Runtime | Node.js 20 or newer |
Build command | npm run build |
Start command | npm start |
Environment variables | Set GEMINI_API_KEY=<your-api-key> and other necessary secrets. |
The start
command (npm start
) should point to your compiled entry point,
typically lib/index.js
. Be sure to add all necessary environment variables
for your deployment platform.
After deploying, you can use the provided service URL to invoke your flow as an HTTPS endpoint.
Call your flows from the client
Section titled “Call your flows from the client”In your client-side code (e.g., a web application, mobile app, or another service), you can call your deployed flows using the Genkit client library. This library provides functions for both non-streaming and streaming flow calls.
First, install the Genkit library:
npm install genkit
Then, you can use runFlow
for non-streaming calls and streamFlow
for streaming calls.
Non-streaming Flow Calls
Section titled “Non-streaming Flow Calls”For a non-streaming response, use the runFlow
function. This is suitable for flows that return a single, complete output.
import { runFlow } from 'genkit/beta/client';
async function callHelloFlow() { try { const result = await runFlow({ url: 'http://127.0.0.1:3400/helloFlow', // Replace with your deployed flow's URL input: { name: 'Genkit User' }, }); console.log('Non-streaming result:', result.greeting); } catch (error) { console.error('Error calling helloFlow:', error); }}
callHelloFlow();
Streaming Flow Calls
Section titled “Streaming Flow Calls”For flows that are designed to stream responses (e.g., for real-time updates or long-running operations), use the streamFlow
function.
import { streamFlow } from 'genkit/beta/client';
async function streamHelloFlow() { try { const result = streamFlow({ url: 'http://127.0.0.1:3400/helloFlow', // Replace with your deployed flow's URL input: { name: 'Streaming User' }, });
// Process the stream chunks as they arrive for await (const chunk of result.stream) { console.log('Stream chunk:', chunk); }
// Get the final complete response const finalOutput = await result.output; console.log('Final streaming output:', finalOutput.greeting); } catch (error) { console.error('Error streaming helloFlow:', error); }}
streamHelloFlow();
Authentication (Optional)
Section titled “Authentication (Optional)”If your deployed flow requires authentication, you can pass headers with your requests:
const result = await runFlow({ url: 'http://127.0.0.1:3400/helloFlow', // Replace with your deployed flow's URL headers: { Authorization: 'Bearer your-token-here', // Replace with your actual token }, input: { name: 'Authenticated User' },});
You can deploy Genkit flows as web services using any service that can host a Go binary. This page, as an example, walks you through the general process of deploying the default sample flow, and points out where you must take provider-specific actions.
-
Create a directory for the Genkit sample project:
Terminal window mkdir -p ~/tmp/genkit-cloud-projectcd ~/tmp/genkit-cloud-projectIf you’re going to use an IDE, open it to this directory.
-
Initialize a Go module in your project directory:
Terminal window go mod init example/cloudrungo get github.com/firebase/genkit/go -
Create a sample app using Genkit:
package mainimport ("context""fmt""log""net/http""os""github.com/firebase/genkit/go/ai""github.com/firebase/genkit/go/genkit""github.com/firebase/genkit/go/plugins/googlegenai""github.com/firebase/genkit/go/plugins/server")func main() {ctx := context.Background()// Initialize Genkit with the Google AI plugin and Gemini 2.0 Flash.// Alternatively, use &googlegenai.VertexAI{} and "vertexai/gemini-2.5-flash"// to use Vertex AI as the provider instead.g := genkit.Init(ctx,genkit.WithPlugins(&googlegenai.GoogleAI{}),genkit.WithDefaultModel("googleai/gemini-2.5-flash"),)flow := genkit.DefineFlow(g, "jokesFlow", func(ctx context.Context, topic string) (string, error) {resp, err := genkit.Generate(ctx, g,ai.WithPrompt(`Tell a short joke about %s. Be creative!`, topic),)if err != nil {return "", fmt.Errorf("failed to generate joke: %w", err)}return resp.Text(), nil})mux := http.NewServeMux()mux.HandleFunc("POST /jokesFlow", genkit.Handler(flow))log.Fatal(server.Start(ctx, "127.0.0.1:"+os.Getenv("PORT"), mux))} -
Implement some form of authentication and authorization to gate access to the flows you plan to deploy.
Because most generative AI services are metered, you most likely do not want to allow open access to any endpoints that call them. Some hosting services provide an authentication layer as a frontend to apps deployed on them, which you can use for this purpose.
-
Make API credentials available to your deployed function. Do one of the following, depending on the model provider you chose:
Gemini (Google AI)
-
Make sure Google AI is available in your region.
-
Generate an API key for the Gemini API using Google AI Studio.
-
Make the API key available in the deployed environment.
Most app hosts provide some system for securely handling secrets such as API keys. Often, these secrets are available to your app in the form of environment variables. If you can assign your API key to the
GEMINI_API_KEY
variable, Genkit will use it automatically. Otherwise, you need to modify thegooglegenai.GoogleAI
plugin struct to explicitly set the key. (But don’t embed the key directly in code! Use the secret management facilities provided by your hosting provider.)Gemini (Vertex AI)
-
In the Cloud console, Enable the Vertex AI API for your project.
-
On the IAM page, create a service account for accessing the Vertex AI API if you don’t alreacy have one.
Grant the account the Vertex AI User role.
-
Set up Application Default Credentials in your hosting environment.
-
Configure the plugin with your Google Cloud project ID and the Vertex AI API location you want to use. You can do so either by setting the
GOOGLE_CLOUD_PROJECT
andGOOGLE_CLOUD_LOCATION
environment variables in your hosting environment, or in yourgooglegenai.VertexAI{}
constructor.The only secret you need to set up for this tutorial is for the model provider, but in general, you must do something similar for each service your flow uses.
-
-
Optional: Try your flow in the developer UI:
-
Set up your local environment for the model provider you chose:
Gemini (Google AI)
Terminal window export GEMINI_API_KEY=<your API key>Gemini (Vertex AI)
Terminal window export GOOGLE_CLOUD_PROJECT=<your project ID>export GOOGLE_CLOUD_LOCATION=us-central1gcloud auth application-default login -
Start the UI:
Terminal window genkit start -- go run . -
In the developer UI (
http://localhost:4000/
), run the flow: -
Click jokesFlow.
-
On the Input JSON tab, provide a subject for the model:
"bananas" -
Click Run.
-
-
If everything’s working as expected so far, you can build and deploy the flow using your provider’s tools.
Prerequisites: make sure you have everything installed from the Get Started guide.
-
Install Genkit Flask plugin
Terminal window pip install git+https://github.com/firebase/genkit#subdirectory=py/plugins/flaskOr create a
requirements.txt
filerequirements.txt genkit-plugin-flask @ git+https://github.com/firebase/genkit#subdirectory=py/plugins/google-genai -
Create
main.py
file:main.py from flask import Flaskfrom genkit.ai import Genkitfrom genkit.plugins.flask import genkit_flask_handlerfrom genkit.plugins.google_genai import (GoogleGenai,google_genai_name,)ai = Genkit(plugins=[GoogleGenai()],model=google_genai_name('gemini-2.5-flash'),)app = Flask(__name__)@app.post('/joke')@genkit_flask_handler(ai)@ai.flow()async def joke(name: str, ctx):return await ai.generate(on_chunk=ctx.send_chunk,prompt=f'tell a medium sized joke about {name}',) -
Run the app:
Terminal window flask --app main.py runOr with Dev UI:
Terminal window genkit start -- flask --app main.py runYou can invoke the flow via HTTP:
Terminal window curl -X POST http://127.0.0.1:5000/joke -d '{"data": "banana"}' -H 'content-Type: application/json' -H 'Accept: text/event-stream'or you can use Genkit client library.
Authorization and custom context
Section titled “Authorization and custom context”You can do custom authorization and custom context parsing by passing a ContextProvider
implementation.
from genkit.types import GenkitError
# Assume parse_request_header is defined elsewhere# def parse_request_header(auth_header):# # Example implementation: Replace with your actual logic# if auth_header and auth_header.startswith('Bearer '):# token = auth_header.split(' ')[1]# # Validate token and return username, or None/raise error# if token == "valid-token":# return "testuser"# return None
async def my_context_provider(request): # This function needs access to the request object from Flask # The exact way to get headers might depend on how genkit_flask_handler passes the request auth_header = request.headers.get('authorization') username = parse_request_header(auth_header) # Call the (assumed) function return {'username': username}
@app.post('/say_hi')@genkit_flask_handler(ai, context_provider=my_context_provider)@ai.flow()async def say_hi(name: str, ctx): if not ctx.context.get('username'): raise GenkitError(status='UNAUTHENTICATED', message='user not provided')
return await ai.generate( on_chunk=ctx.send_chunk, prompt=f'say hi to {ctx.context.get("username")}', )
parse_request_header
can be your custom authorization header parsing/validation.