Skip to content

Instantly share code, notes, and snippets.

@coderbyheart
Created June 1, 2026 07:51
Show Gist options
  • Select an option

  • Save coderbyheart/0335d3595d10726c6d7dbaf991723809 to your computer and use it in GitHub Desktop.

Select an option

Save coderbyheart/0335d3595d10726c6d7dbaf991723809 to your computer and use it in GitHub Desktop.
wipe-tables.ts
/**
* Wipes all items from every DynamoDB table whose name starts with the given
* prefix.
*
* Lists all tables in the account, keeps the ones matching the prefix, and for
* each one scans every item (projecting only the key attributes) and deletes
* them in batches of 25 via `BatchWriteItem`. Tables with deletion protection
* enabled are skipped. The table itself is left in place — only its contents
* are removed.
*
* Intended as an operator script for tearing down CI stack data.
*
* Usage:
* node --experimental-transform-types --no-warnings wipe-tables.ts [prefix]
*/
import {
BatchWriteItemCommand,
DescribeTableCommand,
DynamoDBClient,
paginateListTables,
paginateScan,
} from '@aws-sdk/client-dynamodb'
const db = new DynamoDBClient()
const prefix = process.argv[2]
if (prefix === undefined) {
console.error('Usage: ts-node wipe-tables.ts [prefix]')
process.exit(1)
}
// Get all tables prefixed with the provided prefix
const tables: string[] = []
for await (const { TableNames } of paginateListTables({ client: db }, {})) {
tables.push(...(TableNames ?? []).filter((name) => name.startsWith(prefix)))
}
for (const TableName of tables) {
const { Table } = await db.send(new DescribeTableCommand({ TableName }))
// Check that deletion protection is disabled
if (Table?.DeletionProtectionEnabled === true) {
console.log(`Skipping ${TableName}: deletion protection is enabled`)
continue
}
const keyAttributes = (Table?.KeySchema ?? []).map(
({ AttributeName }) => AttributeName as string,
)
// Delete all items in the table
let deleted = 0
let batch: Record<string, unknown>[] = []
const flush = async () => {
if (batch.length === 0) return
await db.send(
new BatchWriteItemCommand({
RequestItems: {
[TableName]: batch.map((Key) => ({
DeleteRequest: { Key: Key as never },
})),
},
}),
)
deleted += batch.length
batch = []
}
for await (const { Items } of paginateScan(
{ client: db },
{
TableName,
ProjectionExpression: keyAttributes.map((_, i) => `#k${i}`).join(', '),
ExpressionAttributeNames: Object.fromEntries(
keyAttributes.map((name, i) => [`#k${i}`, name]),
),
},
)) {
for (const item of Items ?? []) {
batch.push(item)
// BatchWriteItem allows at most 25 requests per call
if (batch.length === 25) await flush()
}
}
await flush()
console.log(`Wiped ${TableName}: deleted ${deleted} items`)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment