Azpg when not to use
Skill lestermarch/postgres-ai-experts/skills/azpg-when-not-to-use
The devil's-advocate / right-tool advisor for Azure Database for PostgreSQL Flexible Server. Use this skill whenever someone asks "should this live in Postgres?", is weighing Postgres against a dedicated Azure service, is hitting a scaling wall, or is about to force a workload (messaging, global distribution, extreme-low-latency cache, full-text/vector search at massive scale, heavy analytics/OLAP, large blobs, high-ingest time-series) onto Postgres because "PostgreSQL can do everything." Deliberately argues AGAINST the single-platform premise where the evidence warrants, giving break-out thresholds, the signals to watch, and the specific Azure service to reach for — and, just as importantly, when to stay put. Reach for this before over-engineer ing a Postgres workaround or prematurely breaking a workload out.From its SKILL.md
npx -y skills add lestermarch/postgres-ai-experts --skill azpg-when-not-to-useAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.6 KB, ~2.1k tokens by cl100k_base, as published. Nobody here has run it
When NOT to use Postgres (right-tool advisor)
This repo's premise is "PostgreSQL can be used for everything." This skill is the honest counterweight: it argues against the premise when the evidence warrants, so teams don't paint themselves into a corner by forcing the wrong workload onto Flexible Server — or, equally, don't prematurely abandon Postgres for a shiny dedicated service they don't yet need.
This skill is read-only and advisory. It inspects scale signals and gives a recommendation with trade-offs; it never changes anything. There is no write path.
The goal is a defensible recommendation, not dogma. Most workloads should stay in Postgres far longer than people assume — extensions (
pgvector,pgmq, JSONB, PostGIS, full-text) push the break-out line out a long way. Only recommend breaking out when a concrete signal crosses a real limit. Deep per-domain thresholds are inreference.md; the hard Flexible Server ceilings that anchor the thresholds are inazure-constraints.md.
Live instance context (dynamic injection)
Ground the advice in the workload's actual scale before quoting any threshold —
a recommendation to break out (or stay) is only credible against real numbers.
PGCONN is a libpq connection string. These are read-only and safe to
auto-run.
- Database size (how close to the storage ceiling?):
!
psql "$PGCONN" -tAc "SELECT pg_size_pretty(pg_database_size(current_database()));" 2>/dev/null || echo "(could not connect — ask for connection details)" - Largest tables (where the pressure actually is):
!
psql "$PGCONN" -tAc "SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS total, n_live_tup FROM pg_stat_user_tables ORDER BY pg_total_relation_size(relid) DESC LIMIT 8;" 2>/dev/null || echo "(unknown)" - Connection pressure (used vs ceiling):
!
psql "$PGCONN" -tAc "SELECT count(*) AS conns, current_setting('max_connections') AS max FROM pg_stat_activity;" 2>/dev/null || echo "(unknown)" - Which single-platform extensions are already carrying load:
!
psql "$PGCONN" -tAc "SELECT extname FROM pg_extension WHERE extname IN ('pgmq','vector','pg_diskann','postgis','pg_cron','timescaledb') ORDER BY extname;" 2>/dev/null || echo "(none)"
If injection is unavailable, run
scripts/scale_signals.sql and read its output.
Never quote a break-out threshold without a real number next to it.
When to use this skill
Trigger on: "should we use Postgres for X?", "is Postgres the right choice for a queue / cache / search / analytics / global app?", "we're hitting a wall on size/connections/latency", "should we move this to Cosmos DB / Event Hubs / AI Search / Redis / Fabric?", or any moment where the single-platform premise is about to be stretched. Also use it defensively — when someone wants to break out but the numbers say Postgres is fine, say so.
How to give a recommendation
- Get the real numbers (injection above). Size, hottest tables, connection pressure, and which extensions already run. No numbers → no verdict.
- Identify the workload class — messaging, search/vector, global distribution, cache, analytics/OLAP, time-series, or blob/large-object.
- Compare against the break-out signal for that class (table below +
reference.md). A break-out is warranted only when a concrete signal crosses a real limit, not on vibes. - State the trade-off both ways. What you gain by breaking out (and what you
lose: transactional consistency, one system to operate,
JOINs across the data). What you gain by staying (simplicity) and what you risk. - Recommend the specific Azure service if breaking out, and how to integrate (often alongside Postgres, not instead of it).
Break-out signals by workload class (summary)
Stay in Postgres until the break-out signal fires; then reach for the service
named. Full thresholds, trade-offs, and integration notes in
reference.md.
| Workload | Stay in Postgres with… | Break-out signal | Reach for |
|---|---|---|---|
| Queue / jobs | pgmq, SELECT … FOR UPDATE SKIP LOCKED | Millions of msgs/sec, fan-out to many consumers, cross-region eventing | Service Bus / Event Hubs |
| Search / vector | pgvector (+ DiskANN), full-text tsvector | ≫100M vectors, heavy relevance tuning, hybrid ranking at scale | Azure AI Search |
| Global distribution | Read replicas, JSONB | Multi-region active-active writes, single-digit-ms global reads | Cosmos DB |
| Cache | UNLOGGED tables, in-DB memoisation | Sub-ms p99 at very high QPS as a dedicated cache | Azure Managed Redis |
| Analytics / OLAP | Columnar-ish patterns, materialised views, read replica | TB-scale scans, star schemas, BI concurrency hurting OLTP | Microsoft Fabric / Synapse |
| Time-series | Partitioning, BRIN, pg_cron rollups | Extreme sustained ingest + retention beyond storage ceiling | Azure Data Explorer |
| Large blobs | bytea / large objects for small files | Files > a few MB, media, many-GB objects | Azure Blob Storage (store URL in PG) |
| In-DB LLM generation | azure_ai.generate on a non-reasoning model | Only reasoning models (gpt-5/o-series) deployable, or you need generation params (temperature, tools, JSON mode) azure_ai.generate doesn't expose | App-tier call to Azure OpenAI (keep embeddings + retrieval in PG) |
The strongest pattern is usually Postgres as the system of record + a break-out service alongside it, not a wholesale migration.
Read / inspect steps (safe · auto)
Everything this skill does is read-only:
- Scale signals —
scripts/scale_signals.sqlgathers DB size, top tables, connection pressure, and extension presence in one pass (the injection backstop). - Confirm the wall is real — before recommending a break-out on a performance
complaint, verify the workload is actually saturated, not just un-tuned. A slow
query is often an index or config problem, not a platform problem — route to
azpg-explain-analyze/azpg-index-selection/azpg-config-tuningfirst.
Common false alarms (stay in Postgres)
Push back on premature break-out when the real fix is cheaper:
- "Postgres can't handle our queue."
pgmq+SKIP LOCKEDhandles very high throughput. Break out for cross-region eventing or massive fan-out, not for a few thousand jobs/sec. →azpg-ai-in-database/ messaging skills. - "We need Redis for caching."
UNLOGGEDtables and app-side caching cover many cases without another system. Break out for a dedicated sub-ms cache at high QPS. - "Vector search won't scale."
pgvector+ DiskANN scales to many millions of vectors. Break out to AI Search for ≫100M vectors or heavy hybrid relevance. →azpg-pgvector-rag. - "The database is slow, we've outgrown Postgres." Usually tuning, indexing,
or a bad plan — verify with
azpg-explain-analyzebefore blaming the platform.
A worked "should we break out?" decision, end to end, is in
examples/breakout_decision.md.
Advisory protocol
- Numbers before verdict. Never recommend break-out or stay-put without the real scale signals in hand.
- Rule out tuning first. Performance complaints route to
azpg-explain-analyze/azpg-index-selection/azpg-config-tuningbefore any platform verdict. - State both sides. Every recommendation names what's gained and lost — a break-out costs you transactional consistency and one-system simplicity.
- Prefer "alongside," not "instead of." The default shape is Postgres as system of record with a specialised service for the one dimension it can't serve — keep the blast radius small.
- Read-only, always. This skill never provisions or migrates. If the verdict
is "break out," hand off (e.g.
azpg-provision-iacfor a new component, migration skills for a move) — don't act here.
Bundled files
reference.md— per-workload break-out thresholds, the signals to watch, trade-offs, and which Azure service + integration pattern to use.azure-constraints.md— the hard Flexible Server ceilings (storage, connections, single-region writes, IOPS) that anchor the thresholds.scripts/scale_signals.sql— read-only signal gatherer (injection backstop).examples/breakout_decision.md— a worked decision with real numbers and a both-sides recommendation.
What ships with it: 6 files
24.6 KB alongside SKILL.md
examples/
- breakout_decision.md4.3 KB
scripts/
- README.md1.2 KB
- scale_signals.sql2.4 KB
- azure-constraints.md3.8 KB
- EVALUATION.md4.9 KB
- reference.md8.0 KB