PCI DSS for Developers

PCI DSS is the payment card industry's security standard, and the most useful thing to understand about it is that the goal is to be out of scope. The requirements are extensive — twelve requirement groups, hundreds of sub-requirements, annual assessment — and they apply to any system that stores, processes, or transmits cardholder data. Every system you keep out of that path is a system you don't have to bring into compliance.

Modern payment integration is designed around this. Hosted fields (Stripe Elements, Adyen Components, Braintree Hosted Fields) render an iframe served by the payment provider, so the card number is typed into their page, transmitted to their servers, and never touches your infrastructure. You receive a token — a meaningless reference — and store that. Your scope collapses from "everything that handles a card" to "the page that includes their script."

The failure mode is a team that builds a card form on their own domain because it's easier to style, posts the number to their own server, and discovers they've pulled their entire application, database, backups, and logs into PCI scope.

TL;DR

Core Concepts

What counts as cardholder data

The CVV rule is absolute and is the one violated most often — usually accidentally, by logging a full request body or storing a payment payload for debugging. It's also the one that causes the most damage when a breach occurs, because PAN plus CVV is directly usable for fraud.

Scope reduction

Storing the last four digits and the brand is explicitly permitted and is what you display to users. The full PAN never exists in your system.

SAQ levels

Self-Assessment Questionnaires, by integration type:

The gap between A and D is enormous, and it's determined entirely by an integration decision. Choosing hosted fields at design time is worth more than any amount of subsequent security work.

A-EP is the trap: a JavaScript-based integration where the card posts directly to the provider but your page controls the form. Because your site's compromise could alter that form and skim cards — which is exactly what Magecart attacks do — you carry more requirements than SAQ A, including script integrity monitoring.

Merchant levels

Thresholds and requirements vary slightly by card brand, and a breach can move you to Level 1 regardless of volume. Your acquirer tells you your level and what they require.

The requirements that touch code

PCI DSS v4.0

Version 4.0 became the only active standard in March 2024, with a set of future-dated requirements that became mandatory on 31 March 2025. The changes engineers most need to know:

Best Practices

Use hosted fields, always

Stripe Elements, Adyen Components, Braintree Hosted Fields, or a fully hosted checkout page. This one decision determines whether you file a 20-question SAQ A or a several-hundred-question SAQ D. The styling limitations are real and are worth an order of magnitude less than the compliance cost.

Never let a PAN reach your servers

If a card number is in a request to your infrastructure, it's in your load balancer logs, your application logs, your APM traces, your error tracker, and your request replay tooling. Keeping it out of the request entirely is the only reliable control.

Store tokens and the last four

Tokens for charging, last4 and brand for display. That's everything a normal application needs. If you believe you need the full PAN, the answer is almost always a provider feature you haven't found — network tokens, saved payment methods, and account updaters all exist to avoid it.

Filter card patterns at the logging layer

Even with hosted fields, someone will eventually paste a card number into a support ticket, a form field, or a debug log. A regex filter in the logging pipeline that redacts anything matching a PAN with a valid Luhn checksum is a cheap safety net.

Never put production card data in lower environments

Test card numbers are published by every provider precisely so you don't need real ones. A staging environment containing real PANs has production PCI obligations and pre-production controls.

Segment the network if anything is in scope

If you genuinely must handle card data, isolate that environment — separate VPC or subnet, strict firewall rules, no shared credentials with the rest of the estate. Segmentation is what keeps the rest of your infrastructure out of scope, and its effectiveness must be tested.

Monitor payment page scripts

Subresource Integrity where possible, a strict Content Security Policy, an inventory of every script on the checkout page, and alerting on change. This is now an explicit v4.0 requirement and is the control that actually prevents card skimming.

Ask your provider what SAQ your integration implies

They know, and they'll tell you — often with documentation mapping each integration method to its SAQ. Confirming this before building is a five-minute conversation that occasionally saves a rewrite.

Common Mistakes

Building your own card form

Storing CVV

Logging the payment request body

Real card data in test environments

Unmonitored third-party scripts on the checkout page

Assuming a provider makes you compliant

FAQ

Do we need to be PCI compliant if we use Stripe?

Yes, at a much smaller scope. Using a provider doesn't remove your obligation — it reduces which SAQ applies. With fully hosted fields you file SAQ A, roughly twenty questions, annually. With a custom form posting to your server you're in SAQ D territory regardless of who processes the charge. The provider handles their side; you attest to yours.

Can we ever store the full card number?

Technically yes, with a documented business need, strong encryption, separated key management, and full SAQ D obligations. Practically, almost never — recurring billing, saved cards, and one-click checkout are all solved by provider tokens and network tokens. If someone proposes storing PANs, the first question is which provider feature they haven't found.

What about the CVV for recurring charges?

You never need it, and you may never store it. CVV is required only for the initial transaction; subsequent charges against a stored payment method don't use it. Any design that appears to need a stored CVV is a design that should be using the provider's recurring-payment or saved-method flow.

Is PCI DSS a law?

No — it's a contractual requirement imposed by the card brands through your acquiring bank. Non-compliance means fines levied through your acquirer, higher transaction fees, or losing the ability to accept cards. Several jurisdictions have written PCI-like requirements into law, and a breach involving card data will also trigger the applicable data protection regimes. See GDPR for Engineers.

How does PCI relate to SOC 2?

They overlap substantially in access control, logging, vulnerability management, and change management, and they differ in focus: PCI DSS is prescriptive and specific to cardholder data, SOC 2 is criteria-based and covers your controls broadly. Organizations doing both typically find PCI evidence largely satisfies the equivalent SOC 2 controls, though the prescriptiveness runs one way — SOC 2 lets you define controls, PCI tells you what they must be.

What is a Magecart attack and why does v4.0 care?

Malicious JavaScript injected into a checkout page — usually through a compromised third-party script or a supply-chain attack on a dependency — that reads card fields and exfiltrates them. It bypasses server-side controls entirely because the theft happens in the browser before the data ever reaches your provider. PCI DSS v4.0 added explicit script inventory and change-monitoring requirements (6.4.3, 11.6.1) specifically because this became the dominant card-theft vector for e-commerce.

Related Topics

References