---
title: "Map every store that holds personal data · Agent Wranglers"
url: https://agentwranglers.se/playbook/compliance/records-and-data-map/data-map
updated: 2026-10-20
licence: "All rights reserved"
---

# Map every store that holds personal data

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

- Level: Required
- Chapter: [Records and data map](https://agentwranglers.se/playbook/compliance/records-and-data-map)
- Rule: Keep a data map in the repository of every place personal data is stored or sent. Give each its region, its owner and the kinds of data in it.
- How: Include databases, file buckets, caches, search indexes, queues, logs, backups, analytics, the email service, the support desk and every AI provider. Give each store a stable ID that the other registers refer to. Generate the list of stores from your infrastructure code, such as Terraform state, and compare it with the map in the build. The [personal data columns rule](https://agentwranglers.se/playbook/data/personal-data/minimal-columns) lists the columns inside each database.
- Check: The build compares the stores defined in infrastructure code and the external hostnames the app calls with the data map. It fails on any store or host missing from the map.

Example:

```yaml
- id: orders-db
  kind: database
  provider: hosting-eu
  region: eu-north-1
  data: [name, email, address, order history]
  subjects: [customers]
  owner: maria.lind
- id: support-desk
  kind: processor
  provider: helpdesk-us
  region: us-east
  data: [name, email, message text]
  subjects: [customers, prospects]
  owner: jonas.berg
```

```js
import { readFileSync } from 'node:fs';
import { parse } from 'yaml';

const mapped = new Set(parse(readFileSync('compliance/data-map.yaml', 'utf8')).map(store => store.id));
const state = JSON.parse(readFileSync('terraform-show.json', 'utf8'));
const STORE_TYPES = ['aws_db_instance', 'aws_s3_bucket', 'aws_elasticache_cluster', 'aws_opensearch_domain'];
const unmapped = state.values.root_module.resources
  .filter(resource => STORE_TYPES.includes(resource.type))
  .map(resource => resource.values.tags?.data_map_id ?? resource.address)
  .filter(id => !mapped.has(id));
if (unmapped.length) { console.error(`Stores missing from the data map: ${unmapped.join(', ')}`); process.exit(1); }
```

```python
import json, sys, yaml

mapped = {store["id"] for store in yaml.safe_load(open("compliance/data-map.yaml"))}
state = json.load(open("terraform-show.json"))
STORE_TYPES = {"aws_db_instance", "aws_s3_bucket", "aws_elasticache_cluster", "aws_opensearch_domain"}
unmapped = [
    (r["values"].get("tags") or {}).get("data_map_id", r["address"])
    for r in state["values"]["root_module"]["resources"] if r["type"] in STORE_TYPES
]
missing = [store_id for store_id in unmapped if store_id not in mapped]
sys.exit(f"Stores missing from the data map: {', '.join(missing)}" if missing else None)
```

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers compliance playbook: https://agentwranglers.se/playbook/compliance/records-and-data-map/data-map`.

- Next: [Keep the record of processing as data](https://agentwranglers.se/playbook/compliance/records-and-data-map/records-of-processing)
- [Records and data map](https://agentwranglers.se/playbook/compliance/records-and-data-map)
