Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Data Storage

ASecurity

Choosing and using the right store — relational SQL (PostgreSQL and friends), NoSQL (document, key-value, wide-column, graph), embedded/in-app databases (SQLite, Room, Drift, Realm), Redis as cache and in-memory store, and Elasticsearch/OpenSearch as a search and read-load layer in front of the database. Covers when each is justified, cache invalidation, indexing, migrations and the polyglot-persistence trade-off. Invoke when a change adds or touches a datastore, a cache, a search index, or a...

3 stars
0 votes
0 copies
1 views
Added 9/6/2026
ai-agentsgoswiftsqltestingdatabaseperformance

Works with

cursorcli

Security Analysis

A100/100

Scanned 9/6/2026

$npx -y skills add cyber93de/aiflow --skill data-storage --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Data Storage?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Data Storage
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/cyber93de-data-storage/badge)](https://www.skillsdirectory.com/skills/cyber93de-data-storage)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: data-storage
description: Choosing and using the right store — relational SQL (PostgreSQL and friends), NoSQL (document, key-value, wide-column, graph), embedded/in-app databases (SQLite, Room, Drift, Realm), Redis as cache and in-memory store, and Elasticsearch/OpenSearch as a search and read-load layer in front of the database. Covers when each is justified, cache invalidation, indexing, migrations and the polyglot-persistence trade-off. Invoke when a change adds or touches a datastore, a cache, a search index, or a migration, when a read path is slow, or on explicit request — "database", "SQL", "NoSQL", "MongoDB", "Redis", "cache", "Elasticsearch", "SQLite", "index", "migration".
---

# Data & storage — SQL · NoSQL · in-app DB · Redis · Elasticsearch

Extends `AGENTS.md` §3c (database modelling rules, MANDATORY) with the *choice* of store and the
performance layers §3a asks you to consider deliberately.

## Default: a relational database

PostgreSQL unless there is a stated reason otherwise. It does JSON, full-text search, geospatial,
arrays, LISTEN/NOTIFY, partitioning and window functions — a surprising number of "we need a
document store / a search engine / a queue" requirements are one Postgres feature away. The §3c
design rules (≥3NF, real foreign keys, `NOT NULL` by default, `CHECK` constraints, `UNIQUE` on
natural keys, precise types, junction tables, no needless surrogate keys) apply in full to anything
you create new. Brownfield schemas fall under §3c's B-rules: **note improvement potential as beads,
don't restructure as a side effect** — other systems may share that schema and old app versions may
need to roll back onto it.

**Migrations** are versioned, forward-only, and reviewed like code (Flyway, Liquibase, EF
Migrations, `sqlx migrate`, Alembic). Expand–contract for anything a running deployment reads:
add the new column → backfill → dual-write → switch reads → drop the old one, in separate releases.
A migration that locks a large table in a single statement is an outage.

## When NoSQL is actually justified

| Kind | Justified when | Not justified because |
|------|----------------|------------------------|
| **Document** (MongoDB, DynamoDB) | genuinely schema-variable aggregates, single-key access dominates, horizontal write scale | "schemas are annoying" — you still have a schema, it's just enforced nowhere |
| **Key-value** (Redis, DynamoDB) | cache, session, rate limiter, ephemeral state | it is your system of record |
| **Wide-column** (Cassandra, Scylla) | huge write volume, known query patterns, multi-region | you'd like it to be fast |
| **Graph** (Neo4j) | traversal depth is the query (recommendations, permissions, fraud rings) | your data merely has foreign keys |
| **Time-series** (Timescale, Influx) | metrics/telemetry at scale with retention and downsampling | you have a `created_at` column |

Choosing NoSQL means giving up joins, cross-document transactions, and schema enforcement — you now
own consistency in application code. Say so out loud, record the decision, and don't spread data
across five stores because each one is individually defensible: **polyglot persistence multiplies
your operational and consistency burden.**

## Embedded / in-app databases

SQLite (Room, Drift, GRDB, SwiftData, `sqflite`) or Realm on client devices. Treat it as a real
database, not a cache file: migrations are versioned and tested against an *old* database file,
schema changes ship with an upgrade path, and the file is encrypted (SQLCipher / Realm encryption)
where it holds anything personal. It is also the offline layer — see the **stack-mobile** skill for
sync and conflict resolution. Never ship an app that wipes user data on a schema mismatch.

## Redis — cache and in-memory store

Worth it when a measurable read path is slow, or when you need something a relational store models
badly: sessions, rate limiting, distributed locks (Redlock, with its caveats), leaderboards,
short-lived queues, pub/sub fan-out.

Rules that keep it from becoming the outage:
- **Every key has a TTL** unless you can name who deletes it. Unbounded key growth is the classic
  Redis incident.
- **Cache invalidation is designed, not hoped for.** Pick one: TTL-only (accept staleness, state
  the window), write-through, or explicit invalidation on write. Write it down.
- **The cache is never the source of truth** — a cold Redis must be survivable, just slower.
  Guard against stampedes (jittered TTLs, single-flight) and cache the negative result too.
- Namespaced key schema (`app:v1:user:{id}:profile`), documented, versioned so a format change
  doesn't read stale garbage.
- Measure the hit rate. A cache below ~80 % hit rate on a hot path is usually the wrong key.

## Elasticsearch / OpenSearch

The right tool for relevance-ranked full-text search, faceting, and aggregations over large
volumes — and, as §3a notes, a way to **decouple the database from the application** by absorbing
read load that would otherwise hammer the primary.

- **It is a derived index, never the source of truth.** You must be able to rebuild it from the
  database — and that rebuild path is tested, not theoretical.
- Feed it from the outbox/CDC stream (see **messaging-events**), not by dual-writing from the
  service — dual writes diverge the first time one of them fails.
- Design the mapping deliberately (analysers, `keyword` vs `text`, no dynamic mapping explosion);
  index only fields you actually query.
- Reindex behind an **alias** so a mapping change is a zero-downtime alias swap.
- Before adopting it: check whether Postgres full-text search or a materialised view already
  answers the requirement (`ponytail`, §2a reuse). Elasticsearch is a second datastore to operate,
  secure and keep in sync.

## Performance basics

Index what you filter, join and sort on — and **only** that (§3c R11); every index costs write
throughput. Read the query plan before adding one. Fix N+1 at the source (batch/join/`DataLoader`),
not with a cache. Paginate every unbounded query, cursor-based for large sets. Use connection
pooling with a bounded pool, and never hold a transaction across a network call.

## Testing (§3a)

Integration tests run against the **real** engine in Testcontainers — H2 standing in for
PostgreSQL, or fakeredis for Redis, hides dialect and eviction behaviour, which is exactly where
the bugs are. Test migrations both ways: apply to an empty DB **and** to a snapshot of the current
production schema. Test cache-miss and cache-stale paths explicitly, and test the search index
rebuild.

## Typical findings to raise

Soft foreign key without a real constraint (§3c R4) · nullable column that is never actually
unknown (R6) · missing index on a filtered column, or an index-everything strategy (R11) · a cache
key with no TTL · cache used as the source of truth · dual-write to DB and search index ·
`SELECT *` with no pagination · N+1 hidden behind a cache · migration that rewrites a large table
in one statement · a second datastore introduced without a recorded decision.

Attribution

cyber93decyber93de
View sourceSee grades on GitHubMore from cyber93de →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698621 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →