ts-db-perf — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ts-db-perf (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Optimize: $ARGUMENTS
The classic trap: fetching a list, then querying per item in a loop.
// N+1: one query for the list, one per item
const orders = await db.order.findMany();
for (const order of orders) {
order.customer = await db.customer.findUnique({ where: { id: order.customerId } });
}
// Resolved: single query with join/include
const orders = await db.order.findMany({
include: { customer: true },
});If the ORM doesn't support include, use a WHERE id IN (...) or a JOIN.
// Over-fetching
const users = await db.user.findMany();
// Tight select
const users = await db.user.findMany({
select: { id: true, email: true },
});Applies to raw SQL too -- avoid SELECT * when you only need a few columns.
Always paginate list endpoints. Cursor-based for large/real-time datasets, offset-based for simple cases.
// Offset-based
const [data, total] = await Promise.all([
db.user.findMany({ skip: (page - 1) * limit, take: limit }),
db.user.count(),
]);
// Cursor-based (no count query, stable under writes)
const items = await db.message.findMany({
take: limit,
cursor: cursor ? { id: cursor } : undefined,
orderBy: { createdAt: "desc" },
});Cache where data is read-heavy and stale reads are tolerable.
async function getExchangeRate(from: string, to: string): Promise<number> {
const key = `rate:${from}:${to}`;
const cached = await cache.get(key);
if (cached !== null) return Number(cached);
const rate = await fetchRateFromAPI(from, to);
await cache.set(key, String(rate), { ttl: 60 }); // 60s TTL
return rate;
}For repository-level caching, wrap the lookup:
async findById(id: string): Promise<User | null> {
const cached = await cache.get(`user:${id}`);
if (cached) return JSON.parse(cached);
const user = await db.user.findUnique({ where: { id } });
if (user) await cache.set(`user:${id}`, JSON.stringify(user), { ttl: 300 });
return user;
}Invalidate on writes. Prefer short TTLs over complex invalidation logic.
// Sequential writes outside a transaction -- slow and non-atomic
for (const item of items) {
await db.item.update({ where: { id: item.id }, data: item });
}
// Batched in a transaction -- fast and atomic
await db.$transaction(
items.map((item) =>
db.item.update({ where: { id: item.id }, data: item })
)
);For large batches, chunk to avoid exceeding connection limits or statement size:
const CHUNK = 100;
for (let i = 0; i < items.length; i += CHUNK) {
await db.$transaction(
items.slice(i, i + CHUNK).map((item) =>
db.item.update({ where: { id: item.id }, data: item })
)
);
}Critical for balance updates, inventory, counters -- anything that reads-then-writes.
Optimistic locking (version column):
const result = await db.account.update({
where: { id: accountId, version: currentVersion },
data: { balance: newBalance, version: { increment: 1 } },
});
if (!result) throw new ConflictError("Concurrent modification");Atomic updates (no read needed):
await db.account.update({
where: { id: accountId },
data: { balance: { increment: amount } },
});Distributed lock (Redis/Valkey, for cross-service coordination):
const lock = await acquireLock(`balance:${accountId}`, 30_000);
try {
await db.$transaction(async (tx) => {
await tx.$executeRaw`
UPDATE account SET balance = balance + ${amount} WHERE id = ${accountId}
`;
});
} finally {
await releaseLock(`balance:${accountId}`, lock);
}Idempotency (webhooks, retries):
const key = `processed:${eventId}`;
if (await cache.get(key)) return { status: "already_processed" };
await cache.set(key, "processing", { ttl: 3600 });
// ... do work ...
await cache.set(key, "done", { ttl: 86_400 });Independent lookups should run concurrently.
// Sequential -- 2 round-trips
const user = await db.user.findUnique({ where: { id } });
const settings = await db.settings.findUnique({ where: { userId: id } });
// Parallel -- 1 round-trip wall time
const [user, settings] = await Promise.all([
db.user.findUnique({ where: { id } }),
db.settings.findUnique({ where: { userId: id } }),
]);Use Promise.allSettled when partial failures are acceptable.
Early returns over nesting:
// Nested
async function process(data: Input | null) {
if (data) {
if (data.valid) {
// actual logic
}
}
}
// Flat
async function process(data: Input | null) {
if (!data || !data.valid) return;
// actual logic
}Extract helpers for repeated patterns:
function ensureFound<T>(value: T | null | undefined, label: string): T {
if (value == null) throw new NotFoundError(`${label} not found`);
return value;
}~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.