Connecting from App Engine standard environment to Cloud SQL

This page contains information and examples for connecting to a Cloud SQL instance from a service running in App Engine standard environment.

Cloud SQL is a fully-managed database service that helps you set up, maintain, manage, and administer your relational databases in the cloud.

App Engine is a fully managed, serverless platform for developing and hosting web applications at scale. You can choose from several popular languages, libraries, and frameworks to develop your apps, then let App Engine take care of provisioning servers and scaling your app instances based on demand.

Setting up a Cloud SQL instance

  1. Enable the Cloud SQL Admin API in the project you are connecting from, if you haven't already done so:

    Enable the API

  2. Create a Cloud SQL for SQL Server instance.

    By default, Cloud SQL assigns a public IP address to a new instance. App Engine does not support connecting to Cloud SQL for SQL Server over public IP. Use private IP instead. For more information, see Configuring private IP.

Configuring App Engine

The steps to configure App Engine standard environment depend on the type of IP address you assigned to your Cloud SQL instance.

Public IP (default)

App Engine standard environment does not support connecting to Cloud SQL for SQL Server over public IP. Use private IP instead.

Private IP

A Serverless VPC Access connector handles communication to your VPC network. To connect directly with private IP, you need to:

  1. Make sure that the Cloud SQL instance created above has a private IP address. If you need to add one, see the Configuring private IP page for instructions.
  2. Create a Serverless VPC Access connector in the same VPC network as your Cloud SQL instance.
  3. A connector must be in the same project and region as the resource that uses it, but the connector can send traffic to resources in different regions.

    Serverless VPC Access supports communication to VPC networks connected via Cloud VPN and VPC Network Peering.

    Serverless VPC Access does not support legacy networks or Shared VPC.

  4. Configure App Engine to use the connector.
  5. Connect using your instance's private IP and port 1433.

Connecting to Cloud SQL

After you configure App Engine standard environment, you can connect to your Cloud SQL instance. App Engine provides a mechanism that connects using the Cloud SQL Proxy.

Public IP (default)

App Engine standard environment does not support connecting to Cloud SQL for SQL Server over public IP. Use private IP instead.

Private IP

Connecting with TCP

Connect directly using the private IP address and port 1433 for your instance.

Python

To see this snippet in the context of a web application, view the README on GitHub.

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_host = os.environ["DB_HOST"]

# Extract host and port from environment variable DB_HOST
host_args = db_host.split(":")
db_hostname, db_port = host_args[0], int(host_args[1])

# The SQLAlchemy engine will help manage interactions, including automatically
# managing a pool of connections to your database
pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # mssql+pyodbc://<db_user>:<db_pass>@/<host>:<port>/<db_name>?driver=ODBC+Driver+17+for+SQL+Server
    sqlalchemy.engine.url.URL(
        "mssql+pyodbc",
        username=db_user,
        password=db_pass,
        database=db_name,
        host=db_hostname,
        port=db_port,
        query={"driver": "ODBC Driver 17 for SQL Server"},
    ),
    # ... Specify additional properties here.
    # ...
)

Node.js

To see this snippet in the context of a web application, view the README on GitHub.

const createPool = async () => {
  let config = {pool: {}};
  config.user = process.env.DB_USER; // e.g. 'my-db-user'
  config.password = process.env.DB_PASS; // e.g. 'my-db-password'
  config.database = process.env.DB_NAME; // e.g. 'my-database'
  // set the server to '172.17.0.1' when connecting from App Engine Flex
  config.server = process.env.DEPLOYED ? '172.17.0.1' : '127.0.0.1';
  config.port = 1433;

  // ...
  return await mssql.connect(config);
};

Go

To see this snippet in the context of a web application, view the README on GitHub.

var (
	dbUser    = mustGetenv("DB_USER")     // e.g. 'my-db-user'
	dbPwd     = mustGetenv("DB_PASS")     // e.g. 'my-db-password'
	dbTcpHost = mustGetenv("DB_TCP_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	dbPort    = mustGetenv("DB_PORT")     // e.g. '1433'
	dbName    = mustGetenv("DB_NAME")     // e.g. 'my-database'
)

var dbURI string
dbURI = fmt.Sprintf("server=%s;user id=%s;password=%s;port=%s;database=%s;", dbTcpHost, dbUser, dbPwd, dbPort, dbName)

// dbPool is the pool of database connections.
dbPool, err := sql.Open("mssql", dbURI)
if err != nil {
	return nil, fmt.Errorf("sql.Open: %v", err)
}

// ...

return dbPool, nil

C#

To see this snippet in the context of a web application, view the README on GitHub.

            // Equivalent connection string: 
            // "User Id=<DB_USER>;Password=<DB_PASS>;Server=<DB_HOST>;Database=<DB_NAME>;"
            var connectionString = new SqlConnectionStringBuilder()
            {
                // Remember - storing secrets in plaintext is potentially unsafe. Consider using
                // something like https://cloud.google.com/secret-manager/docs/overview to help keep
                // secrets secret.
                DataSource = Environment.GetEnvironmentVariable("DB_HOST"),     // e.g. '127.0.0.1' 
                // Set Host to 'cloudsql' when deploying to App Engine Flexible environment
                UserID = Environment.GetEnvironmentVariable("DB_USER"),         // e.g. 'my-db-user'
                Password = Environment.GetEnvironmentVariable("DB_PASS"),       // e.g. 'my-db-password'
                InitialCatalog = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'

                // The Cloud SQL proxy provides encryption between the proxy and instance
                Encrypt = false,
            };
            connectionString.Pooling = true;
            // ...
            DbConnection connection =
                new SqlConnection(connectionString.ConnectionString);

Ruby

To see this snippet in the context of a web application, view the README on GitHub.

development:
  adapter: sqlserver
  # Configure additional properties here.
  username: <%= ENV["DB_USER"] %>  # e.g. "my-database-user"
  password: <%= ENV["DB_PASS"] %> # e.g. "my-database-password"
  database: <%= ENV.fetch("DB_NAME") { "vote_development" } %>
  host: <%= ENV.fetch("DB_HOST") { "127.0.0.1" }%> # '172.17.0.1' if deployed to GAE Flex
  port: <%= ENV.fetch("DB_PORT") { 1433 }%> 

PHP

To see this snippet in the context of a web application, view the README on GitHub.

        // $username = 'your_db_user';
        // $password = 'yoursupersecretpassword';
        // $db_name = 'your_db_name';
        // $host = "127.0.0.1";

        $dsn = sprintf('sqlsrv:server=%s;Database=%s', $host, $db_name);

        // Connect to the database.
        // Here we set the connection timeout to five seconds and ask PDO to
        // throw an exception if any errors occur.
        $conn = new PDO($dsn, $username, $password, [
            PDO::ATTR_TIMEOUT => 5,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
        ]);
    } catch (TypeError $e) {
        throw new RuntimeException(
            sprintf(
                'Invalid or missing configuration! Make sure you have set ' .
                '$username, $password, $db_name, and $host. ' .
                'The PHP error was %s',
                $e->getMessage()
            ),
            $e->getCode(),
            $e
        );
    } catch (PDOException $e) {
        throw new RuntimeException(
            sprintf(
                'Could not connect to the Cloud SQL Database. Check that ' .
                'your username and password are correct, that the Cloud SQL ' .
                'proxy is running, and that the database exists and is ready ' .
                'for use. For more assistance, refer to %s. The PDO error was %s',
                'https://cloud.google.com/sql/docs/mysql/connect-external-app',
                $e->getMessage()
            ),
            (int) $e->getCode(),
            $e
        );
    }

    return $conn;
};

// Configure the templating engine.
$container['view'] = function () {
    return Twig::create(__DIR__ . '/../views');
};

// Create the application.
$app = AppFactory::create();

// Add the twig middleware
$app->add(TwigMiddleware::createFromContainer($app));

// Setup error handlinmg
$app->addErrorMiddleware(true, false, false);

return $app;

Best practices and other information

You can use the Cloud SQL proxy when testing your application locally. See the quickstart for using the proxy for local testing for detailed instructions.

Connection Pools

Connections to underlying databases may be dropped, either by the database server itself, or by the underlying infrastructure. To mitigate this, we recommend that you use a client library that supports connection pools and automatic reconnection.

For more detailed examples on how to use connection pools, see Managing database connections.

Connection Limits

Cloud SQL imposes a maximum limit on concurrent connections, and these limits may vary depending on the database engine chosen (see Cloud SQL Quotas and Limits).

App Engine has the ability to automatically create more instances as load increases, which may cause you to exceed these limits. To avoid this issue, limit the maximum number of App Engine instances. For more information, see Scaling elements.

Each App Engine instance running in a standard environment cannot have more than 100 concurrent connections to an instance. For PHP 5.5 apps, the limit is 60 concurrent connections.

App Engine applications are subject to request time limits depending on usage and environment. For more information, see how instances are managed in App Engine standard and flexible environments.

App Engine applications are also subject to additional App Engine quotas and limits as discussed on the App Engine Quotas page.

API Quota Limits

App Engine provides a mechanism that connects using the Cloud SQL Proxy, which uses the Cloud SQL Admin API. API quota limits apply to the Cloud SQL Proxy.