title: How to pass 'quotaUser' parameter for queries to MySQL server in GCP from cloud function?
body: <p>I'm working on a project right now that shows a list of items. To retrieve this data, the page calls a callable cloud function which queries the data from a MySQL server. This MySQL server, like our cloud functions, is part of our project on the Google Cloud Platform.</p>
  <p>The page that shows the items is used quite a lot by our customer and last Tuesday they reported some problems that the data wasn't showing or took a long time to show up.
  Having looked at the cloud function logs at that time, we see a lot of timeouts followed by a few of these errors:</p>
  <blockquote>
  <p>CloudSQL warning: your action is needed to update your function and avoid potential disruptions. Please see <a href="https://cloud.google.com/functions/docs/sql#troubleshooting" rel="nofollow noreferrer">https://cloud.google.com/functions/docs/sql#troubleshooting</a> for additional details: googleapi: Error 429: Quota exceeded for quota group 'default' and limit 'Queries per user per 100 seconds' of service 'sqladmin.googleapis.com' for consumer 'project_number:[some number]'., rateLimitExceeded</p>
  </blockquote>
  <p>I'm not entirely sure if this is the cause of the issue, but it does seem like something we should do something about anyway.
  As I understand it, we can send 300 queries per user per 100 seconds to the MySQL server. So about 3 per second. The cloud function itself only sends 2 queries to the server. One to retrieve the data for the current page with the applied filters and another one to get a total record count.
  However, we don't send any user info when performing the query. So I think that if 150 users each trigger the callable, 300 queries will be performed and counted towards the quota as if they were done by a single user. Because it's a server, the cloud function, that actually performs the query. The error also mentions the quota group 'default'.</p>
  <p>The following page tells me that I should be able to pass a 'quotaUser' parameter to specify a specific user that requests should count towards for the quota.</p>
  <p><a href="https://cloud.google.com/apis/docs/capping-api-usage#limiting_requests_per_second_per_user" rel="nofollow noreferrer">https://cloud.google.com/apis/docs/capping-api-usage#limiting_requests_per_second_per_user</a></p>
  <p>However... I have no idea how to pass that parameter with our queries. I've read something that this parameter can be used in the url parameters or in the headers, but we are using the Node.js mysql package to perform these queries, and I don't know how to tell it to send this parameter.
  This is the guide we followed to set up the mysql connection. We are using the same mysql package.</p>
  <p><a href="https://cloud.google.com/sql/docs/mysql/connect-functions#node.js" rel="nofollow noreferrer">https://cloud.google.com/sql/docs/mysql/connect-functions#node.js</a></p>
  <p>I would think that if a GCP guide tells us to use that mysql package, it should also somehow be possible to specify this quotaUser.</p>
  <p>If anyone can help me out with this, it would be greatly appreciated. I'm a bit stuck and can't find any documentation or examples on how to pass this parameter for MySQL queries.</p>
  <p>This is how we connect to the MySQL server:</p>
  <pre><code>import { config } from '../config';
  import { createConnection, Connection, ConnectionConfig } from 'mysql';
  
  export function connectToMySQLDatabase(): Connection {
      const connectionName: string | undefined = process.env.INSTANCE_CONNECTION_NAME || `${config.firebaseProjectId}:${config.mysqlConfig.regionId}:${config.mysqlConfig.instanceId}`;
      const dbUser: string | undefined = process.env.SQL_USER || config.mysqlConfig.user;
      const dbPassword: string | undefined = process.env.SQL_PASSWORD || config.mysqlConfig.password;
      const dbName: string | undefined = process.env.SQL_NAME || config.mysqlConfig.databaseName;
  
      const mysqlConfig: ConnectionConfig = {
          user: dbUser,
          password: dbPassword,
          database: dbName,
          dateStrings: true,
          socketPath = `/cloudsql/${connectionName}`;
      };
  
      return createConnection(mysqlConfig);
  }
  </code></pre>
  <p>And how we perform a query:</p>
  <pre><code>exports.itemQuerySQL = functions
      .region(config.region)
      .runWith({
          timeoutSeconds: 60,
          memory: '1GB'
      })
      .https
      .onCall(async (request: GetItemsRequest, context) =&gt; {
          const mysqlConnection: Connection = connectToMySQLDatabase();
          try {
              return await queryItems(request, mysqlConnection);
          } catch (error) {
              throw error;
          }
          finally {
              mysqlConnection.end();
          }
      });
  
  async function queryItems(request: GetItemsRequest, mysqlConnection: Connection): Promise&lt;CallableQueryResponse&lt;string&gt;&gt; {
      let query = '';
      let values = [];
  
      // Removed a bunch of code irrelevant to the issue that builds up the query and values array.
  
      const results: any[] = await performQuery(mysqlConnection, sqlQuery, sqlQueryValues);
      return {
          results: results,
          // Some other properties
      };
  }
  
  async function performQuery(mysqlConnection: Connection, query: string, values?: (string | string[] | number | null)[]): Promise&lt;any&gt; {
      return new Promise((resolve: (value?: unknown) =&gt; void, reject: (reason?: any) =&gt; void): void =&gt; {
          mysqlConnection.query(query, values, (error: MysqlError, results: any) =&gt; {
              if (error) {
                  return reject(error);
              } else {
                  return resolve(results);
              }
          });
      });
  }
  </code></pre>
  <p>Besides the code that constructs the query itself, I also left out most of the error handling to keep these examples small.</p>