PGVector on CloudSQL for GCP

PGVector on CloudSQL for GCP
Adham Sersour โ€ข Generative AI โ€ข 28 July 2025

A practical guide to automating vector search infrastructure with Terraform and Makefiles, streamlining the deployment of PGVector on Cloud SQL and letting you focus on building powerful semantic applications.

๐Ÿ”— GitHub Repository: View on GitHub

๐Ÿ“‹ Why Infrastructure as Code May Help with Vector Search

Manual cloud setup can sometimes be time-consuming and prone to inconsistenciesโ€”a missed configuration step might lead to unexpected behavior or security concerns. When building a vector search application, a RAG system, or a semantic recommendation engine for production, having a reliable infrastructure approach alongside your application code could be beneficial.

Many of us have experienced the initial satisfaction of setting up resources through the Google Cloud Console, only to later struggle when trying to recreate that environment or share the exact setup with teammates. Without version control or documentation, reproducing environments consistently can be challenging. While manual setup works well for quick experiments, teams often look for more systematic approaches when moving toward production.

๐Ÿ’ก Vector Search Context: Vector search represents a specialized approach to storing and querying high-dimensional vectors efficiently. When working with embeddings for recommendation or RAG applications, having stable and reliable infrastructure can be particularly important.

We've found that combining Terraform for infrastructure definition with Makefiles for operation simplification might help address some common challenges. This approach allows you to define your cloud environment as code and potentially automate deployments, which could help maintain consistency across environments and reduce time spent on manual configuration.

By turning your vector database stack into code, you get:

flowchart TD User([๐Ÿง‘โ€๐Ÿ’ป Developer]) --> |Uses| Makefile[๐Ÿ“‹ Makefile
Command Interface] Makefile --> |Executes| TerraformCommands[โš™๏ธ Terraform Operations] subgraph "Repository Structure" Makefile TerraformDir[๐Ÿ“ terraform-sql
Infrastructure Config] EnvDir[๐ŸŒ environments
Environment Configs] ModulesDir[๐Ÿงฉ modules
Reusable Components] TutorialsDir[๐Ÿ“š tutorials
Example Apps] TerraformDir --> EnvDir TerraformDir --> ModulesDir end subgraph "Environment Configurations" EnvDir --> DevEnv[๐Ÿงช dev
Development] EnvDir --> PreprodEnv[๐Ÿ”„ preprod
Pre-production] EnvDir --> ProdEnv[๐Ÿญ prod
Production] end subgraph "Terraform Modules" ModulesDir --> ProjectModule[๐Ÿ—๏ธ project
GCP Setup] ModulesDir --> VPCModule[๐ŸŒ vpc
Network Config] ModulesDir --> SQLModule[๐Ÿ—„๏ธ sql
Database Config] end subgraph "Terraform Commands" TerraformCommands --> TFInit[๐Ÿš€ terraform init] TerraformCommands --> TFPlan[๐Ÿ” terraform plan] TerraformCommands --> TFApply[โœ… terraform apply] TerraformCommands --> TFDestroy[๐Ÿ’ฅ terraform destroy] end subgraph "Database Operations" Makefile --> DBCommands[๐Ÿ—„๏ธ Database Commands] DBCommands --> SetupDB[๐Ÿ”ง Setup Database
Schema & Extensions] DBCommands --> SampleData[๐Ÿ“Š Load Sample Data] DBCommands --> CheckDB[โœ… Verify Setup] DBCommands --> RunDemo[๐Ÿš€ Run Demo Queries] end subgraph "GCP Resources" ProjectModule --> GCPProject[โ˜๏ธ GCP Project] GCPProject --> APIs[๐Ÿ”Œ Enabled APIs
SQL, IAM, Compute] GCPProject --> ServiceAccts[๐Ÿ”‘ Service Accounts] VPCModule --> VPCNetwork[๐ŸŒ VPC Network] VPCModule --> FirewallRules[๐Ÿ”ฅ Firewall Rules] VPCModule --> PrivateAccess[๐Ÿ”’ Private Access] SQLModule --> CloudSQL[๐Ÿ—„๏ธ PostgreSQL Instance] CloudSQL --> PGVector[๐Ÿง  pgvector Extension] PGVector --> VectorDB[๐Ÿ“Š Vector Database
with Indexes] end DevEnv --> |Configures| DevResources[๐Ÿงช Dev Config
Public IP, Open Firewall
Lower Specs, ZONAL] PreprodEnv --> |Configures| PreprodResources[๐Ÿ”„ Preprod Config
Private IP, VPC
Medium Specs, ZONAL] ProdEnv --> |Configures| ProdResources[๐Ÿญ Prod Config
Private IP, Strict VPC
High Specs, REGIONAL] DevResources --> GCPProject PreprodResources --> GCPProject ProdResources --> GCPProject VectorDB --> Applications[๐Ÿš€ Vector Applications] Applications --> UseCases[๐ŸŽฏ Use Cases
Recommendations, RAG
Semantic Search] style User fill:#E8F4FD,stroke:#2C5AA0,stroke-width:2px style Makefile fill:#FFF2CC,stroke:#B7950B,stroke-width:2px style TerraformCommands fill:#E8F6F3,stroke:#1B5E4F,stroke-width:2px style DBCommands fill:#F4ECF7,stroke:#7D3C98,stroke-width:2px style GCPProject fill:#FADBD8,stroke:#A93226,stroke-width:2px style VectorDB fill:#E1F5FE,stroke:#1976D2,stroke-width:2px style Applications fill:#EAEDED,stroke:#566573,stroke-width:2px

Comprehensive architecture showing repository structure, workflow, and GCP resources

๐Ÿ”

Consistency

Every environment is identical, every time

โšก

Speed

Deploy or tear down resources in minutes, not hours

๐Ÿ“

Version Control

Track changes, roll back, and collaborate with your team

๐Ÿ“ˆ

Scalability

Grow your infrastructure as your needs evolve

๐Ÿงฌ

Reproducibility

Create identical environments across dev, pre-production, and production

๐Ÿ“š

Documentation

Your code serves as living documentation of your architecture

๐Ÿ’ธ

Cost Control

Easily destroy resources when not in use, reducing cloud expenses

โš ๏ธ Team Experience Varies: Some teams have reported significant time savings and reduced incidents after adopting Infrastructure as Code approaches, though results vary based on team expertise and specific use cases.

โœจ Key Features

Our PGVector on CloudSQL solution provides several key advantages:

๐Ÿ—๏ธ Infrastructure as Code

Terraform-based provisioning of Google Cloud SQL PostgreSQL instances with pgvector extension

๐Ÿ”„ Simplified Operations

All database operations managed directly through intuitive Makefile commands

๐ŸŒ Multi-Environment Support

Separate configurations for development, pre-production, and production environments

๐Ÿš€ Quick Setup

Easy-to-follow setup process with comprehensive documentation and examples

๐Ÿ—๏ธ Terraform Architecture for PostgreSQL Vector Search

Ready to build something cool? Let's get our hands dirty with a complete PostgreSQL setup that has pgvector extensions baked in. No more manual steps or forgotten configurationsโ€”just pure, repeatable infrastructure.

The repository is organized using a modular approach with separate environments, making it enterprise-ready from day one:

.
โ”œโ”€โ”€ ๐Ÿ“„ Makefile                # Main command interface for all operations
โ”œโ”€โ”€ ๐Ÿ“ terraform-sql/          # Terraform configuration for Cloud SQL
โ”‚   โ”œโ”€โ”€ ๐Ÿ“ environments/       # Environment-specific configurations
โ”‚   โ”‚   โ”œโ”€โ”€ ๐Ÿ“ dev/            # Development environment
โ”‚   โ”‚   โ”œโ”€โ”€ ๐Ÿ“ preprod/        # Pre-production environment
โ”‚   โ”‚   โ””โ”€โ”€ ๐Ÿ“ prod/           # Production environment
โ”‚   โ””โ”€โ”€ ๐Ÿ“ modules/            # Reusable Terraform modules
โ”‚       โ”œโ”€โ”€ ๐Ÿ“ project/        # GCP project configuration
โ”‚       โ”œโ”€โ”€ ๐Ÿ“ sql/            # Cloud SQL instance configuration
โ”‚       โ””โ”€โ”€ ๐Ÿ“ vpc/            # Network configuration
โ””โ”€โ”€ ๐Ÿ“ how_to_tutorials/       # Example applications and demos
    โ””โ”€โ”€ ๐Ÿ“ semantic_demo/      # Semantic search demo for product recommendations
flowchart TD Makefile[๐Ÿ“‹ Makefile\nMain Command Interface] subgraph "terraform-sql" Envs[๐ŸŒ environments] Mods[๐Ÿงฉ modules] end subgraph "environments" Dev[๐Ÿงช dev] Preprod[๐Ÿ”„ preprod] Prod[๐Ÿญ prod] end subgraph "modules" Project[๐Ÿ—๏ธ project] SQL[๐Ÿ—„๏ธ sql] VPC[๐ŸŒ vpc] end Tutorials[๐Ÿ“š how_to_tutorials\nExample Apps] SemanticDemo[๐Ÿ’ก semantic_demo\nProduct Recommendations Demo] Makefile --> |"calls"| Envs Makefile --> |"calls"| Mods Envs --> Dev Envs --> Preprod Envs --> Prod Mods --> Project Mods --> SQL Mods --> VPC Tutorials --> SemanticDemo style Makefile fill:#FFF2CC,stroke:#B7950B style Envs fill:#E8F6F3,stroke:#1B5E4F style Mods fill:#F4ECF7,stroke:#7D3C98 style Dev fill:#E1F5FE,stroke:#1976D2 style Preprod fill:#EAEDED,stroke:#566573 style Prod fill:#FADBD8,stroke:#A93226 style Project fill:#E8F4FD,stroke:#2C5AA0 style SQL fill:#FFF2CC,stroke:#B7950B style VPC fill:#E8F6F3,stroke:#1B5E4F style Tutorials fill:#FADBD8,stroke:#A93226 style SemanticDemo fill:#EAEDED,stroke:#566573

Visual overview of the repository structure and modular organization for Terraform-based PGVector deployment.

The architecture aims to be straightforward while addressing common infrastructure needs:

  1. ๐Ÿ๏ธ A dedicated GCP project created by Terraform providing some isolation between projects
  2. ๐Ÿ”’ Custom VPC with private network connectivity for enhanced security
  3. ๐ŸŒ Cloud SQL PostgreSQL instance with configurable access options (public access limited to dev environments)
  4. ๐Ÿงฉ Vector database configuration for storing embeddings
  5. ๐Ÿšฆ Environment separation for dev, preprod, and prod following common DevOps practices

๐Ÿ“Š What Does the Terraform Setup Do?

The modular configuration in terraform-sql automates the following:

  • Initializes your Google Cloud project and authenticates Terraform โ˜๏ธ
  • Activates essential APIs: Cloud SQL, networking, IAM, Compute, and more ๐Ÿ”Œ
  • Creates service accounts with proper permissions ๐Ÿ”‘
  • Creates a secure VPC network with private subnet ranges ๐Ÿ›ก๏ธ
  • Configures firewall rules for secure communication ๐Ÿ”ฅ
  • Sets up Private Service Access for Cloud SQL connections ๐ŸŒ
  • Provisions a Cloud SQL PostgreSQL instance with proper sizing based on environment ๐Ÿ“Š
  • Configures it for the pgvector extension, enabling vector similarity search ๐Ÿง 
  • Sets up database users with secure passwords ๐Ÿ‘ค
  • Configures automated backups and high availability options ๐Ÿ’พ
  • Separate configurations for dev, preprod, and prod environments ๐Ÿงช
  • Parameterization through variables for project name, region, database size, and more ๐Ÿงฎ
  • Uses Terraform workspaces to isolate state between environments ๐Ÿ“‹
  • Provides connection details and resource IDs for use in your application or CI/CD pipelines ๐Ÿ”—
  • Outputs important information like database IP, connection names, and project details ๐Ÿ“

๐Ÿ” Security Considerations

The repository implements different security configurations for each environment. Let's look at the networking module which includes thoughtful firewall rules:

# Allow PostgreSQL access from authorized sources
resource "google_compute_firewall" "allow_postgres" {
  name    = "${var.name_prefix}-allow-postgres"
  network = google_compute_network.vpc_network.self_link

  allow {
    protocol = "tcp"
    ports    = ["5432"]
  }

  # In development, this might be more permissive
  # In production, this should be limited to specific sources
  source_ranges = var.authorized_networks
  target_tags   = ["cloudsql"]
  description   = "Allow PostgreSQL access from authorized networks"
}

# Allow internal traffic within the VPC
resource "google_compute_firewall" "allow_internal" {
  name    = "${var.name_prefix}-allow-internal"
  network = google_compute_network.vpc_network.self_link

  allow {
    protocol = "all"
  }

  source_ranges = [var.subnet_cidr]
  description   = "Allow all internal traffic within the VPC"
}

๐Ÿ”‘ Key Security Features

  • ๐Ÿ”’ Environment-specific security settings (dev is more open, prod is locked down)
  • ๐Ÿ”‘ Parameterized authorized networks for database access, not hard-coded
  • ๐Ÿ›ก๏ธ Private Service Access for Cloud SQL, ensuring database isn't publicly exposed in production
  • ๐Ÿ‘ฎโ€โ™€๏ธ IAM role separation with principle of least privilege
  • ๐Ÿงฉ Separate service accounts for different components
๐Ÿšจ Production Checklist:
  • ๐ŸŽฏ Set authorized_networks to specific IP ranges in prod environment
  • ๐Ÿ‘ค Enable Cloud SQL IAM authentication for user access
  • ๐Ÿ—๏ธ Store secrets in Secret Manager, not in Terraform variables
  • ๐Ÿ“Š Enable audit logging and monitoring
  • ๐Ÿ” Implement database encryption at rest and in transit

The repository suggests a progressive security model that allows starting with more permissive settings in development environments while implementing stricter controls in production. We recommend carefully reviewing security settings before deploying to productionโ€”security considerations are an essential part of any deployment strategy.

๐Ÿšฆ Simplified Deployment: Using the Makefile

One of the standout features of this project is its streamlined approach using Makefiles. You can deploy and manage your entire vector search infrastructure with simple commands:

# Copy the example environment file
cp .env.example .env
# Edit with your credentials

# Copy the example variables file
cp terraform-sql/environments/dev/terraform.tfvars.example terraform-sql/environments/dev/terraform.tfvars
# Edit terraform.tfvars with your specific configuration values
# Initialize Terraform for your chosen environment
make tf-init ENV=dev

# Review what will be created
make tf-plan ENV=dev

# Apply the changes
make tf-apply ENV=dev
# Create database schema with pgvector extension
make setup-db ENV=dev

# Add sample product data
make add-sample-data ENV=dev

# Verify database setup
make check-db ENV=dev

# Run simple demo queries
make run-simple-demo ENV=dev
# Check current environment settings
make env

# Connect directly to the database
make connect-db ENV=dev

# Clean up when done
make tf-destroy ENV=dev

This Makefile approach attempts to simplify complex commands, which might help team members collaborate more effectively without needing to memorize every technical detail.

๐Ÿง‘โ€๐Ÿ’ป Post-Deployment: Setting Up pgvector

After your infrastructure is deployed, you need to set up the vector extension. Traditionally this would require multiple manual steps, but our Makefile simplifies this:

make setup-db ENV=dev

This single command connects to your database and runs:

CREATE EXTENSION IF NOT EXISTS vector;

-- Create a database for our application
CREATE DATABASE vector_search;
\c vector_search

-- Create a table for semantic product data
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    description TEXT,
    category TEXT,
    price DECIMAL(10, 2),
    embedding VECTOR(1536) -- For OpenAI embeddings, adjust as needed
);

-- Create an index for fast similarity search
CREATE INDEX ON products USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);
๐Ÿ”ฎ Advanced Tip: You can adjust the vector dimension (1536 here is for OpenAI's text-embedding-ada-002) based on your embedding model of choice. All this is handled through the Makefile, so you don't need to remember complex SQL commands.

๐Ÿค” Potential Use Cases

This infrastructure can support various vector-based applications:

Vector Database Use Cases and Applications
Use Case Description Implementation Benefits
๐Ÿ›’ Product Recommendations Deliver personalized suggestions using semantic similarity Higher conversion rates, improved UX
๐Ÿค– Retrieval-Augmented Generation (RAG) Enhance chatbots and LLMs with context-aware retrieval More accurate responses, reduced hallucinations
๐Ÿ” Semantic Search Go beyond keywords to find relevant documents, products, or answers Better search relevance, natural language queries
๐Ÿงน Content Deduplication Identify near-duplicate items in large datasets Data quality improvement, storage optimization
๐Ÿšจ Anomaly Detection Spot unusual patterns by comparing vector representations Early threat detection, quality assurance
๐ŸŽฏ Personalization Engines Tailor user experiences based on semantic profiles Increased engagement, user satisfaction

๐Ÿš€ Success Story: E-commerce Recommendation Engine

Context: A mid-sized e-commerce platform implemented vector-based product recommendations using similar infrastructure, resulting in a 35% increase in click-through rates and 20% boost in sales conversion.

  • Semantic Understanding: Products were matched based on meaning, not just keywords
  • Real-time Performance: Sub-100ms query responses enabled dynamic recommendations
  • Scalable Infrastructure: Terraform automation allowed rapid scaling during peak seasons
  • A/B Testing: Multiple environments enabled safe experimentation

๐Ÿงฌ The Power of Reproducibility

One potential benefit of Infrastructure as Code is improved reproducibility. Many of us have faced challenges with environment inconsistencies or struggled to remember exact setup steps.

With the Terraform and Makefile approach described here, you might find it easier to:

  • โฑ๏ธ
    Create similar testing environments more efficiently

    Spin up identical environments in minutes rather than hours of manual configuration

  • ๐ŸŒ
    Deploy to different regions using the same configuration base

    Multi-region deployment becomes a simple parameter change

  • ๐Ÿ”
    Recover from accidental resource deletions by reapplying your configuration

    Disaster recovery becomes a matter of running terraform apply

  • ๐Ÿ‘‹
    Onboard new team members by sharing code rather than lengthy setup instructions

    New developers can be productive in hours, not days

This approach could potentially reduce documentation overhead and make collaboration more straightforward, though every team's experience will vary based on their specific needs and existing workflows.

๐Ÿ† Production-Ready Deployment Tips

Ready to go beyond the demo and into production? The repository is already structured to support this journey, with separate environments for dev, preprod, and prod. Here are some hard-learned lessons to save you some late-night troubleshooting sessions:

Environment Differences

Environment Access Network Resources Availability Protection
๐Ÿงช dev Public IP Open firewall Lower specs ZONAL No deletion protection
๐Ÿ”„ preprod Private IP only VPC network Medium specs ZONAL No deletion protection
๐Ÿญ prod Private IP only Strict VPC Higher specs REGIONAL Deletion protection + backups

Deployment Steps

  1. Environment progression (follow the path to production):
    • Start with dev environment to test your configuration ๐Ÿงช
    • Validate in preprod with production-like settings ๐Ÿ”
    • Apply strict security rules only in prod ๐Ÿ›ก๏ธ
  2. Secure your database (because security matters):
    • In the prod environment variables, restrict authorized_networks to specific IP ranges ๐Ÿ”’
    • Enable Private Service Connect for production deployments ๐Ÿ”
    • Enable Cloud SQL IAM authentication by setting enable_iam_auth = true in your tfvars ๐Ÿ‘ค
  3. Optimize for performance (vector search gets hungry):
    • The repository supports different instance sizes per environment:
      • db-f1-micro for dev testing
      • db-custom-2-7680 for preprod
      • db-custom-4-15360 for production workloads ๐Ÿ‹๏ธ
    • Vector search loves RAMโ€”use the high-memory options in the variables ๐Ÿง 
    • Benchmark with real data in preprod before going to production โณ
  4. Manage secrets properly (no passwords in GitHub, please):
    • The repository includes .gitignore for .tfvars files ๐Ÿšซ
    • Use environment variables for sensitive data in CI/CD pipelines ๐Ÿ”‘
    • Consider using the google_secret_manager_secret resource ๐Ÿ—๏ธ
    • Use Terraform's sensitive = true marking for outputs ๐Ÿ™ˆ
  5. Use the environment-specific Makefiles:
    • Follow the principle of "make it easy to do the right thing" ๐ŸŽฏ
    • Take advantage of the input validation built into the modules ๐Ÿ”
  6. Monitoring saves lives (or at least your weekend):
    • Set up Cloud Monitoring alerts before you need them ๐Ÿšจ
    • Enable the automated backups using the backup_configuration in the SQL module ๐Ÿ’พ
    • Consider read replicas for high-traffic applications by setting read_replica_size ๐Ÿ“š

๐ŸŽ‰ Conclusion

By automating your vector search infrastructure with Terraform and Makefiles, you might find your workflow becoming more streamlined and reproducible. Rather than clicking through console interfaces and trying to remember all the steps, this approach offers a way to document and version your infrastructure setup.

When your database configuration is defined in code, it becomes something you can collaboratively work on, review, and improve over time โ€“ a shared resource for your team.

๐ŸŽฏ Key Project Features

The pgvector_cloudsql_gcp repository attempts to implement this approach with features like:

  • ๐ŸŒ Environment Separation: Different configurations for dev, preprod, and prod environments
  • ๐Ÿงฉ Modular Design: Reusable modules for various infrastructure components
  • ๐Ÿ›ก๏ธ Progressive Security: Security controls that adapt to each environment
  • โš™๏ธ Operation Helpers: Makefile commands to assist with common tasks
  • ๐Ÿ“ Organized Structure: A folder organization that aims to be logical and maintainable

Infrastructure as code can be a valuable approach that helps bridge the gap between experimental demos and production-ready systems. For vector search applications where configuration details can significantly impact performance, this approach might save you considerable time and reduce potential errors.

๐Ÿ’ก Interested in trying this approach? Feel free to explore the repo and experiment with the commandsโ€”we'd love to hear about your experience and how you adapt it to your specific needs.

๐Ÿ“š Additional Resources

๐Ÿ“ Coming Next: "Vector Database Applications" - Where we'll explore practical implementations like recommendation systems, retrieval-augmented generation (RAG), semantic search, and other real-world use cases.

We'd welcome your feedback, suggestions, or contributions to help improve this project.

Recommended Posts

How do you feel about this article?

Comments

No comments yet. Be the first to comment!