--- id: db-postgres-extensions title: Postgres Extensions — pgvector / TimescaleDB / Citus category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [database, postgres, extensions, vibe-coding] tech_stack: { language: "PostgreSQL", applicable_to: ["Backend"] } applied_in: [] aliases: [Postgres extensions, pgvector, TimescaleDB, Citus, PostGIS, pg_cron, pg_partman] --- # Postgres Extensions > Postgres = "swiss army knife". **Extension 가 거의 모든 use case**. pgvector / TimescaleDB / Citus / PostGIS / pg_cron 등. ## 📖 핵심 개념 - Extension: SQL + C code module. - `CREATE EXTENSION`: 활성. - Cloud RDS / Aurora / Neon = 대부분 지원. - Self-host = 직접 install. ## 💻 코드 패턴 ### 자주 쓰는 extension ```sql -- Vector CREATE EXTENSION vector; -- pgvector -- Time-series CREATE EXTENSION timescaledb; -- TimescaleDB -- Distributed CREATE EXTENSION citus; -- Citus -- Geo CREATE EXTENSION postgis; -- PostGIS -- Crypto CREATE EXTENSION pgcrypto; -- 해시, 암호 -- UUID CREATE EXTENSION "uuid-ossp"; -- UUID 생성 -- Cron CREATE EXTENSION pg_cron; -- DB 안 cron -- Stats CREATE EXTENSION pg_stat_statements; -- query 분석 CREATE EXTENSION auto_explain; -- slow query log -- HLL (probabilistic) CREATE EXTENSION hll; -- HyperLogLog -- Trigram (fuzzy search) CREATE EXTENSION pg_trgm; -- JSON 강력 CREATE EXTENSION pg_jsonschema; -- Async / queue CREATE EXTENSION pgmq; -- message queue -- Compression CREATE EXTENSION pg_lz; ``` ### pgvector (vector search) ```sql CREATE EXTENSION vector; CREATE TABLE docs ( id BIGSERIAL, content TEXT, embedding VECTOR(1536) ); CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops); -- Search SELECT * FROM docs ORDER BY embedding <=> $1::vector LIMIT 5; ``` → [[DB_pgvector_Production]]. ### TimescaleDB (time-series) ```sql CREATE EXTENSION timescaledb; CREATE TABLE metrics ( ts TIMESTAMPTZ NOT NULL, device_id TEXT, cpu DOUBLE PRECISION ); SELECT create_hypertable('metrics', 'ts', chunk_time_interval => INTERVAL '1 day'); -- 자동 partition + 압축 + retention ``` → [[DB_Time_Series_Patterns]]. ### Citus (sharding) ```sql CREATE EXTENSION citus; SELECT create_distributed_table('orders', 'tenant_id'); -- 자동 sharding by tenant_id ``` → [[DB_Sharding_Strategies]]. ### PostGIS (geo) ```sql CREATE EXTENSION postgis; CREATE TABLE places ( id SERIAL PRIMARY KEY, name TEXT, location GEOGRAPHY(POINT, 4326) ); INSERT INTO places (name, location) VALUES ( 'Tower', ST_GeographyFromText('POINT(127.0 37.5)') ); -- 1km 안 가까운 SELECT * FROM places WHERE ST_DWithin(location, ST_GeographyFromText('POINT(127.0 37.5)'), 1000); -- 거리 SELECT name, ST_Distance(location, ST_GeographyFromText('POINT(127.0 37.5)')) AS dist FROM places ORDER BY dist LIMIT 10; ``` ### pg_trgm (fuzzy search) ```sql CREATE EXTENSION pg_trgm; CREATE INDEX users_name_trgm ON users USING GIN (name gin_trgm_ops); -- Similar names SELECT name, similarity(name, 'alice') AS sim FROM users WHERE name % 'alice' -- pg_trgm operator ORDER BY sim DESC LIMIT 10; -- Partial match SELECT * FROM users WHERE name ILIKE '%al%'; -- 빠름 (with trgm index) ``` ### pg_cron (scheduled jobs) ```sql CREATE EXTENSION pg_cron; -- 매일 오전 9시 cleanup SELECT cron.schedule('cleanup-old-data', '0 9 * * *', $$ DELETE FROM events WHERE created_at < NOW() - INTERVAL '90 days' $$); -- 매 5분 SELECT cron.schedule('sync-cache', '*/5 * * * *', 'CALL refresh_cache()'); -- List SELECT * FROM cron.job; -- Unschedule SELECT cron.unschedule('cleanup-old-data'); ``` → Application-level cron 대안. ### pgcrypto (encryption) ```sql CREATE EXTENSION pgcrypto; -- Hash SELECT crypt('password', gen_salt('bf')); -- Verify SELECT crypt('password', stored_hash) = stored_hash; -- Random SELECT gen_random_uuid(); SELECT gen_random_bytes(16); -- Encrypt SELECT pgp_sym_encrypt('secret', 'password'); SELECT pgp_sym_decrypt(encrypted, 'password'); ``` ### pgmq (message queue in PG) ```sql CREATE EXTENSION pgmq; SELECT pgmq.create('my_queue'); -- Send SELECT pgmq.send('my_queue', '{"order_id": 42}'); -- Read (with VT — 30s lock) SELECT * FROM pgmq.read('my_queue', 30, 1); -- {msg_id, message, ...} -- Delete (ack) SELECT pgmq.delete('my_queue', 1); -- Archive SELECT pgmq.archive('my_queue', 1); ``` → Postgres = light queue. SQS / RabbitMQ alternative. ### pg_stat_statements (query 분석) ```sql CREATE EXTENSION pg_stat_statements; -- Top slow queries SELECT query, calls, total_exec_time / 1000 AS total_seconds, mean_exec_time AS avg_ms, rows FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 20; ``` → [[DB_Postgres_EXPLAIN]]. ### auto_explain (slow query log) ```sql -- postgresql.conf shared_preload_libraries = 'auto_explain' ALTER SYSTEM SET auto_explain.log_min_duration = '500ms'; ALTER SYSTEM SET auto_explain.log_analyze = on; ALTER SYSTEM SET auto_explain.log_buffers = on; SELECT pg_reload_conf(); ``` → Slow query 자동 EXPLAIN log. ### pg_partman (자동 partition) ```sql CREATE EXTENSION pg_partman; SELECT partman.create_parent( p_parent_table => 'public.events', p_control => 'created_at', p_type => 'native', p_interval => 'monthly', p_premake => 3 ); -- Maintenance (매 시간) SELECT partman.run_maintenance_proc(); ``` → Automatic partition creation + drop. ### plv8 (JS in DB) ```sql CREATE EXTENSION plv8; CREATE FUNCTION my_function(input TEXT) RETURNS TEXT AS $$ return input.toUpperCase(); $$ LANGUAGE plv8; SELECT my_function('hello'); -- 'HELLO' ``` → JavaScript stored procedure. ### Foreign Data Wrapper (FDW) ```sql -- Postgres → Postgres CREATE EXTENSION postgres_fdw; CREATE SERVER remote_pg FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'remote.example.com', dbname 'app'); CREATE FOREIGN TABLE remote_users (id UUID, email TEXT) SERVER remote_pg OPTIONS (schema_name 'public', table_name 'users'); SELECT * FROM remote_users; ``` → Postgres → MySQL / S3 / file 도 가능. ### pg_jsonschema (JSON validation) ```sql CREATE EXTENSION pg_jsonschema; CREATE TABLE events ( data JSONB CHECK (jsonschema_is_valid(' {"type":"object","required":["type"],"properties":{"type":{"type":"string"}}} ', data)) ); ``` ### pgaudit (compliance) ```sql CREATE EXTENSION pgaudit; ALTER SYSTEM SET pgaudit.log = 'write,ddl'; SELECT pg_reload_conf(); ``` → Detailed audit log. ### pg_hint_plan (force plan) ```sql CREATE EXTENSION pg_hint_plan; /*+ IndexScan(orders orders_user_idx) */ SELECT * FROM orders WHERE user_id = $1; ``` → Planner hint. Last resort. ### Cloud 의 extension 지원 ``` RDS Postgres: 100+ extension. Aurora: 비슷. Supabase: pgvector, pg_cron, etc 강. Neon: pgvector, postgis. Cloud SQL: 표준 set. → Provider docs 검사. ``` ### Self-host ```bash # Docker docker run -d \ -e POSTGRES_PASSWORD=secret \ -p 5432:5432 \ pgvector/pgvector:pg16 # Or 직접 install apt install postgresql-16-pgvector ``` ### Extension version 관리 ```sql -- 현재 version SELECT * FROM pg_extension WHERE extname = 'vector'; -- Update ALTER EXTENSION vector UPDATE TO '0.7.0'; -- Available versions SELECT * FROM pg_available_extension_versions WHERE name = 'vector'; ``` ### pg_repack (online table rewrite) ```bash pg_repack -d mydb -t orders ``` → VACUUM FULL 의 zero-downtime alternative. → [[DB_Vacuum_Autovacuum]]. ### Useful 시작 set ```sql -- 시작 시 활성 CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS pg_stat_statements; CREATE EXTENSION IF NOT EXISTS pgcrypto; CREATE EXTENSION IF NOT EXISTS pg_trgm; ``` ### Combo (modern app) ``` - pgvector (RAG) - pg_cron (scheduled tasks) - pgmq (light queue) - pg_trgm (search) - pg_stat_statements (monitoring) - pgaudit (compliance) ``` → Postgres 만으로 큰 stack 가능. ### Multi-extension query ```sql -- Vector + cron + JSON SELECT cron.schedule('embed-new-docs', '*/10 * * * *', $$ UPDATE docs SET embedding = embed(content) WHERE embedding IS NULL $$); ``` ### Custom extension (자체 build) ```c // my_extension.c #include "postgres.h" #include "fmgr.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(my_function); Datum my_function(PG_FUNCTION_ARGS) { int32 arg = PG_GETARG_INT32(0); PG_RETURN_INT32(arg * 2); } ``` → C 작성 → DB 안 native function. ### Extension as source of truth ``` Cloud-native: - pgvector + RAG - pg_cron + jobs - pgmq + queue - pg_partman + time-series → Postgres = monolith DB. 작은 팀 = 강력. ``` ### When NOT to use ``` - 큰 throughput / 분산 — Citus / Yugabyte - Real-time analytics (PB) — ClickHouse / Druid - 강력 search — Elasticsearch - Real-time messaging — Kafka - 큰 vector (1B+) — Vespa / Milvus ``` ### Migration path ``` Start: Postgres + extensions (작은 stack). Grow: 일부 = 별 system (Kafka, ClickHouse). End: Specialized stack. → Premature specialization X. PG 가 90% case 충분. ``` ### Backup with extensions ```bash pg_dump --extensions=all -d mydb > backup.sql # Or specific pg_dump --extension=pg_cron --extension=vector -d mydb ``` ### Test ```ts // Test 가 같은 extension 가짐 beforeAll(async () => { await db.execute(`CREATE EXTENSION IF NOT EXISTS pg_trgm`); }); ``` ## 🤔 의사결정 기준 | 사용 | 추천 extension | |---|---| | Vector search | pgvector | | Time-series | TimescaleDB | | Sharding | Citus | | Geo | PostGIS | | Search | pg_trgm + tsvector | | Cron | pg_cron | | Queue | pgmq | | Crypto | pgcrypto | ## ❌ 안티패턴 - **Cloud 가 안 지원 — extension 가정**: 검사. - **Major upgrade 시 extension 호환 X**: 검증. - **Extension 너무 많이**: 의존 복잡. - **자체 patch — upstream 무시**: 유지 어려움. - **Production 가 latest minor**: 검증. ## 🤖 LLM 활용 힌트 - Postgres + 5 ~ 10 extension = 큰 stack. - pgvector + pg_cron + pgmq = mini SaaS. - Cloud 의 supported list 확인. - 점진 도입. ## 🔗 관련 문서 - [[DB_pgvector_Production]] - [[DB_Time_Series_Patterns]] - [[DB_Sharding_Strategies]]