All Products
Search
Document Center

Function Compute:Best practices for accessing RDS PostgreSQL

Last Updated:Sep 05, 2025

In Function Compute, states are not shared between different execution environment instances. You can use databases to persist structured data to achieve state sharing. Through Function Compute, you can access cloud databases to perform operations such as data queries and data insertion. This topic uses Python 3 as an example to describe how to access ApsaraDB RDS for PostgreSQL within the same VPC or across VPCs and regions.

Before you start

  • Create an RDS PostgreSQL instance

  • The logic in the index.py sample code in this topic is to query all data in a database table named users. You can modify the table name according to your actual situation and ensure that there is at least one record in the table.

Procedure

Step 1: Set up database whitelist

Scenario 1: Access PostgreSQL database within the same VPC

Important
  • Make sure that the database instance that you create is in the same region as the function that needs to access the database instance.

  • You create a database instance in a zone that is supported by Function Compute. For more information, see Zones supported by Function Compute.

  • If your database instance is not deployed in a zone that is supported by Function Compute, create a vSwitch in your VPC. The vSwitch must be in the same zone as Function Compute. In addition, you must specify the vSwitch ID in the VPC configuration of the specified service in Function Compute. Because different vSwitches within the same VPC can communicate with each other through the internal network, Function Compute can access resources in other zones within the VPC through this vSwitch. For specific steps, see What should I do if I encounter the "vSwitch is in unsupported zone" error?.

  1. Visit RDS instance list, select a region at the top, click the target instance ID, click Basic Information, click View Connection Details next to VPC to view the VPC information of PostgreSQL.

    image

  2. Log on to the Function Compute console, create a Python Web function, enable VPC access for the function, and configure the target VPC resource.

    Note

    Make sure that the VPC configured for the function is the same as the VPC bound to the database instance.

    image

  3. On the function details page, choose Configuration > Network, and then on the Network page, obtain the CIDR block of the vSwitch in the function configuration.

    image

  4. Add the CIDR block of the vSwitch obtained in the previous step to the access whitelist.

    Important

    Use an IP address whitelist to authorize functions to access the database. Do not use the security group mode. Otherwise, functions may occasionally fail to connect to the database, which affects the businesses.

    1. Log on to the RDS Management Console, select a region at the top, and then click the target instance ID.

    2. In the left-side navigation pane, select Whitelist And Security Groups, on the Whitelist Settings tab, find the target whitelist template name, and click Modify on the right.

    3. In the Modify Whitelist Group panel that appears, enter the CIDR block of the vSwitch bound to the target instance in the Whitelist input box, and then click OK.

      image

After the configuration is complete, the function can access the PostgreSQL database through the internal network address of the database.

Scenario 2: Access PostgreSQL database across VPCs or regions

Different VPCs and regions are completely logically isolated from each other. Under normal circumstances, databases cannot be accessed across VPCs and regions. If you need to access a database across VPCs or regions, you can configure a static public IP address for the function. The system will create a public NAT Gateway in the VPC bound to the function, allowing access to the database through the public IP address.

  1. Visit RDS instance list, select a region at the top, click the target instance ID, click Basic Information, click View Connection Details next to VPC to view the VPC information of PostgreSQL.

    image

  2. Log on to the Function Compute console, create a Python Web function, on the function details page, choose Configuration > Network, in the Network panel, configure a static public IP address for the function, and then click Deploy.

    image

  3. In the Static Public IP Configuration dialog box that appears, check the prompt box, and then click OK. After the configuration is complete, set the Allow Default NIC To Access Internet parameter to No to make the configured static public IP address take effect. For more details, see Configure a static public IP address.

  4. On the function details page, choose Configuration > Network, and then on the Network page, obtain the static public IP address configured for the function.

    image

  5. Add the static public IP address obtained in the previous step to the access whitelist.

    Important

    Use an IP address whitelist to authorize functions to access the database. Do not use the security group mode. Otherwise, functions may occasionally fail to connect to the database, which affects the businesses.

    1. Log on to the RDS Management Console, select a region at the top, and then click the target instance ID.

    2. In the left-side navigation pane, select Whitelist And Security Groups, on the Whitelist Settings tab, find the target whitelist template name, and click Modify on the right.

    3. In the Modify Whitelist Group panel that appears, enter the static public IP address to be bound in the Whitelist input box, and then click OK.

      image

After the configuration is complete, the function can access the PostgreSQL database through the public network address of the database.

Step 2: Access PostgreSQL database in the function

  1. Log on to the Function Compute console, find the target function in the function list, on the function details page, click the Code tab, and write the following sample code in the code editor according to the database table.

    from flask import Flask, jsonify
    import psycopg2  # Need to install psycopg2 library first
    import os
    import sys
    from datetime import datetime
    import logging
    
    
    app = Flask(__name__)
    
    # Global variable for storing PostgreSQL singleton connection
    _postgresql_connection = None
    
    # Create database connection (singleton pattern)
    def getConnection():
        global _postgresql_connection
        try:
            # If the connection already exists and is not disconnected, return it directly
            if _postgresql_connection is not None:
                try:
                    # Test if the connection is valid (simple command test)
                    with _postgresql_connection.cursor() as cursor:
                        cursor.execute("SELECT 1")  # Simple query to test connection status
                        result = cursor.fetchone()
                        if result and result[0] == 1:
                            return _postgresql_connection
                except psycopg2.OperationalError:
                    # If the connection is disconnected, reset it
                    _postgresql_connection = None
    
            # If the connection does not exist or is disconnected, recreate it
            _postgresql_connection = psycopg2.connect(
                database=os.environ['DATABASE'],
                user=os.environ['USER'],
                password=os.environ['PASSWORD'],
                host=os.environ['HOST'],
                port=os.environ['PORT'],
            )
            return _postgresql_connection
        except Exception as e:
            print(f"ERROR: Unexpected error: Could not connect to PostgreSQL instance: {e}")
            raise
    
    
    @app.route('/', defaults={'path': ''})
    @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
    def hello_world(path):
        conn = getConnection()
        try:
            with conn.cursor() as cursor:
                # Query all records in the users table, modify users table according to the actual table name
                sql = "SELECT * FROM users"
                cursor.execute(sql)
                result = cursor.fetchall()
                
                columns = [desc[0] for desc in cursor.description]  # Get the list of field names
    
                # Convert query results to a list of dictionaries
                users = []
                for row in result:
                    user = {}
                    for idx, column_name in enumerate(columns):
                        value = row[idx]
                        if isinstance(value, datetime):  # Handle date type fields
                            user[column_name] = value.strftime('%Y-%m-%d %H:%M:%S')
                        else:
                            user[column_name] = value
                    users.append(user)
                    
                if users:
                    # Return JSON response for all users
                    return jsonify(users), 200
                else:
                    # If no users are found, return 404 error
                    return jsonify({'error': 'No users found'}), 404
    
        except Exception as e:
            logging.error(f"Error occurred during database operation: {e}")
            return jsonify({'error': 'Database error'}), 500
    
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=9000)
    
  2. Install the required dependencies for the function: pip3 install -t . psycopg2 , click Deploy Code to make the dependencies take effect. For detailed steps, see Install dependencies through the console Web IDE terminal.

  3. On the Function Details page, choose Configuration > Environment Variables, click Edit, and configure the following environment variables in the Environment Variables panel.

    Environment Variable Name

    Environment Variable Value

    Description

    HOST

    pgm-*****q.pg.rds.aliyuncs.com

    The access address of the database instance. If you choose the PostgreSQL database within the same VPC scenario, set this environment variable value to the internal network address of the database. If you choose the Access PostgreSQL database across VPCs or regions scenario, set this environment variable value to the external network address of the database.

    Visit Instance List, select a region at the top, and then click the target instance ID. In the left-side navigation pane, click Database Connection, and in the Database Connection information area, obtain the connection address information for connecting to the database.

    PORT

    5432

    Database internal network port number

    USER

    *****

    The account name created in the PostgreSQL instance.

    PASSWORD

    *****

    Database Password

    DATABASE

    *****

    The database name created in the instance.

  4. On the function details page, select the Code tab, click Test Function, and view the return result after successful execution.

    image

More information

  • For more examples of accessing RDS PostgreSQL databases, see Function Compute Python accessing PostgreSQL database.

  • For information about how to view the vSwitch information configured for Function Compute and how to allow the vSwitch CIDR block of Function Compute in the RDS MySQL database, see Configure network and Configure a whitelist for PostgreSQL respectively.

  • If database access fails, you need to troubleshoot based on the problem symptoms. For details, see Common causes of database access failure.

  • If you want to use the Serverless Devs command-line tool to create functions and access ApsaraDB RDS for PostgreSQL databases, see the following steps.

    Click here to view Serverless Devs operation steps

    1. Install Serverless Devs and Docker, and add key information. For specific operations, see Quick Start.

    2. Create a code directory mycode, prepare the s.yaml file and code file app.py. For the sample code of app.py, see the sample code provided in Step 2: Access PostgreSQL database in the function. The example of the s.yaml file is as follows.

      The following s.yaml example is applicable to the scenario of accessing SQL Server database within the same VPC. If you need to access the database across VPCs and regions, see Scenario 2: Access PostgreSQL database across VPCs or regions.

      # ------------------------------------
      #   Official manual: https://manual.serverless-devs.com/user-guide/aliyun/#fc3
      #   Tips: https://manual.serverless-devs.com/user-guide/tips/
      #   If you have any questions, join the DingTalk group 33947367.
      # ------------------------------------
      edition: 3.0.0
      name: hello-world-app
      access: "default"
      
      vars: # Global variables
        region: "cn-hangzhou"  # If you choose the scenario of accessing RDS database within the same VPC, make sure the function is deployed in the same region as the RDS database
      
      resources:
        hello_world:
          component: fc3 
          actions:       
            pre-${regex('deploy|local')}: 
              - component: fc3 build 
          props:
            region: ${vars.region}              
            functionName: "start-python-PostgreSQL"
            runtime: custom.debian10
            description: 'hello world by serverless devs'
            timeout: 10
            memorySize: 512
            cpu: 0.5
            diskSize: 512
            code: ./code
            customRuntimeConfig:
              port: 9000
              command:
                - python3
                - app.py
            internetAccess: true
            vpcConfig:
              vpcId: vpc-bp1dxqii29fpkc8pw**** # VPC ID where the database instance is located
              securityGroupId: sg-bp12ly2ie92ixrfc**** # Security group ID
              vSwitchIds: 
                 - vsw-bp1ty76ijntee9z83**** # Make sure the CIDR block of this vSwitch has been configured in the database instance access whitelist
            environmentVariables:
              PYTHONPATH: /code/python
              PATH: /code/python/bin:/var/fc/lang/python3.10/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin
              HOST: rm-*****.sqlserver.rds.aliyuncs.com  # Database endpoint
              USER: ******   # Account name created in the instance
              PASSWORD: *****     # Database Password
              DATABASE: *****     # Database name created in the instance.
              PORT: "5432"        # Database port
              

      The directory structure of the code is as follows.

      ├── code
      │ ├── app.py
      │ └── requirements.txt
      └── s.yaml

      The dependencies specified in the requirements.txt file are shown below.

      flask==2.2.5
      psycopg2==2.9.10
    3. Run the following command to build the project.

      sudo s build --use-docker
    4. Run the following command to deploy the project.

      sudo s deploy -y
    5. Run the following command to invoke the function.

      Note

      Make sure that the CIDR block of the vSwitch configured for the function has been added to the database instance access whitelist. For specific operations, see Step 4.

      sudo s invoke -e "{}"