supabase-postgres-best-practices (supabase/agent-skills)
Guía el diseño de esquemas Postgres, migraciones, RLS, índices y rendimiento de consultas con Supabase.
Supabase Postgres best practices: sin mejora frente a Codex a secas en tareas de esquema, revisión e índices (4.48 vs 4.54)
Codex CLI · gpt-6-astra
24.4 / 30
Mejora frente a sin skill: -0.06 · Según el caso · 18 ejecuciones
Según el caso: la mejora -0.06 está por debajo de +1.0. Para ser recomendada hace falta un total de 22/30, una calidad de salida de 3.5 y una mejora de +1.0.
SOTA
AprobadaProbada con Codex.
Cubre Codex, Claude Code
Codex CLI 0.166 (nivel SOTA): 18 ejecuciones puntuadas. Una pasada aquí también cubre Claude Code según nuestra regla de niveles; no dice nada sobre el segundo nivel.
Puntuaciones
Cada dimensión va de 0 a 5 y las seis suman el total sobre 30. 5 es mejor en todas las dimensiones. Coste 5 significa barato y rápido. Instalación 5 significa fácil.
- Fiabilidad de activación
- 5.0
- Mejora frente a sin skill
- 1.9
- Calidad de salida
- 4.5
- Coste en tokens y tiempo
- 4.0
- Instalación y portabilidad
- 4.0
- Seguridad
- 5.0
Revisión de seguridad
SeguraEscaneo estático: 0 CRITICAL / 4 HIGH / 0 MEDIUM. Revisión manual: Segura para ejecutar en un sandbox sin red (hallazgos del escáner explicados). Un escaneo limpio no demuestra que una skill sea segura.
Instalar
npx skills@latest add supabase/agent-skills --skill supabase-postgres-best-practices
Commit fijado: c9be0e931b7930f7d02126d04774d904c381e7d7
Probada: 2026-11-02
Qué probamos
- Esquema multiinquilino con RLS — Escribe schema.sql para un gestor de proyectos multiinquilino en Supabase (Postgres): organizaciones, membresías (un usuario de autenticación de Supabase pertenece a una organización con un rol), proyectos, tareas (responsable, estado, fecha de vencimiento) y comentarios en las tareas. Un usuario solo puede ver y cambiar…
- Revisa un esquema, consultas y un worker — Revisa schema.sql, queries.sql y worker.py (una app de tickets de soporte con Supabase/Postgres). Enumera los problemas, del más grave al menos, cada uno con su solución. No cambies ningún archivo. Escribe la lista en tu respuesta final.
- Índices para tres consultas lentas — Las tres consultas de slow_queries.md son lentas sobre la tabla de schema.sql (120M de filas). Escribe migration.sql con los cambios de índices que harías (y nada más), y notes.md (como máximo 120 palabras) indicando qué índice sirve a cada consulta y cualquier salvedad. (Sin base de datos…
Ventajas
- La skill se activó sin nombrarla: se leyó el archivo de la skill en 6/6 ejecuciones con skill.
Inconvenientes
- Sin mejora medible frente a sin skill (-0.06, dentro del ruido).
- Un prompt de una frase obtuvo 4.75, frente a 4.48 con la skill (-0.27).
- n=2 por tarea y rama; las diferencias de menos de aproximadamente 1 punto son ruido.
Reseña
Codex CLI 0.166 (gpt-6-astra, razonamiento bajo) en una máquina de pruebas Mac, un proyecto temporal nuevo y HOME/TMPDIR/cachés temporales en cada ejecución, skill instalada (grupo con skill), ausente (control) o ausente con el requisito central de la skill comprimido en una frase añadida al prompt (grupo del prompt de una frase), 2 ejecuciones por grupo y tarea, red desactivada, escrituras en /tmp bloqueadas. Los prompts nunca mencionan la skill (salvo la redacción indicada abajo). Tres tareas: escribir un esquema de Supabase multiinquilino con RLS (comprobaciones: RLS en todas las tablas, auth.uid() envuelto en un select, cada clave foránea indexada, timestamptz, claves identity o uuid, restricciones, nombres en minúsculas), revisar un esquema, unas consultas y un worker defectuosos para detectar 11 problemas plantados, y escribir migraciones de índices más notas para tres consultas lentas sobre una tabla de 120M de filas (índice compuesto, índice parcial, CONCURRENTLY, como máximo 4 índices).
Comparación de tres ramas
| Rama | Puntuación media (0-5) | Tokens por ejecución |
|---|---|---|
| Sin la skill | 4.54 | 77k |
| Prompt de una frase | 4.75 | 80k |
| Con la skill | 4.48 | 93k |
Medido con Codex CLI en 18 ejecuciones, puntuado con comprobaciones basadas en reglas y sin juez LLM. Total 24.4 / 30, veredicto Según el caso.
Veredicto: Según el caso (24.4 / 30). Fuente: supabase/agent-skills, skills/supabase-postgres-best-practices, fijada en el commit c9be0e9. Instalación: npx skills@latest add supabase/agent-skills --skill supabase-postgres-best-practices. Licencia: MIT (LICENSE del repositorio).
Qué es
La skill supabase-postgres-best-practices de supabase/agent-skills: orientación sobre rendimiento y esquema de Postgres para proyectos de Supabase en unos 35 archivos de referencia (rendimiento de consultas e índices, gestión de conexiones, seguridad y RLS, diseño de esquema, concurrencia y bloqueos, patrones de acceso a datos, monitorización), con un SKILL.md de 440 palabras que los indexa. Solo Markdown, sin scripts.
Cómo lo probamos
Codex CLI 0.166 (gpt-6-astra, razonamiento bajo) en un Mac de pruebas, un proyecto temporal nuevo y HOME/TMPDIR/cachés temporales por ejecución, skill instalada (tratamiento) o ausente (control) o ausente con el requisito central de la skill comprimido en una frase añadida al final del prompt (grupo de una frase), 2 ejecuciones por grupo y tarea, red desactivada, escrituras en /tmp bloqueadas. Los prompts nunca mencionan la skill (salvo la formulación indicada abajo).
Tres tareas: escribir un esquema de Supabase multiinquilino con RLS (comprobaciones: RLS en todas las tablas, auth.uid() envuelto en un select, todas las claves foráneas indexadas, claves timestamptz, identity o uuid, restricciones, nombres en minúsculas), revisar un esquema/consultas/worker defectuosos en busca de 11 problemas sembrados, y escribir migraciones de índices más notas para tres consultas lentas sobre una tabla de 120M filas (índice compuesto, índice parcial, CONCURRENTLY, como máximo 4 índices).
- Esquema multiinquilino con RLS — Escribe schema.sql para un gestor de proyectos multiinquilino en Supabase (Postgres): organizaciones, membresías (un usuario de auth de Supabase pertenece a una organización con un rol), proyectos, tareas (responsable, estado, fecha de vencimiento) y comentarios en las tareas. Un usuario solo puede ver y camb…
- Revisar un esquema, consultas y un worker — Revisa schema.sql, queries.sql y worker.py (una aplicación de tickets de soporte en Supabase/Postgres). Enumera los problemas, de más grave a menos, cada uno con su corrección. No cambies ningún archivo. Escribe la lista en tu respuesta final.
- Índices para tres consultas lentas — Las tres consultas de slow_queries.md son lentas sobre la tabla de schema.sql (120M filas). Escribe migration.sql con los cambios de índices que harías (y nada más), y notes.md (como máximo 120 palabras) indicando qué índice sirve a cada consulta y cualquier salvedad. (Sin datos…
La puntuación es programática (pruebas ocultas / detección de problemas sembrados / comprobaciones de restricciones / renderizado+OCR cuando corresponde), 0–5 por ejecución. Ningún juez LLM decidió ninguna puntuación.
Resultados
La frase única que recibió el tercer grupo: "Aplica las buenas prácticas de Postgres: indexa cada clave foránea y cada columna usada en WHERE/ORDER BY (índices compuestos con las columnas de igualdad primero, índices parciales para estados poco frecuentes, CREATE INDEX CONCURRENTLY en tablas grandes), activa RLS en cada tabla expuesta y envuelve auth.uid() en (select auth.uid()), usa timestamptz, claves identity o uuid y nombres en snake_case en minúsculas, pagina con keyset y no con offset, y mantén las transacciones cortas (sin llamadas externas dentro)."
| Tarea | Puntuación del control | Frase única | Con la skill | Tokens del control | Tokens de una frase | Tokens con la skill | Skill leída |
|---|---|---|---|---|---|---|---|
| t1-schema | 4.52 | 4.79 | 4.16 | 104k | 121k | 124k | 2/2 |
| t2-review | 4.09 | 4.46 | 4.28 | 64k | 56k | 70k | 2/2 |
| t3-indexes | 5.0 | 5.0 | 5.0 | 60k | 61k | 84k | 2/2 |
Puntuación media: 4.54 sin vs 4.48 con la skill (delta -0.06). Tokens por ejecución: 77k vs 93k (1.21x); tiempo 78s vs 73s. Grupo de una frase: 4.75 (ganancia de la skill sobre la frase única: -0.27; ganancia de la frase única sobre sin skill: +0.21); tokens de la frase única 80k por ejecución, así que la skill cuesta 1.16x la frase única.
Qué ocurrió
- Ninguna diferencia: media 4.54 control, 4.75 una frase, 4.48 skill. La skill está -0.06 frente al control con 93k tokens por ejecución frente a 77k (1.2x).
- La tarea de índices la resuelven todos los grupos en todas las ejecuciones (las seis comprobaciones de índices pasan 6/6 en todos los grupos, incluido CONCURRENTLY y respetar los 4 índices): Codex a secas ya conoce estos básicos.
- En la tarea de esquema, todos los grupos indexaron todas las claves foráneas, activaron RLS en todas las tablas y usaron claves uuid/identity. Envolver auth.uid() en (select auth.uid()) solo se hizo para parte de las políticas en todos los grupos: 3 de 5-6 apariciones en las ejecuciones de control y de la skill, 5 de 5 en una ejecución de la frase única. El grupo de una frase fue el mejor en esta regla (1.6 de 2 frente a 1.1 de control y skill). Una ejecución de la skill usó una columna timestamp simple (3.86), la puntuación más baja de cualquier ejecución.
- En la tarea de revisión, todos los grupos encontraron 8-9 de los 11 problemas sembrados (1.5-1.7 de 2 comprobaciones); la skill no encontró más.
- La prueba se repitió una vez para la tarea de índices: el primer lote no le dio archivos de entrada por un error en la especificación (la lista de fixtures estaba vacía), así que las 6 ejecuciones dijeron que faltaban los archivos. Corregimos la especificación y volvimos a ejecutar esas 6; las anteriores no cuentan.
Puntuaciones por dimensión
| Dimensión | Puntuación | Motivo |
|---|---|---|
| 1. Calidad del resultado | 4.48 | Puntuación media 4.48/5 con la skill (comprobaciones programáticas; consulta la tabla por tarea). |
| 2. Mejora frente a no usar skill | 1.94 | -0.06 puntos frente a 4.54 sin la skill (n=2 por tarea; menos de ~1 punto es ruido). |
| 3. Activación | 5.0 | Archivo de la skill leído en 6/6 ejecuciones de tratamiento. |
| 4. Portabilidad de las instrucciones | 4 | Archivos de reglas en Markdown simple; sigue la estructura abierta de skills. |
| 5. Eficiencia | 4 | 1.21x tokens (93k vs 77k por ejecución) y 0.93x tiempo (73s vs 78s). |
| 6. Seguridad e higiene | 5 | Solo Markdown; los cuatro aciertos HIGH del escáner son el nombre de
tabla |
Límites de esta prueba
- Problemas de manual en archivos pequeños; no se probaron puntos específicos de Supabase más allá de RLS (agrupación de conexiones, Realtime, almacenamiento).
- Los puntos se comparan con expresiones regulares, así que una corrección formulada de otra manera cuenta como no detectada.
- No se ejercieron las reglas de la skill sobre bloqueos, monitorización y patrones de acceso a datos.
- n = 2 por grupo y tarea: las diferencias de menos de 1 punto son ruido.
- La puntuación basada en reglas mide lo que las comprobaciones pueden ver; no puede juzgar el gusto ni si un resultado es el mejor posible.
Seguridad
Consulta security.md. Escaneo: 0 CRITICAL / 4 HIGH / 0 MEDIUM. Veredicto: seguro para ejecutar (sandbox sin red). Un escaneo limpio no demuestra que una skill sea segura.
En resumen
En tareas de diseño de esquema, revisión e índices, Codex a secas ya aplica las prácticas que enumera esta skill, y la skill no mejoró la puntuación mientras añadía alrededor de un 20% de tokens. Aun así puede ser una referencia útil para temas de Supabase menos comunes que estas pruebas no tocaron.
Transcripción
Registro de ejecuciones: supabase-postgres-best-practices (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) Columnas: tarea, grupo-ejecución, puntuación (0-5), tokens, segundos, comprobaciones superadas, archivos de la skill que abrió el agente. t1-schema control-1: puntuación 4.57, tokens 105331, s 124.5, comprobaciones 6/7, no abrió nada t1-schema control-2: puntuación 4.46, tokens 104624, s 130.1, comprobaciones 6/7, no abrió nada t1-schema oneliner-1: puntuación 5.0, tokens 111153, s 140.4, comprobaciones 7/7, no abrió nada t1-schema oneliner-2: puntuación 4.57, tokens 132693, s 145.1, comprobaciones 6/7, no abrió nada t1-schema treatment-1: puntuación 3.86, tokens 123861, s 108.3, comprobaciones 5/7, abrió supabase-postgres-best-practices t1-schema treatment-2: puntuación 4.46, tokens 124377, s 129.6, comprobaciones 6/7, abrió supabase-postgres-best-practices t2-review control-1: puntuación 4.27, tokens 64780, s 65.4, comprobaciones 2/2, no abrió nada t2-review control-2: puntuación 3.91, tokens 64695, s 71.5, comprobaciones 2/2, no abrió nada t2-review oneliner-1: puntuación 3.91, tokens 45381, s 57.3, comprobaciones 2/2, no abrió nada
18 ejecuciones, 3 artefactos
Resultado de ejemplo
SOTA · With the skill: schema.sql (t1-schema, run 1, Codex)
-- Fresh Supabase database: run once as postgres (trusted BYPASSRLS owner). -- Members manage tenant content; admins also manage settings and memberships. -- service_role bypasses RLS: keep its credentials exclusively on the backend. begin; create schema if not exists private; revoke all on schema private from public, anon; grant usage on schema private to authenticated; -- Keep private out of the Data API's exposed schemas. create table public.organizations ( id uuid primary key default gen_random_uuid(), name text not null check (length(btrim(name)) between 1 and 200), created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create table public.memberships ( organization_id uuid not null references public.organizations(id) on delete cascade, user_id uuid not null references auth.users(id) on delete cascade, role text not null default 'member' check (role in ('admin', 'member')), created_at timestamptz not null default now(), primary key (organization_id, user_id) ); -- Reverse lookup for the caller's tenants, RLS, and auth user deletion. create index memberships_user_idx on public.memberships (user_id, organization_id) include (role); create table public.projects ( id uuid primary key default gen_random_uuid(), organization_id uuid not null references public.organizations(id) on delete cascade, name text not null check (length(btrim(name)) between 1 and 200), description text not null default '', created_at timestamptz not null default now(), updated_at timestamptz not null default now(), unique (organization_id, id) ); create index projects_list_idx on public.projects (organization_id, created_at desc, id desc); create table public.tasks ( id uuid primary key default gen_random_uuid(), organization_id uuid not null references public.organizations(id) on delete cascade, project_id uuid not null, title text not null check (length(btrim(title)) between 1 and 500), description text not null default '', assignee_id uuid, status text not null default 'todo' check (status in ('todo', 'in_progress', 'done', 'cancelled')), due_date date, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), unique (organization_id, id), foreign key (organization_id, project_id) references public.projects (organization_id, id) on delete cascade, -- Unassign tasks before deleting a membership/auth user. Deferred checking -- permits deleting an entire organization and all its children atomically. foreign key (organization_id, assignee_id) references public.memberships (organization_id, user_id) on delete no action deferrable initially deferred ); create index tasks_project_list_idx on public.tasks (organization_id, project_id, created_at desc, id desc); create index tasks_board_idx on public.tasks (organization_id, project_id, status, created_at desc, id desc); create index tasks_assignee_idx on public.tasks (organization_id, assignee_id, status, due_date, id) where assignee_id is not null; create index tasks_open_due_idx on public.tasks (organization_id, due_date, id) where status in ('todo', 'in_progress') [... excerpt: first 3200 of 11674 characters]