---
name: "GDPR Subprocessor Register Template"
version: "1.0"
updated: "2026-07-20"
source: "https://www.orbiqhq.com/templates/gdpr-subprocessor-register"
license: "Free to use and adapt within your organisation. Attribution appreciated. Not legal advice."
legal_basis:
  - "https://eur-lex.europa.eu/eli/reg/2016/679/oj"            # GDPR — Art. 28(2), 28(3)(d), 28(4), 30(2), Chapter V
  - "https://eur-lex.europa.eu/eli/dec_impl/2021/914/oj"       # SCCs for transfers to third countries
  - "https://www.edpb.europa.eu/documents/opinion-of-the-board-art-64/opinion-222024-on-certain-obligations-following-from-the_en"  # EDPB Opinion 22/2024
---

# GDPR Subprocessor Register Template (machine-readable)

Purpose: maintain the subprocessor list a processor needs under GDPR Article 28(2) and EDPB
Opinion 22/2024 — every subprocessor in the chain with identity, service, data categories,
processing location, transfer mechanism and security guarantees — together with the change log
(the Article 28(2) notice evidence trail) and the due-diligence log (the ongoing Article 28(1)
"sufficient guarantees" record). This file is self-contained: an agent can create register
records, generate the public subprocessor list, drive change notices, and keep the due-diligence
schedule from the definitions below.

Structural rules:
1. ONE register record per subprocessor, INCLUDING sub-subprocessors further down the chain
   (EDPB Opinion 22/2024: the controller must be able to identify every actor in the chain).
   Chain membership is expressed with `engaged_by` + `chain_tier`, never by omission.
2. The register is the SOURCE; the public subprocessor page / Trust Center list is a projection
   of records with `status` in {active, announced}. Records are never deleted — removals flip
   `status` to `removed` and keep their history.
3. A new engagement follows the sequence: due-diligence record (approved) → register record with
   `status: announced` → change-log record with notice sent → `status: active` only after
   `objection_deadline` passes with no unresolved objection.
4. This register is NOT a Record of Processing Activities (GDPR Art. 30 — see
   gdpr-ropa-template.md) and NOT the change notice itself (see
   gdpr-subprocessor-change-notice.md). The three files key into each other via
   `subprocessor_name` and `notice_ref`.

Jurisdiction notes: UK GDPR carries Article 28 unchanged (ICO expects an explicit objection
deadline). Norway applies the GDPR via the EEA Agreement (personopplysningsloven, Datatilsynet).
EEA→UK transfers ride on the renewed UK adequacy decisions (extended 2025, sunset 2031-12-27);
EEA-internal processing including Norway needs no transfer mechanism.

---

## 1. Subprocessor Register — one record per subprocessor in the chain

| # | Field | Type | Definition / rule |
|---|---|---|---|
| 1 | `subprocessor_name` | text, unique | PRIMARY KEY — legal entity name |
| 2 | `registered_address` | text | Registered address (EDPB 22/2024: identity + address for every chain actor) |
| 3 | `country_of_establishment` | text (ISO 3166-1 alpha-2) | Where the entity is established |
| 4 | `contact` | text (email/URL) | Privacy/DPO contact for the subprocessor |
| 5 | `service_description` | text | What the subprocessor does and which product/service it supports |
| 6 | `data_categories` | list | Categories of personal data processed (e.g. contact data, usage data, customer content) |
| 7 | `special_categories` | enum: `yes` / `no` | Art. 9 special categories involved? If `yes`, due diligence and notice depth increase |
| 8 | `processing_locations` | list of countries | Where the data is actually processed (not the HQ) |
| 9 | `transfer_mechanism` | enum | `none_eea_only` / `adequacy_decision` / `sccs_2021_914_plus_tia` / `binding_corporate_rules` / `other_art46_safeguard` / `art49_derogation_exceptional` |
| 10 | `transfer_detail` | text | Which adequacy decision, or SCC module + TIA date. Required unless mechanism is `none_eea_only` |
| 11 | `security_guarantees` | text | Certifications (ISO/IEC 27001, SOC 2) or TOMs summary supporting Art. 28(1) |
| 12 | `engaged_by` | text | Chain parent: `us` for direct subprocessors, else the name of the engaging (sub)processor |
| 13 | `chain_tier` | enum: `tier1` / `tier2` / `tier3_or_deeper` | Depth in the sub-processing chain |
| 14 | `flowdown_contract_date` | date (ISO 8601) | Date of the Art. 28(4) flow-down contract imposing the same obligations |
| 15 | `status` | enum | `announced` (objection window open) / `active` / `offboarding` / `removed` |
| 16 | `effective_date` | date | When processing starts/started. For `announced` records this MUST be after `objection_deadline` |
| 17 | `last_verified` | date | Last due-diligence re-verification (join to Due Diligence Log) |
| 18 | `notice_ref` | text | Latest change-log record covering this subprocessor |

## 2. Change Log — one record per change

| # | Field | Type | Definition / rule |
|---|---|---|---|
| 1 | `notice_ref` | text, unique | PRIMARY KEY, e.g. `SUB-2026-002` |
| 2 | `notice_sent` | date | Date the notice went to controllers (push, not page-update-only) |
| 3 | `subprocessor_name` | text | FK → register |
| 4 | `change_type` | enum | `addition` / `replacement` / `removal` / `material_change` |
| 5 | `summary` | text | What changed, in controller-readable terms |
| 6 | `channels` | list | e.g. `email_subscribers`, `trust_center_update` — at least one active (push) channel required |
| 7 | `controllers_scope` | text | Which controllers were notified (all / segment) |
| 8 | `objection_deadline` | date | Explicit deadline; window is contractual (~15 days typical, 30–60 negotiated, 90 rare) |
| 9 | `objections_received` | integer | Count of objections |
| 10 | `outcome` | enum | `window_open` / `no_objection_effective` / `workaround_agreed` / `objection_upheld_not_engaged` / `contract_terminated_by_controller` / `withdrawn` |
| 11 | `effective_date` | date | When the change takes/took effect |
| 12 | `register_updated` | date | When the register/public list was updated (must be ≤ `notice_sent`) |
| 13 | `evidence_link` | text | Stored notice document / send log |

## 3. Due Diligence Log — one record per assessment

| # | Field | Type | Definition / rule |
|---|---|---|---|
| 1 | `subprocessor_name` | text | FK → register |
| 2 | `assessment_date` | date | When the assessment was performed |
| 3 | `assessor` | text (role) | e.g. DPO, Security Lead |
| 4 | `guarantees_reviewed` | text | What was examined: certificates, audit reports, TOMs, breach history |
| 5 | `certifications_verified` | list | e.g. `ISO/IEC 27001:2022`, `SOC 2 Type II` — verify scope + validity, not logos |
| 6 | `toms_ref` | text | Reference to the reviewed technical and organisational measures |
| 7 | `tia_date` | date or `n/a` | Transfer impact assessment date — REQUIRED when `transfer_mechanism` = `sccs_2021_914_plus_tia` |
| 8 | `subsubprocessors_disclosed` | enum: `yes` / `no` | Whether the subprocessor disclosed its own chain (EDPB 22/2024 expects full-chain visibility) |
| 9 | `result` | enum | `approved` / `approved_with_conditions` / `rejected` |
| 10 | `conditions` | text | Follow-ups, e.g. EU-region routing option, DPF-status monitoring |
| 11 | `next_review_due` | date | Re-verification is ongoing, not one-off |

---

## Agent workflow hints

- To PUBLISH the public list: select register records with `status` in {`active`, `announced`},
  project fields 1, 3, 5, 6, 8, 9, 15, 16, and sort by `subprocessor_name`. Announced records
  must show the objection deadline.
- To ADD a subprocessor: create a due-diligence record; if `result` != `rejected`, create the
  register record with `status: announced`, generate the notice from
  gdpr-subprocessor-change-notice.md, create the change-log record, and schedule the status flip
  for `objection_deadline + 1 day` conditional on `objections_received` being resolved.
- To VERIFY register health: every `active` record needs (a) `last_verified` within the review
  cadence, (b) a `flowdown_contract_date`, (c) `transfer_detail` populated unless
  `transfer_mechanism` = `none_eea_only`, and (d) a resolvable `notice_ref`.
- DPF caveat: records relying on the EU–US Data Privacy Framework should be flagged for
  monitoring — the General Court dismissed the Latombe challenge (2025-09-03), but the appeal is
  pending before the CJEU; SCCs + TIA remain the resilient default for US subprocessors.

## Example records (fictional — Aurora Software GmbH, Berlin B2B SaaS)

```yaml
- subprocessor_name: "Helvetia Cloud AG"
  registered_address: "Werdstrasse 2, 8004 Zürich, Switzerland"
  country_of_establishment: "CH"
  contact: "privacy@helvetiacloud.example"
  service_description: "Production hosting and storage for the Aurora platform (EU region)"
  data_categories: ["account data", "usage data", "customer content"]
  special_categories: "no"
  processing_locations: ["DE"]
  transfer_mechanism: "adequacy_decision"
  transfer_detail: "Switzerland adequacy (Decision 2000/518/EC, confirmed in the 2024 review)"
  security_guarantees: "ISO/IEC 27001:2022, SOC 2 Type II"
  engaged_by: "us"
  chain_tier: "tier1"
  flowdown_contract_date: "2024-03-11"
  status: "active"
  effective_date: "2024-04-01"
  last_verified: "2026-05-14"
  notice_ref: "SUB-2024-001"

- subprocessor_name: "Frankfurt DC Ops GmbH"
  registered_address: "Hanauer Landstraße 300, Frankfurt, Germany"
  country_of_establishment: "DE"
  contact: "security@fdcops.example"
  service_description: "Data-centre operations engaged by Helvetia Cloud AG"
  data_categories: ["customer content (encrypted at rest)"]
  special_categories: "no"
  processing_locations: ["DE"]
  transfer_mechanism: "none_eea_only"
  transfer_detail: "—"
  security_guarantees: "ISO/IEC 27001:2022, ISO 22301"
  engaged_by: "Helvetia Cloud AG"
  chain_tier: "tier2"
  flowdown_contract_date: "2024-03-11"
  status: "active"
  effective_date: "2024-04-01"
  last_verified: "2026-05-14"
  notice_ref: "SUB-2024-001"
```
