The Single-Server Baseline
On a standalone instance, the sequence is straightforward: a database master key protects a certificate, the certificate protects a database encryption key, and the encryption key encrypts the actual data and log files.
USE master;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'A very strong password, stored in a vault';
CREATE CERTIFICATE TDE_Cert WITH SUBJECT = 'TDE Certificate for ProductionDB';
USE ProductionDB;
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDE_Cert;
ALTER DATABASE ProductionDB SET ENCRYPTION ON;
Back up the certificate immediately, before you flip encryption on, to a location entirely separate from the database backups it protects:
BACKUP CERTIFICATE TDE_Cert
TO FILE = 'D:\Secure\TDE_Cert.cer'
WITH PRIVATE KEY (
FILE = 'D:\Secure\TDE_Cert.pvk',
ENCRYPTION BY PASSWORD = 'A different very strong password'
);
On a single server that's the whole story. Restoring the database elsewhere means restoring this certificate first. If that's all you need, see the companion article on what TDE actually protects and the full key hierarchy.
Why an Availability Group Changes the Picture
A certificate lives in master on the instance where it was created, protected by that instance's Service Master Key. AlwaysOn data movement replicates database content: the log records that make up the primary's transactions. It does not replicate instance-level objects such as logins, linked servers, SQL Agent jobs, or certificates. That list has always excluded certificates, and it still does.
So when a database is encrypted, every secondary replica must independently possess a certificate with the exact same thumbprint as the one protecting the primary's database encryption key, before that replica can decrypt the incoming log stream. Nothing about creating the availability group or adding the database does this for you.
Correct Order of Operations: Rolling Out TDE on an AG
The rule is simple even though the consequence of skipping it is not obvious: the certificate must exist on every secondary before encryption is enabled on the primary (or before an already-encrypted database is added to the group).
- Create the master key and certificate on the primary, exactly as in the single-server sequence above.
- Back up the certificate from the primary.
- Restore that same certificate onto every secondary replica's
masterdatabase, before touching theALTER DATABASE ... SET ENCRYPTION ONstatement. - Only then enable encryption on the primary (or add the database to the availability group, if it's already encrypted).
- Verify encryption state on every replica, not just the primary.
-- Step 1-2: on the primary
USE master;
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'A very strong password, stored in a vault';
CREATE CERTIFICATE TDE_Cert WITH SUBJECT = 'TDE Certificate for ProductionDB';
BACKUP CERTIFICATE TDE_Cert
TO FILE = 'D:\Secure\TDE_Cert.cer'
WITH PRIVATE KEY (
FILE = 'D:\Secure\TDE_Cert.pvk',
ENCRYPTION BY PASSWORD = 'A different very strong password'
);
-- Step 3: on EVERY secondary, before step 4
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'Master key password on this replica';
CREATE CERTIFICATE TDE_Cert
FROM FILE = 'D:\Secure\TDE_Cert.cer'
WITH PRIVATE KEY (
FILE = 'D:\Secure\TDE_Cert.pvk',
DECRYPTION BY PASSWORD = 'The password used when backing up the private key'
);
-- Step 4: back on the primary, once every secondary has the certificate
USE ProductionDB;
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = AES_256
ENCRYPTION BY SERVER CERTIFICATE TDE_Cert;
ALTER DATABASE ProductionDB SET ENCRYPTION ON;
Copying a certificate to several replicas by hand is exactly the kind of repetitive, error-prone step that's worth automating. dbatools' Copy-DbaDbCertificate exports the certificate and private key from the source instance and imports it on each target in one call, which removes the chance of a typo'd password or a file that never made it to one of the secondaries:
Copy-DbaDbCertificate -Source SQL-Primary -Destination SQL-Sec1, SQL-Sec2 `
-EncryptionPassword (ConvertTo-SecureString 'temp-export-password' -AsPlainText -Force) `
-DecryptionPassword (ConvertTo-SecureString 'temp-export-password' -AsPlainText -Force)
Adding an Already-Encrypted Database to an Existing AG
The same rule applies in reverse. If you have a standalone database that already has TDE enabled and you're adding it to an existing availability group, restore its certificate onto every secondary before running the Add Database to Availability Group wizard (or Add-DbaAgDatabase). Adding the database first and fixing the certificate afterward just means a period of "Not Synchronizing" that a quick look at the error log will explain, but that's still an avoidable page-out at 2am.
Adding a New Replica Later
This is the scenario that catches people who got the initial rollout right: a new secondary replica joins the group months later, whether for capacity, a hardware refresh, or replacing a failed node. Automatic seeding will happily copy the encrypted database to the new replica, but it will not bring the certificate with it. Restore the certificate on the new replica first, exactly as in step 3 above, before it joins the group, or that replica will sit unsynchronized the moment data starts moving.
Verifying Across All Replicas
Run this on the primary and every secondary; a mismatched thumbprint or a missing row on any replica is the rollout not being finished yet, not a bug:
SELECT
DB_NAME(dek.database_id) AS database_name,
dek.encryption_state, -- 3 = encrypted, 2 = encryption in progress
dek.percent_complete,
dek.encryptor_type,
c.thumbprint,
c.name AS certificate_name
FROM sys.dm_database_encryption_keys dek
JOIN sys.certificates c ON dek.encryptor_thumbprint = c.thumbprint;
dbatools' Get-DbaDbEncryption gives the same view across a list of instances in one call, which is the more practical way to confirm parity across an entire availability group instead of connecting to each replica in turn:
Get-DbaDbEncryption -SqlInstance SQL-Primary, SQL-Sec1, SQL-Sec2 |
Select-Object SqlInstance, Database, EncryptionState, Encryptors
Certificate Backup Discipline Now Applies to the Whole Group
Everything the single-server article says about certificate backups still holds, just multiplied by the number of replicas. Losing the certificate doesn't only threaten a restore of the primary's backups; it threatens the ability of any replica that never got it to ever serve as a readable copy of that database. Keep every historical certificate for as long as backups taken under it remain in your retention policy, and store the archive with the same access-control discipline as the databases themselves, separate from where the data backups live.
Single Server vs. AlwaysOn: What Changes
| Step | Single server | AlwaysOn Availability Group |
|---|---|---|
| Create master key & certificate | Once, on the instance | Once, on the primary |
| Distribute the certificate | Not applicable | Restore on every secondary before enabling encryption |
| Enable encryption | ALTER DATABASE ... SET ENCRYPTION ON | Same command, but only after all secondaries have the certificate |
| Verify | One instance | Every replica; thumbprints must match |
| New replica joins later | Not applicable | Certificate must be restored there before it joins |
| Certificate backup archive | One secure location | Same archive, but every replica depends on it being complete |
The Bottom Line
TDE itself does not behave any differently inside an Availability Group; the encryption, the performance characteristics, and the restore requirements are identical to the single-server case. What changes is a single operational fact that's easy to miss because nothing in the tooling forces it on you: the certificate is instance-scoped, AG data movement is database-scoped, and the two never automatically meet. Restore the certificate on every secondary before enabling encryption, do the same for every replica added afterward, and verify thumbprints across the whole group rather than trusting that the primary being encrypted means the job is done.