TigerData logo
TigerData logo
  • Product

    Tiger Cloud

    Robust elastic cloud platform for startups and enterprises

    Agentic Postgres

    Postgres for Agents

    TimescaleDB

    Postgres for time-series, real-time analytics and events

  • Docs
  • Pricing

    Pricing

    Enterprise Tier

  • Developer Hub

    Changelog

    Benchmarks

    Blog

    Community

    Customer Stories

    Events

    Support

    Integrations

    Launch Hub

  • Company

    Contact us

    About

    Timescale

    Partners

    Security

    Careers

Log InTry for free
TigerData logo

Products

Time-series and Analytics AI and Vector Enterprise Plan Cloud Status Support Security Cloud Terms of Service

Learn

Documentation Blog Forum Tutorials Changelog Success Stories Time-series Database

Company

Contact Us Careers About Brand Community Code Of Conduct Events

Subscribe to the Tiger Data Newsletter

By submitting, you acknowledge Tiger Data's Privacy Policy

2026 (c) Timescale, Inc., d/b/a Tiger Data. All rights reserved.

Privacy preferences
LegalPrivacySitemap

Copy as HTML

Open in ChatGPT

Open in Claude

Open in v0

Damaso Sanoja

By Damaso Sanoja

14 min read

Dec 18, 2025

TimescaleDBAI

Table of contents

01 CloudNativePG for Kubernetes-Native PostgreSQL Operations02 Why TimescaleDB Official Images Don't Work with CloudNativePG03 Building a TimescaleDB + pgvectorscale Image for Kubernetes04 Deploying TimescaleDB with Vector Extensions on CloudNativePG05 Validating Custom Image Integration and Stack Functionality06 Resource Optimization Insights from K3s Testing07 Conclusion: A Working Foundation for AI Data Platforms on Kubernetes

Spend more time improving your AI app and less time managing a database.

Start building

Deploying TimescaleDB Vector Search on CloudNativePG Kubernetes Operator

Deploying TimescaleDB Vector Search on CloudNativePG Kubernetes Operator
TimescaleDB
Damaso Sanoja

By Damaso Sanoja

14 min read

Dec 18, 2025

Table of contents

01 CloudNativePG for Kubernetes-Native PostgreSQL Operations02 Why TimescaleDB Official Images Don't Work with CloudNativePG03 Building a TimescaleDB + pgvectorscale Image for Kubernetes04 Deploying TimescaleDB with Vector Extensions on CloudNativePG05 Validating Custom Image Integration and Stack Functionality06 Resource Optimization Insights from K3s Testing07 Conclusion: A Working Foundation for AI Data Platforms on Kubernetes

Copy as HTML

Open in ChatGPT

Open in Claude

Open in v0

Spend more time improving your AI app and less time managing a database.

Start building

Consider an AI-powered financial analytics platform that processes real-time stock price data while simultaneously searching for similar trading patterns across historical data embeddings. Or an IoT monitoring system tracking sensor metrics over time while running anomaly detection through vector similarity search. These AI applications share a common architecture challenge: they require both efficient time-series storage and vector similarity search to operate at production scale.

Tiger Data's timescaledb-ha Docker image offers an elegant solution by unifying time-series and vector operations within a single PostgreSQL instance, with Kubernetes deployment scripts and Patroni-based clustering for scalability and high availability. But what if your organization requires declarative cluster management through native GitOps workflows rather than script-based orchestration?

This tutorial addresses that requirement by building a custom Docker image from CloudNativePG's PostgreSQL base that integrates TimescaleDB, pgvector, and pgvectorscale, enabling fully declarative, operator-managed clusters on Kubernetes. 

You'll discover why TimescaleDB official Docker images are incompatible with CloudNativePG, build a custom image that resolves these incompatibilities, and deploy a demonstration-scale proof-of-concept cluster to validate the solution.

CloudNativePG for Kubernetes-Native PostgreSQL Operations

The timescale/timescaledb-ha image is purpose-built for Patroni-based clustering and delivers high availability through battle-tested PostgreSQL patterns. For environments where Patroni's script-driven orchestration aligns with operational workflows, timescaledb-ha provides a comprehensive solution including TimescaleDB, vector extensions, PostGIS, Kubernetes deployment helpers, and many other tools.

CloudNativePG takes a different approach: operator-driven PostgreSQL management where cluster lifecycle operations execute through Kubernetes Custom Resource Definitions (CRDs) rather than external scripts. The operational differences become evident when managing multiple PostgreSQL clusters through native GitOps workflows:

Aspect

timescaledb-ha (Patroni)

CloudNativePG

Cluster Management

Script-driven via Patroni

Kubernetes-native operator with CRDs

Configuration

Environment variables + ConfigMaps

Fully declarative YAML manifests

Lifecycle Operations

Manual coordination through Patroni

Automated rolling upgrades, failover

GitOps Integration

Initial deployment only, runtime changes bypass version control

Complete infrastructure-as-code workflow

Extension Customization

Pre-bundled versions only

Control extension versions and the build process

Given these operational differences, deploying TimescaleDB with CloudNativePG requires understanding why the timescaledb-ha image, despite bundling all necessary extensions, cannot work with CloudNativePG's operator-driven model.

Why TimescaleDB Official Images Don't Work with CloudNativePG

TimescaleDB’s image architecture reflects Patroni's operational requirements: custom entrypoint scripts manage cluster initialization, data directories reside at /home/postgres/pgdata instead of PostgreSQL's standard /var/lib/postgresql/data, and the initialization process expects root-level access before transitioning to the Postgres user.

CloudNativePG's operator requires PostgreSQL official image patterns: standard data directory paths, init container-based bootstrapping, and postgres-user ownership from container startup. These architectural differences make the timescale-ha image incompatible with CloudNativePG's reconciliation model: the operator cannot initialize clusters when the base image expects different initialization sequences, data paths, and permission models.

Building a custom image from CloudNativePG's PostgreSQL base that adds TimescaleDB and vector extensions resolves these architectural conflicts while preserving full operator compatibility. This approach requires maintaining a build pipeline for extension updates. Still, it provides complete control over extension versions and ensures the image adheres to PostgreSQL's official conventions, which CloudNativePG's operator expects for initialization, configuration management, and lifecycle operations.

Building a TimescaleDB + pgvectorscale Image for Kubernetes

CloudNativePG's PostgreSQL base images don't include TimescaleDB or vector extensions, requiring compilation from source. Our build uses a four-stage Dockerfile targeting specific versions tested for compatibility: PostgreSQL 17 on Debian 12 (Bookworm), pgvector 0.8.1, pgvectorscale 0.9.0, and TimescaleDB 2.x. This version combination works reliably, although diverging to newer versions (PostgreSQL 18, Debian 13) requires thorough testing, as extension compatibility with the base OS and PostgreSQL versions isn't guaranteed.

Start by cloning the tutorial repository to access the complete Dockerfile and Kubernetes manifests:

git clone https://TIMESCALE-REPO.git
cd TIMESCALE-REPO

The Dockerfile implements a four-stage build process, with each stage isolating specific compilation requirements.

Stage 1: Building pgvector from Source

The first stage compiles pgvector (the traditional vector data type for similarity operations) using CloudNativePG's PostgreSQL 17 Debian 12 base image as the builder. Debian 12 is critical here because Debian 11 is deprecated in CloudNativePG's image catalog, and Debian 13 lacks stable packages for several PostgreSQL extensions.

Using the same base image for both building and runtime ensures library compatibility and aligns with CloudNativePG's initialization patterns. The compilation follows standard PostgreSQL extension build procedures with make install:

FROM ghcr.io/cloudnative-pg/postgresql:17-bookworm AS pgvector-builder

ARG PG_MAJOR=17
ARG PGVECTOR_VERSION=0.8.1

…

RUN make clean && make OPTFLAGS="" && make install

Stage 2: Building pgvectorscale from Source

pgvectorscale extends pgvector with DiskANN indexes—disk-based approximate nearest neighbor search that maintains optimal query performance while using minimal RAM. This makes vector search viable in resource-constrained Kubernetes environments. The extension compiles from Rust source using cargo-pgrx with a critical configuration requirement:

ENV RUSTFLAGS="-C target-cpu=x86-64-v3 -C target-feature=+avx2,+fma"

The RUSTFLAGS configuration requires AVX2 and FMA CPU instructions for pgvectorscale's DiskANN implementation. While most modern CPUs support these instructions (Intel since 2013, AMD since 2015), virtualized environments often don't expose them to guest VMs by default. If deploying on VMs, verify the hypervisor configuration exposes these instruction sets by running this command inside your Kubernetes nodes:

lscpu | grep -E 'avx2|fma'

Stage 3: Installing TimescaleDB

TimescaleDB installs from the official apt repository rather than compiling from source:

FROM ghcr.io/cloudnative-pg/postgresql:17-bookworm AS timescaledb-builder

…

RUN apt-get update && apt-get install -y \
    Timescaledb-2-postgresql-17

This approach simplifies maintenance since version updates only require changing the Dockerfile's ARG declaration and rebuilding, while apt handles PostgreSQL version compatibility automatically.

Stage 4: Assembling the Runtime Image

The final stage combines all components on CloudNativePG's PostgreSQL 17 base image. CloudNativePG's operator is strict about file paths and ownership; extensions must follow standard PostgreSQL directory conventions for the operator's initialization process to recognize them:

…
COPY --from=pgvector-builder \
    /usr/lib/postgresql/17/lib/vector.so \
    /usr/lib/postgresql/17/lib/
COPY --from=pgvector-builder \
    /usr/share/postgresql/17/extension/vector*.sql \
    /usr/share/postgresql/17/extension/
…

The assembly stage copies shared libraries to /usr/lib/postgresql/17/lib/ and SQL/control files to /usr/share/postgresql/17/extension/, then switches to user 26 (the postgres user). CloudNativePG expects this ownership model from container startup; diverging from these paths or permissions breaks operator initialization.

Building and Pushing the Image

Build the image with standard Docker commands, adjusting the registry, image name, and tag for your environment:

docker build -t YOUR_REGISTRY/timescale-ai:pg17-v1.0.0 .
docker push YOUR_REGISTRY/timescale-ai:pg17-v1.0.0

After building and pushing the image to your registry, CloudNativePG requires an ImageCatalog resource to reference custom PostgreSQL images during cluster initialization. The ImageCatalog configuration and cluster deployment manifests are covered in the next section.

Deploying TimescaleDB with Vector Extensions on CloudNativePG

This tutorial assumes the CloudNativePG operator is installed in your cluster. If not, follow the official installation guide.

Verify the operator is running:

kubectl get deployment -n cnpg-system

You should see the cnpg-cloudnative-pg deployment ready and available.

With the custom image built and pushed to your registry, the ImageCatalog resource in kubernetes/imagecatalog-timescaledb.yaml tells CloudNativePG where to find the image during cluster initialization:

apiVersion: postgresql.cnpg.io/v1
kind: ImageCatalog
metadata:
  name: timescale-ai
  namespace: timescaledb
spec:
  images:
  - major: 17
    image: YOUR_REGISTRY/timescale-ai:pg17-v1.0.0

This catalog bridges the custom build process with Kubernetes-native deployment by referencing the catalog by name rather than specifying image URLs directly, allowing centralized image version management across multiple PostgreSQL clusters.

Creating the Cluster Manifest

The Cluster resource defines PostgreSQL deployment topology, storage configuration, and extension initialization. The tutorial repository includes a script named cluster-setup.sh, run it, to create the namespace, deploy the ImageCatalog, and provision the cluster:

./cluster-setup.sh

The script applies the manifest in kubernetes/cluster-timescaledb.yaml, which configures a three-instance deployment (one primary, two replicas) with 10Gi storage per instance:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: timescaledb-cluster
  namespace: timescaledb
spec:
  instances: 3
  imageCatalogRef:
    apiGroup: postgresql.cnpg.io
    kind: ImageCatalog
    name: timescale-ai
    major: 17
  storage:
    size: 10Gi
  postgresql:
    shared_preload_libraries:
      - timescaledb
    parameters:
      work_mem: '128MB'
      maintenance_work_mem: '1GB'
      shared_buffers: '512MB'
      effective_cache_size: '1536MB'
      max_connections: '100'
      timescaledb.max_background_workers: '4'
  bootstrap:
    initdb:
      database: app
      owner: app
      postInitApplicationSQL:
        - CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
        - CREATE EXTENSION IF NOT EXISTS vector CASCADE;
        - CREATE EXTENSION IF NOT EXISTS vectorscale CASCADE;

Let's break down the key configuration parameters:

  • imageCatalogRef - References the ImageCatalog, allowing CloudNativePG to resolve the custom image during cluster initialization.
  • storage: 10Gi - Allocates 10Gi per instance. The demo application consumes approximately 150MB uncompressed. This leaves ample space for experimenting with larger datasets and observing TimescaleDB compression behavior.
  • shared_preload_libraries: [timescaledb] - Loads TimescaleDB at PostgreSQL startup. This is mandatory since NativeCloudPG won’t allow TimescaleDB to load dynamically.
  • work_mem: '128MB' - Controls memory per query operation. In our demo with 50K vectors, work_mem below 64MB caused query operations to spill to disk, degrading similarity search performance from sub-15ms to 50-100ms. The 128MB setting handled our demo queries comfortably. Your workload may need different values. Start here and adjust based on query complexity and available memory.
  • maintenance_work_mem: '1GB' - Affects index creation performance. DiskANN index builds in our full demo (50K vectors, 1,536 dimensions) failed with 512MB but succeeded at 1GB. Production deployments with hundreds of thousands or millions of vectors will require significantly more memory; start with 2-4GB and monitor index build performance.
  • shared_buffers: '512MB' - Allocates shared memory for caching frequently accessed data. In our testing, 256MB showed increased disk I/O during concurrent queries. The 512MB setting provided adequate caching for our demo workload. PostgreSQL documentation typically recommends 25% of available RAM, but optimal values depend on your data volume and query patterns.
  • effective_cache_size: '1536MB' - Informs PostgreSQL's query planner about available system memory for caching. This doesn't allocate memory—it influences query plan decisions. The value shown assumes approximately 2GB total memory available to PostgreSQL; adjust proportionally for your environment.
  • max_connections: '100' - Standard connection limit. AI applications that generate embeddings create bursty traffic patterns. For unpredictable query patterns or high connection churn, consider enabling CloudNativePG's PgBouncer pooler to reuse connections and prevent PostgreSQL from being overwhelmed by connection overhead.
  • timescaledb.max_background_workers: '4' - Controls TimescaleDB background job concurrency for compression and continuous aggregates. Four workers balance background task processing with query workload for typical configurations. Adjust as required.
  • postInitApplicationSQL - Executes after cluster initialization completes. Creates the three required extensions: timescaledb for time-series optimization, pgvector for essential vector operations, and vectorscale for DiskANN indexes.

Note on resource limits: For demonstration purposes, this manifest doesn't define Kubernetes resource limits or requests. The parameters above assume PostgreSQL has at least 2GB memory available. Production deployments should define explicit resources in the Cluster spec and tune parameters based on actual pod sizing. 

CloudNativePG provisions the three-instance cluster within 2-3 minutes. The operator creates persistent volumes, initializes the primary instance, and starts replication to replicas automatically. Monitor cluster initialization:

kubectl get cluster -n timescaledb -w

Verifying Extensions

After the cluster reaches a ready state, verify that all extensions are loaded correctly with a single comprehensive test:

kubectl exec -it timescaledb-cluster-1 -n timescaledb -- \
  psql -U postgres -d app -c "
-- Verify all extensions
SELECT extname, extversion FROM pg_extension 
WHERE extname IN ('timescaledb', 'vector', 'vectorscale') 
ORDER BY extname;

-- Verify DiskANN access method
SELECT amname FROM pg_am WHERE amname = 'diskann';

-- Test TimescaleDB hypertable creation
CREATE TABLE IF NOT EXISTS metrics (
  time TIMESTAMPTZ NOT NULL, 
  value DOUBLE PRECISION
);
SELECT create_hypertable('metrics', 'time', if_not_exists => TRUE);

-- Confirm operational
SELECT 'All extensions operational!' as status;
"

The expected output is:

   extname   | extversion 
-------------+------------
 timescaledb | 2.19.3
 vector      | 0.8.1
 vectorscale | 0.9.0
(3 rows)

 amname  
---------
 diskann
(1 row)

CREATE TABLE
      create_hypertable       
------------------------------
 (1,public,metrics,t)
(1 row)

           status            
-----------------------------
 All extensions operational!
(1 row)

This output verifies extension versions match the build configuration, the DiskANN access method is registered correctly for pgvectorscale indexes, TimescaleDB hypertable creation works, and the complete stack is operational.

Sample Application Setup

The tutorial repository includes a sample application demonstrating time-series data combined with vector embeddings. The application models stock market pattern recognition: 432,000 stock price records stored in TimescaleDB hypertables with 1,800 corresponding pattern embeddings for similarity search.

This demo dataset validates the stack integration at demonstration scale: hypertables partition correctly, DiskANN indexes build successfully, compression activates automatically, and time-series + vector queries execute as expected. The dataset is intentionally sized for quick experimentation: initialization completes in 2-3 minutes, allowing rapid iteration on configuration changes.

Initialize the sample schema and data:

./initialize-db.sh

The initialization script creates hypertables, seeds data, generates embeddings, and builds DiskANN indexes for both cosine and L2 distance metrics. The next section validates query performance and compression behavior using this dataset, providing baseline metrics you can compare against when experimenting with different parameter configurations or larger datasets.

Validating Custom Image Integration and Stack Functionality

With the cluster deployed using the custom image, it is time to validate that all components integrate correctly. To that end, the tutorial repository includes a script named run-capability-tests.sh, an interactive test suite that confirms the custom image solution works as intended.

The test suite offers two modes:

  • Quick Validation runs in under a minute, testing the current dataset of 1,800 vectors to verify extensions loaded correctly and basic operations execute.
  • Full Capability Demo generates 50,000 vectors across 9 months of time-series data, providing more comprehensive integration testing including time-windowed queries, vector similarity search, and automatic compression behavior.

Run the test suite:

./run-capability-tests.sh

Select Full Capability Demo if you want to generate the complete test dataset. The demonstration completes in approximately 15 minutes on a single-node K3s cluster (4 vCPU, 8GB RAM), validating that the custom image successfully integrates all components without compatibility issues.

Test Dataset and Methodology

The Full Capability Demo creates a demonstration workload combining time-series and vector data to test integration completeness. The dataset comprises 432,000 stock price records (open, high, low, close, and volume) for 10 stock symbols, spanning 272 days with 7-day chunk intervals. Pattern embeddings consist of 50,000 vectors with 1,536 dimensions distributed across the same time range.

The test verifies that TimescaleDB's automatic chunk exclusion functions work correctly, executes vector similarity searches to verify DiskANN index creation and usage, and enables compression policies to validate automatic compression on historical data.

Time-Windowed Query Performance

TimescaleDB automatically partitions data into chunks based on time intervals. Testing queries with different time ranges confirms that chunk exclusion works correctly with the custom image:

Time Range

Execution Time

Chunks Scanned

7 days

~5ms

1 chunk

30 days

~8ms

4 chunks

90 days

~20ms

8 chunks

270 days

~132ms

40 chunks

The performance pattern demonstrates that TimescaleDB's query planner successfully excludes chunks outside the specified time range. A 38.5x increase in time range (7 days to 270 days) results in 26x slower execution, confirming sub-linear scaling. Without time filters, queries scan all 40 chunks regardless of the data needed. The difference between 5ms (1 chunk) and 132ms (all chunks) illustrates why time predicates matter in query design.

These results confirm that the custom image preserves TimescaleDB's automatic partitioning and chunk exclusion capabilities without introducing compatibility issues.

Vector Search Performance

The test suite validates pgvectorscale's DiskANN indexes work correctly. Three common vector search patterns execute successfully:

Query Type

Execution Time

Description

Top-K similarity

~12ms

Find the 10 most similar patterns from 50,000 vectors

Cross-stock correlation

~4ms

Identify similar patterns across different stocks

Historical matching

~6ms

Search patterns from 6 months ago

DiskANN index size remains small at 24 KB per index (one for cosine distance, one for L2 distance), confirming the disk-based indexing approach works as designed. Query execution plans verified through EXPLAIN ANALYZE show "Index Scan using idx_pattern_embeddings_diskann_cosine," proving indexes built correctly and execute as expected.

These results validate that our Rust compilation of pgvectorscale integrated successfully with CloudNativePG's PostgreSQL base image.

Compression Functionality

TimescaleDB's automatic compression policy activates correctly on data older than 30 days. The test results demonstrate compression working as expected:

  • Uncompressed size: 124.2 MB
  • Compressed size: 5.4 MB
  • Compression ratio: 23.0:1 (95.6% space savings)
  • Chunks compressed: 34 of 40 (85%)

The exceptional compression rate (95.6%) reflects the synthetic nature of randomly generated test vectors. Real-world semantic embeddings from language models exhibit structured patterns that compress less effectively. For reference, production deployments typically achieve 60-80% compression on actual embeddings. Even at the lower end, 60% compression provides 2.5x storage savings for long-term data retention.

Queries against compressed chunks execute transparently without application changes, confirming the compression integration works correctly. The compression policy runs automatically in the background, requiring no manual intervention once configured.

This validation proves the custom image approach resolves the architectural incompatibilities between official TimescaleDB images and CloudNativePG. The stack functions correctly for the demonstration workload, providing a foundation for experimentation with your own data volumes and query patterns. Production deployments with larger datasets will require parameter tuning based on your specific workload characteristics, but the core integration is proven functional.

Resource Optimization Insights from K3s Testing

The validation testing ran on a single-node K3s cluster with 8GB RAM and 4 vCPUs, representing resource-constrained edge deployment scenarios. Monitoring during the Full Capability Demo revealed that CPU usage peaked at 33% with significant headroom remaining, while RAM utilization reached 90%. However, Linux's aggressive disk caching likely accounts for much of this. These results provide practical insights for optimizing similar resource-constrained deployments.

Memory Configuration and Actual Utilization

The demonstration cluster used 512MB shared_buffers, 128MB work_mem, and 1GB maintenance_work_mem without defining explicit Kubernetes resource limits. With three PostgreSQL instances running on an 8GB node, memory pressure remained manageable for the demo workload. The key insight: calculate maximum concurrent operations to avoid out-of-memory conditions using (Total RAM - shared_buffers) / work_mem. On our 8GB VM with approximately 6GB available after system overhead, this allowed roughly 45 concurrent operations at 128MB work_mem.

For production deployments, define explicit resource limits and tune parameters proportionally:

1-2GB pods (edge nodes): shared_buffers: 256MB, work_mem: 64MB, maintenance_work_mem: 512MB

2-4GB pods (standard nodes): shared_buffers: 512MB-1GB, work_mem: 128-256MB, maintenance_work_mem: 1-2GB

4GB+ pods (larger workloads): Tune based on actual query patterns and dataset size

Monitor actual memory pressure through swap usage and OOM events rather than total RAM percentage.

Storage Strategy for Cost Optimization

DiskANN's disk-based indexing made K3s's local-path provisioner viable for our demo: queries executed in 10-15ms despite using node local storage rather than high-performance network volumes. This validates a two-tier storage approach for production: fast local or SSD storage for recent uncompressed data (frequent access), and slower network-attached storage for compressed historical chunks (infrequent access, decompression overhead dominates).

TimescaleDB's compression moves data from hot to cold storage patterns automatically. Chunks compressed beyond 30 days tolerate higher storage latency because decompression CPU time exceeds storage access time. This architectural advantage reduces infrastructure costs in resource-constrained environments where high-performance storage across all data is prohibitively expensive.

DiskANN vs HNSW: Decision Framework

Our deployment used DiskANN indexes exclusively because they enabled vector search on resource-constrained K3s nodes. At 50,000 vectors with 1,536 dimensions, DiskANN indexes consumed 24 KB of disk space, while HNSW would have required 2-3GB of RAM.

Choose DiskANN when:

  • Running on resource-constrained Kubernetes nodes (K3s, edge deployments)
  • Dataset size approaches or exceeds available RAM per pod
  • 10-15ms query latency meets application requirements
  • Infrastructure costs constrain memory allocation

Choose HNSW when:

  • Sub-millisecond query latency is required
  • RAM is abundant (dataset fits comfortably in memory)
  • Query throughput justifies higher infrastructure costs

Many AI applications tolerate 10-15ms vector search latency, as embedding generation, LLM inference, and application logic typically dominate the total request time. Our testing confirmed this; the demo application ran effectively with DiskANN's ~15ms similarity search latency.

Connection Pooling for AI Applications

AI workloads create unpredictable connection patterns: batch embedding generation produces connection bursts, RAG implementations open connections per query, and LLM integrations generate variable query patterns. CloudNativePG's integrated PgBouncer addresses this. Enable connection pooling by adding to the Cluster spec:

spec:
  instances: 3
  pooler:
    enabled: true
    type: rw
    instances: 2
    pgbouncer:
      poolMode: transaction
      parameters:
        max_client_conn: "1000"
        default_pool_size: "25"

Transaction-mode pooling works with most AI workloads. Use session-mode only if your application requires prepared statements or temporary tables.

Conclusion: A Working Foundation for AI Data Platforms on Kubernetes

This tutorial solved a specific integration problem: The custom image built from CloudNativePG's PostgreSQL base successfully integrates TimescaleDB, pgvector, and pgvectorscale, enabling declarative cluster management through Kubernetes CRDs rather than script-based orchestration.

The validation confirmed the stack functions correctly at demonstration scale: sub-15ms vector similarity search across 50,000 embeddings, 5-20ms time-windowed queries through automatic chunk exclusion, and compression reducing storage requirements. DiskANN's 24 KB indexes proved that vector search works effectively in resource-constrained environments—our K3s testing showed 33% CPU utilization and stable operation on 8GB nodes. These baseline metrics provide a reference point for scaling experiments with your data volumes and query patterns.

Production deployment requires operational steps beyond this tutorial: configure backup policies for continuous WAL archiving and point-in-time recovery, implement monitoring through CloudNativePG's Prometheus integration, tune PostgreSQL parameters based on your workload characteristics, and validate failover behavior under load. Moreover, expect to revise memory allocations, storage sizing, and index strategies as dataset sizes grow from thousands to millions of vectors.

The complete implementation is available in the tutorial repository, including Dockerfile, Kubernetes manifests, initialization scripts, and test suite. For production deployment guidance, consult CloudNativePG documentation, TimescaleDB best practices, and pgvectorscale performance tuning.

Related posts

It’s 2026, Just Use Postgres

It’s 2026, Just Use Postgres

PostgreSQLTimescaleDB

Feb 02, 2026

Stop managing multiple databases. Postgres extensions replace Elasticsearch, Pinecone, Redis, MongoDB, and InfluxDB with BM25, vectors, JSONB, and time-series in one database.

Read more

TimescaleDB for Manufacturing IoT: Optimizing for High-Volume Production Data

TimescaleDB for Manufacturing IoT: Optimizing for High-Volume Production Data

IoTTimescaleDB

Jan 28, 2026

Manufacturing IoT optimization guide: tune TimescaleDB with hypertables, chunk intervals, continuous aggregates, and compression for high-frequency sensor data.

Read more

Stay updated with new posts and releases.

Receive the latest technical articles and release notes in your inbox.

Share

Get Started Free with Tiger CLI