executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
backend-patternsApply backend patterns — queues, caching, rate limits, serverless/edge. Use when "queue jobs", "caching layer", "rate limiting", "server actions", or "edge function". Which architecture to pick → audit-backend-architecture.
Independent GitHub snapshot · Automated classification · Original documentation governs
Degree of freedom: MIXED. Which pattern to apply [HIGH freedom];
existing-architecture probes and the validation list [LOW freedom — run exactly].
Observe:
createOrdersends email inline; no Inngest/queue; checkout p95 4s. Interpret: confirmation is post-response work, not request-path. Classify:after()or anorder/createdjob; keep the write transactional. Verify: order row commits; email/inventory run after response; retries do not double-charge.
audit-backend-architectureDesign scalable, maintainable backend architectures using modern patterns and best practices.
Code examples lean on Next.js App Router + Supabase/Prisma. The patterns are stack-agnostic — adapt ORMs, client libraries, and deploy targets to your detected ecosystem.
Before implementing ANY backend pattern, verify:
ls -la src/server/ src/api/ app/api/ supabase/functions/ 2>/dev/null
cat package.json | grep -i "prisma\|drizzle\|supabase\|trpc"
rg "createTRPCRouter|publicProcedure" --type ts -l
rg "'use server'" --type ts -l
ls -la supabase/migrations/*.sql 2>/dev/null | tail -5
cat prisma/schema.prisma 2>/dev/null | head -50
cat supabase/config.toml 2>/dev/null
Why: Backend changes have wide impact. Understand existing architecture first.
Next.js 16: Turbopack default; 'use cache' + cacheComponents; reactCompiler: true; middleware.ts → proxy.ts (grep both). Instant navigations → enhance-web-instant-nav.
safeParse → execute → map known errors (Prisma P2002) → generic failure message.ActionResult<T>: { success: true, data } or { success: false, error, fieldErrors? }; never throw to the client.revalidatePath after a successful write.after() from next/server, keeping the write transactional.'use server'
import { after } from 'next/server'
export async function createOrder(formData: FormData) {
const order = await db.order.create({ data: { /* ... */ } })
after(async () => { // runs after the response is sent
await sendOrderConfirmation(order.id)
await updateInventory(order.items)
})
revalidatePath('/orders')
return { success: true, data: order }
}
Full createUser action and the after() example: references/request-patterns.md §Server Actions.
publicProcedure for reads anyone may do; protectedProcedure for anything that uses ctx.session..input(); mutations stamp createdById from the session, not the input.limit + 1, pop the extra row as nextCursor.Full usersRouter (getById, create, cursor-paginated list): references/request-patterns.md §tRPC router definition.
Deno.serve; answer OPTIONS with the CORS headers first.401 on mismatch.SUPABASE_SERVICE_ROLE_KEY bypasses RLS; use it only inside the function.500 JSON body with CORS headers.Full process-webhook function: references/request-patterns.md §Supabase Edge Function.
version INT column; UPDATE ... WHERE id = $1 AND version = $2 and treat 0 rows as a concurrent update.deletedAt with an index; every read filters deletedAt: null; delete sets the timestamp.audit_logs(table_name, record_id, action, old_data, new_data, user_id) filled by a SECURITY DEFINER trigger using TG_OP, row_to_json, auth.uid().UPDATE orders SET status = 'shipped', version = version + 1
WHERE id = $1 AND version = $2; -- 0 rows → concurrent update, retry or surface conflict
Soft-delete Prisma model and the full audit trigger: references/data-and-jobs.md §Soft deletes, §Audit logging.
fetch(url, { next: { revalidate, tags } }); revalidateTag on demand; unstable_cache around DB queries with tags.getCachedData(key, fetcher, ttl) helper, cache-aside; key by entity and id (user:${id}).const getCachedUser = unstable_cache(
async (id: string) => db.user.findUnique({ where: { id } }),
['user'],
{ revalidate: 3600, tags: ['users'] }
)
Next.js cache calls and the Redis helper: references/data-and-jobs.md §Next.js cache, §Redis caching.
inngest.createFunction({ id }, { event }, async ({ event, step }) => ...); each side effect in its own step.run so retries resume, not restart.inngest.send({ name: 'order/created', data }) from the Server Action after the write commits.step.run + return { status: 'cancelled' }, not a throw.export const processOrder = inngest.createFunction(
{ id: 'process-order' }, { event: 'order/created' },
async ({ event, step }) => {
const payment = await step.run('charge-payment', () => chargeCustomer(event.data.paymentMethod))
await step.run('send-confirmation', () => sendOrderConfirmation(event.data.orderId))
return { status: 'completed', paymentId: payment.id }
}
)
Full Inngest function and the Trigger.dev scheduled-task alternative: references/data-and-jobs.md §Background jobs, §Alternatives.
@upstash/ratelimit with Ratelimit.slidingWindow(10, '10 s') over Redis.fromEnv().!success return Too many requests with retryAfter seconds from reset.Full rateLimitedAction: references/request-patterns.md §Rate limiting.
Gateway, BFF, bulkhead, circuit breaker, outbox+CDC, saga, hexagonal, ACL, and strangler-fig →
references/architecture-patterns.md. Pick the pattern for the
topology (no mesh on a monolith; no CQRS unless reads/writes diverge). Timeouts/retries/idempotency
→ audit-resilience; structural gap report → audit-backend-architecture.
After implementing backend patterns: