---
title: "Weigh every legitimate interest in writing · Agent Wranglers"
url: https://agentwranglers.se/playbook/compliance/records-and-data-map/legitimate-interests-assessment
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Weigh every legitimate interest in writing

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/compliance/rules.json) holds every rule of this playbook as JSON.

- Level: Recommended
- Chapter: [Records and data map](https://agentwranglers.se/playbook/compliance/records-and-data-map)
- Rule: Before a purpose relies on legitimate interests, write an assessment with the purpose, necessity and balancing tests. Stop the processing for anyone who objects, unless the assessment shows compelling grounds.
- Applies when: The project it has users in the EU.
- How: GDPR Article 6(1)(f) allows processing that is necessary for a legitimate interest, unless the person's rights override it. Fraud checks, security logs and product analytics often rely on it. The purpose test names the interest and who benefits. The necessity test asks whether less data, or none, would do. The balancing test weighs the effect on people, what they would expect, and whether children are involved. Article 21 lets people object to this processing at any time. An objection to direct marketing always stops it. Public authorities cannot use this basis for their public tasks. When the balancing finds high risk, run the [DPIA screening](https://agentwranglers.se/playbook/compliance/records-and-data-map/dpia-screening). Stop marketing mail at once with [one-click unsubscribe](https://agentwranglers.se/playbook/email/unsubscribe-and-bounces/one-click-unsubscribe).
- Check: Every record of processing entry with the basis `legitimate_interests` links an assessment with the three tests filled in and a review date within 12 months. An end-to-end test sends an objection to direct marketing, and the next marketing job skips that person.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### YAML example

```yaml
- purpose: fraud-checks
  legal_basis: legitimate_interests
  assessment:
    purpose_test: Stop stolen cards from paying for orders, which protects the shop and card holders
    necessity_test: Uses order amount, card country and device signals, no browsing history
    balancing_test: Customers expect fraud checks at checkout, and no children use the service
    result: proceed
    reviewed: 2026-10-01
```

### JavaScript example

```js
const TESTS = ['purpose_test', 'necessity_test', 'balancing_test'];
const MAX_AGE_DAYS = 365;
const DAY_MS = 86_400_000;

export const assessmentProblems = (entry, now = Date.now()) => {
  if (entry.legal_basis !== 'legitimate_interests') return [];
  const assessment = entry.assessment ?? {};
  const missing = TESTS.filter(test => !assessment[test]).map(test => `${entry.purpose}: no ${test}`);
  const isStale = !assessment.reviewed || now - Date.parse(assessment.reviewed) > MAX_AGE_DAYS * DAY_MS;
  return isStale ? [...missing, `${entry.purpose}: review older than ${MAX_AGE_DAYS} days`] : missing;
};
```

### Python example

```python
from datetime import date, timedelta

TESTS = ["purpose_test", "necessity_test", "balancing_test"]
MAX_AGE = timedelta(days=365)

def assessment_problems(entry: dict, today: date | None = None) -> list[str]:
    if entry.get("legal_basis") != "legitimate_interests":
        return []
    today = today or date.today()
    assessment = entry.get("assessment") or {}
    problems = [f"{entry['purpose']}: no {test}" for test in TESTS if not assessment.get(test)]
    reviewed = assessment.get("reviewed")
    if not reviewed or today - reviewed > MAX_AGE:
        problems.append(f"{entry['purpose']}: review older than {MAX_AGE.days} days")
    return problems
```

## Sources

- [GDPR Articles 6 and 21](https://eur-lex.europa.eu/eli/reg/2016/679/oj)
- [EDPB Guidelines 1/2024 on legitimate interest](https://www.edpb.europa.eu/our-work-tools/documents/public-consultations/2024/guidelines-12024-processing-personal-data-based_en)
- [ICO guidance on applying legitimate interests](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/lawful-basis/legitimate-interests/how-do-we-apply-legitimate-interests-in-practice/)

## Related rules

- [Screen every new feature for a DPIA](https://agentwranglers.se/playbook/compliance/records-and-data-map/dpia-screening) in Compliance
- [Offer one-click unsubscribe](https://agentwranglers.se/playbook/email/unsubscribe-and-bounces/one-click-unsubscribe) in Email

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/compliance/records-and-data-map/legitimate-interests-assessment">Agent Wranglers compliance playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Keep one retention schedule](https://agentwranglers.se/playbook/compliance/records-and-data-map/retention-schedule)
- [Records and data map](https://agentwranglers.se/playbook/compliance/records-and-data-map)
