Sub-processor list template · checked

Sub-processor list template, column by column

A GDPR sub-processor list has one row per vendor that processes personal data on your behalf: who it is, what it does for you, which personal data it receives, where it processes it and on what transfer terms, and the agreement that binds it, with the date the list last changed. Copy the table below, or draft its rows from your code.

The columns, and why each is there

Sub-processorThe vendor's legal name, as your contract with it names the entity. Customers must be able to tell who it is; EDPB Opinion 22/2024 expects you to know every processor in the chain.
PurposeWhat it does for you: hosting, payments, email delivery, LLM inference.
Personal dataThe categories it receives: names and emails, billing details, prompts, IP addresses. Not the fields, the kinds.
LocationWhere it processes the data: a region you chose in its settings, or where it says it processes. It decides the transfer column.
Transfer mechanismOnly for processing outside the EEA: the Standard Contractual Clauses, or the EU-US Data Privacy Framework if the vendor is certified. Its DPA says which.
DPAA link to the data processing agreement that binds it to the same obligations as you.
Its own sub-processorsA link to the vendor's list: the next link in the chain, for a customer who wants to trace it.
SinceThe day it was added. With the list's own last-changed date, this is the record a notice is checked against.

Copy it

Markdown, with the first rows of the example below filled in. Replace each vendor name with the entity your contract names, and every YYYY-MM-DD.

## Sub-processors

Last changed: YYYY-MM-DD. We give customers N days' notice of a new sub-processor; subscribe at <link>.

| Sub-processor | Purpose | Personal data | Location | Transfer mechanism | DPA | Since |
| --- | --- | --- | --- | --- | --- | --- |
| Vercel (legal entity) | Hosting and serverless functions; Web analytics (Vercel Analytics) | Everything your app serves and handles while it runs there, including request logs with IP addresses | fra1 (Frankfurt) | if outside the EEA | [DPA](https://vercel.com/legal/dpa) | YYYY-MM-DD |
| Amazon Web Services (legal entity) | Cloud infrastructure; File storage (S3) | Depends on the services you use: anything you store or process there | eu-central-1 | if outside the EEA | [DPA](https://d1.awsstatic.com/legal/aws-dpa/aws-dpa.pdf) | YYYY-MM-DD |
| Neon (legal entity) | Serverless Postgres database | All personal data your app stores | region | if outside the EEA | [DPA](https://neon.com/dpa) | YYYY-MM-DD |
| … | | | | | | |

Rows drafted from code

The first rows of a list drafted from a small app's code (synthetic, written for the demo); the full example shows every row and where each came from.

Sub-processorPurposePersonal dataLocationDPA
VercelHosting and serverless functions; Web analytics (Vercel Analytics)Everything your app serves and handles while it runs there, including request logs with IP addressesfra1 (Frankfurt)DPA
Amazon Web ServicesCloud infrastructure; File storage (S3)Depends on the services you use: anything you store or process thereeu-central-1DPA
NeonServerless Postgres databaseAll personal data your app storesto confirmDPA
StripePayments and billingCustomers' names, email and billing addresses; card details, which the vendor holdsto confirmDPA

Draft yours

$ grep -rnE --include=package.json --exclude-dir=node_modules '"(@ai-sdk/amazon-bedrock|@ai-sdk/anthropic|@ai-sdk/azure|@ai-sdk/cohere|@ai-sdk/gateway|@ai-sdk/google|@ai-sdk/google-vertex|@ai-sdk/groq|@ai-sdk/mistral|@ai-sdk/openai|@ai-sdk/togetherai|@ai-sdk/xai|@algolia/[^"]*|@amplitude/[^"]*|@anthropic-ai/bedrock-sdk|@anthropic-ai/claude-agent-sdk|@anthropic-ai/sdk|@anthropic-ai/vertex-sdk|@auth0/[^"]*|@aws-sdk/[^"]*|@aws-sdk/client-bedrock-runtime|@aws-sdk/client-dynamodb|@aws-sdk/client-s3|@aws-sdk/client-ses|@aws-sdk/client-sesv2|@aws-sdk/client-sqs|@aws-sdk/lib-dynamodb|@aws-sdk/lib-storage|@axiomhq/[^"]*|@azure/[^"]*|@azure/openai|@azure/storage-blob|@clerk/[^"]*|@cloudflare/next-on-pages|@cloudinary/[^"]*|@datadog/[^"]*|@deepgram/sdk|@discordjs/[^"]*|@elevenlabs/[^"]*|@google-cloud/[^"]*|@google-cloud/bigquery|@google-cloud/storage|@google-cloud/vertexai|@google/genai|@google/generative-ai|@helicone/[^"]*|@huggingface/inference|@intercom/[^"]*|@langfuse/[^"]*|@lemonsqueezy/[^"]*|@libsql/client|@liveblocks/[^"]*|@logtail/[^"]*|@mistralai/mistralai|@mux/[^"]*|@neondatabase/[^"]*|@netlify/[^"]*|@openai/agents|@opennextjs/cloudflare|@openrouter/ai-sdk-provider|@openrouter/sdk|@paddle/[^"]*|@pinecone-database/[^"]*|@planetscale/database|@plausible-analytics/tracker|@posthog/[^"]*|@prisma/adapter-neon|@segment/[^"]*|@sendgrid/[^"]*|@sentry/[^"]*|@slack/[^"]*|@stripe/[^"]*|@supabase/[^"]*|@trigger\.dev/[^"]*|@tursodatabase/[^"]*|@uploadthing/[^"]*|@upstash/[^"]*|@vercel/analytics|@vercel/blob|@vercel/edge-config|@vercel/functions|@vercel/kv|@vercel/og|@vercel/postgres|@vercel/speed-insights|@workos-inc/[^"]*|ably|algoliasearch|analytics-node|apify|apify-cli|apify-client|auth0|aws-cdk-lib|aws-sdk|cloudflare|cloudinary|cohere-ai|crisp-api|crisp-sdk-web|dd-trace|discord\.js|elevenlabs|firebase|firebase-admin|firebase-tools|ga-4-react|groq-sdk|inngest|intercom-client|langfuse|langfuse-langchain|langfuse-vercel|loops|mailgun-js|mailgun\.js|mixpanel|mixpanel-browser|mongodb|mongoose|netlify-cli|next-axiom|next-cloudinary|next-plausible|openai|plausible-tracker|posthog-js|posthog-node|postmark|pusher|pusher-js|raven-js|react-ga4|react-instantsearch|react-use-intercom|replicate|resend|stripe|supabase|together-ai|twilio|uploadthing|vercel|wrangler)"[[:space:]]*:' .

Run it from the repository root; it needs nothing installed and sends nothing anywhere. It finds every dependency, in every package.json, that names one of the 69 vendors in the table below. It cannot see a vendor your code calls without an SDK (an API host in a string, a webhook URL), or one named only by an env variable; check those by hand.

Not legal advice. Whether a vendor is your sub-processor depends on the personal data you send it and on your contracts; a list drafted from code is a draft for you to confirm, row by row. It also misses vendors outside the code (your workspace, support desk, CRM, payroll): add those by hand.

A hosted, dated sub-processor page that emails your customers each change is not built.

It would publish the list you approved at a public URL, keep every change with its date, email your subscribers the notice with the day their objection window closes, and record who was told when. agentcheck runs scheduled checks of endpoints today; this is not one of them. If you would pay for it, say so with one click. The click is counted; nothing else is sent or stored.

Sources

subprocessors is a free tool from agentcheck, which runs scheduled checks of your endpoints and alerts you when an answer changes. Vendor links come from each vendor's own pages, read on the day shown.