# Bulk operations available where needed

- **Pattern:** `ab-002202` (`saas-api-design.request-response.bulk-operations`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002202
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002202)

## Why it matters

When bulk UI affordances (select-all-and-delete, bulk publish, batch price update) exist but the API offers only single-record endpoints, clients must fire N sequential requests to complete the operation. This is both a performance problem (N round trips, N transaction commits) and a data integrity risk: a network failure partway through leaves records in an inconsistent state with no rollback. ISO-25010:2011 performance-efficiency.resource-utilization is directly undermined, and the user experience degrades as dataset size grows.

## Severity rationale

Low because the absence of bulk endpoints degrades performance and UX rather than enabling immediate security exploits, but data integrity risk from partial-batch failures can be severe.

## Remediation

Add a batch endpoint in `app/api/` for each resource type where your UI or business logic already implies multi-record operations. A practical pattern:

```ts
// POST /api/messages/bulk
const { action, ids } = bulkSchema.parse(await req.json())
// bulkSchema enforces: action is one of ['delete', 'archive'], ids.length <= 100

if (action === 'delete') {
  await db.$transaction(
    ids.map((id) => db.message.delete({ where: { id, userId } }))
  )
}
```

Always enforce a maximum batch size (100 records is a reasonable default) to prevent abuse. Wrap all operations in a database transaction so partial failures roll back atomically rather than leaving records in an inconsistent state.

## Detection

- **ID:** `bulk-operations`
- **Severity:** `low`
- **What to look for:** Enumerate all resource types in the codebase. Identify use cases where multiple records of the same type are likely to be created, updated, or deleted together — look at the app's domain (e.g., a todo app would need bulk complete, a CMS would need bulk publish, an e-commerce app would need bulk price updates). Check whether bulk operation endpoints exist for those use cases. Also check: if bulk ops exist, do they have appropriate limits on the number of records per request?
- **Pass criteria:** Either (a) at least 1 bulk operation endpoint exists for primary resource types where batch operations are meaningful, or (b) the application domain genuinely does not require batch operations (single-record operations cover all use cases).
- **Fail criteria:** Client code or UI patterns suggest bulk operations are needed (e.g., "select all and delete" UI exists) but the API requires N individual requests; or bulk operations exist but have no limit on batch size.
- **Skip (N/A) when:** The application clearly operates on single records by design (e.g., a single-user personal tool, a single-item workflow). Signal: no UI patterns or business logic suggesting multi-record batch operations.
- **Detail on fail:** Example: `UI supports bulk delete but API requires N individual requests`. Describe the gap (e.g., "UI supports bulk delete of messages but API only has DELETE /api/messages/:id, requiring N separate requests"). Max 500 chars.
- **Remediation:** Add bulk operation endpoints in `app/api/` for high-value use cases. A practical pattern is a batch endpoint that accepts an array of IDs and an operation: `POST /api/messages/bulk { action: "delete", ids: ["id1", "id2"] }`. Validate and enforce a maximum batch size (e.g., 100 records per request) to prevent abuse. Wrap bulk operations in a database transaction so they succeed or fail atomically — partial success states are a common source of data integrity issues.

---

## External references

- iso-25010 performance-efficiency.resource-utilization

Taxons: user-experience, cost-efficiency

HTML version: https://auditbuffet.com/patterns/ab-002202
