Documentation tagged with Transparent Data Encryption (TDE) in the Geode graph database. TDE provides encryption-at-rest for database files, protecting data stored on disk from unauthorized access while remaining transparent to applications and queries.
Introduction to Transparent Data Encryption
Transparent Data Encryption (TDE) is an enterprise security feature that encrypts database files on disk, ensuring that data remains protected even if storage media is stolen, improperly disposed of, or accessed by unauthorized users. The “transparent” aspect means encryption and decryption happen automatically—applications and users don’t need to modify queries or code.
TDE addresses a critical security requirement: protecting data at rest. While network encryption (TLS) protects data in transit and authentication prevents unauthorized access, TDE ensures that raw database files, backups, and snapshots cannot be read without the encryption keys. This is essential for:
- Compliance: Regulations like GDPR, HIPAA, PCI-DSS, and SOC 2 require encryption at rest
- Data breach protection: Stolen drives or backups are useless without keys
- Multi-tenant security: Prevent cloud providers or storage administrators from accessing data
- Secure decommissioning: Safely dispose of old hardware without data recovery risks
Geode’s TDE implementation uses industry-standard AES-256 encryption with hardware acceleration (AES-NI) for minimal performance overhead, typically less than 5% impact on throughput.
Core TDE Concepts
Encryption at Rest vs. In Transit
Geode provides multiple encryption layers:
- TDE (Encryption at Rest): Protects data stored on disk
- TLS (Encryption in Transit): Protects data transmitted over networks
- FLE (Field-Level Encryption): Protects specific sensitive fields
Together, these provide defense-in-depth security.
Two-Tier Key Architecture
Geode uses a two-tier key hierarchy for security and operational flexibility:
Master Encryption Key (MEK):
- Stored in external Key Management Service (KMS) or Hardware Security Module (HSM)
- Never stored on disk with encrypted data
- Rotated infrequently (annually or when compromised)
- Examples: AWS KMS, Azure Key Vault, HashiCorp Vault, PKCS#11 HSM
Data Encryption Keys (DEK):
- Generated per database/tablespace/file
- Encrypted with MEK and stored alongside encrypted data
- Rotated periodically for defense-in-depth
- Actual key used for encrypting data blocks
This architecture enables key rotation without re-encrypting the entire database—just re-encrypt the DEKs with the new MEK.
Encryption Scope
TDE encrypts:
- Data files: Node storage, relationship storage, property storage
- Index files: All index structures (B-trees, HNSW graphs, etc.)
- WAL (Write-Ahead Log): Transaction log files
- Temporary files: Sort buffers, intermediate query results
- Backups: Backup archives and snapshots
TDE does NOT encrypt:
- Configuration files: Database configuration (not sensitive data)
- Logs: Application logs (use separate log encryption if needed)
- In-memory data: Data in RAM (use encrypted memory for extreme security)
- Query text: GQL queries themselves (use TLS for query privacy)
Encryption Algorithms
Geode supports industry-standard algorithms:
- AES-256-GCM: Recommended default (authenticated encryption, parallelizable)
- AES-256-CBC: Alternative for compatibility (requires separate HMAC for authentication)
- ChaCha20-Poly1305: Software-friendly alternative for systems without AES-NI
All algorithms use 256-bit keys meeting FIPS 140-2 requirements.
How TDE Works in Geode
Enabling TDE
Enable TDE when creating a new database:
# Generate or retrieve master encryption key from KMS
# There is no `geode init`. The server creates its data directory on
# first start; TDE and FLE are always available.
geode serve --data-dir ./data
--kms-provider aws-kms \
--kms-key-id arn:aws:kms:us-east-1:123456789:key/abc-def-123 \
--encryption-algorithm aes-256-gcm
For existing databases, enable TDE through encryption conversion:
# Enable TDE on existing database (requires downtime)
# There is no `geode convert-to-tde`: encryption at rest is always
# available and needs no conversion step.
--data-dir /var/lib/geode/data \
--kms-provider vault \
--kms-endpoint https://vault.example.com \
--kms-token $VAULT_TOKEN
Configuration
Configure TDE in geode.yaml:
# NOTE: `security:` is not a configuration-file section — it is ignored.
# KMS and encryption-at-rest are configured with environment variables:
# GEODE_KMS_URL, GEODE_KMS_ENDPOINT, GEODE_KMS_API_KEY
# GEODE_MASTER_KEY, GEODE_TDE_ENABLED, GEODE_ALLOW_LOCAL_KMS
# Key Management Service configuration
kms:
provider: aws-kms # aws-kms, azure-kv, gcp-kms, vault, pkcs11
key_id: arn:aws:kms:us-east-1:123456789:key/abc-def-123
region: us-east-1
# DEK rotation policy
dek_rotation:
enabled: true
interval_days: 90
# Performance tuning
cache_deks: true # Cache decrypted DEKs in memory
cache_size_mb: 128 # DEK cache size
Key Management Integration
Geode integrates with enterprise key management systems:
AWS KMS:
kms:
provider: aws-kms
key_id: arn:aws:kms:us-east-1:123456789:key/abc-def-123
region: us-east-1
credentials_profile: geode-production
Azure Key Vault:
kms:
provider: azure-kv
vault_url: https://my-keyvault.vault.azure.net
key_name: geode-master-key
tenant_id: 12345-abcd-...
client_id: 67890-efgh-...
HashiCorp Vault:
kms:
provider: vault
endpoint: https://vault.example.com
transit_mount: transit
key_name: geode-mek
token: $VAULT_TOKEN # Or use AppRole, K8s auth
PKCS#11 HSM:
kms:
provider: pkcs11
library_path: /usr/lib/softhsm/libsofthsm2.so
slot_id: 0
pin: $HSM_PIN
key_label: geode-master-key
Runtime Operations
TDE operates transparently:
-- Queries work exactly the same with TDE enabled
MATCH (p:Person {id: $userId})
SET p.last_login = datetime();
-- Application code doesn't change
INSERT (:Document {
id: 'doc-123',
title: 'Sensitive Data',
content: 'This will be encrypted on disk automatically'
});
Encryption and decryption happen automatically in the storage layer.
Use Cases
Regulatory Compliance
Meet encryption requirements for regulated industries:
# HIPAA-compliant TDE configuration
# NOTE: `security:` is not a configuration-file section — it is ignored.
# KMS and encryption-at-rest are configured with environment variables:
# GEODE_KMS_URL, GEODE_KMS_ENDPOINT, GEODE_KMS_API_KEY
# GEODE_MASTER_KEY, GEODE_TDE_ENABLED, GEODE_ALLOW_LOCAL_KMS
kms:
provider: aws-kms
key_id: $HIPAA_COMPLIANT_KMS_KEY
audit:
log_key_access: true
log_encryption_events: true
Multi-Tenant SaaS
Isolate tenant data with per-tenant encryption:
# NOTE: `security:` is not a configuration-file section — it is ignored.
# KMS and encryption-at-rest are configured with environment variables:
# GEODE_KMS_URL, GEODE_KMS_ENDPOINT, GEODE_KMS_API_KEY
# GEODE_MASTER_KEY, GEODE_TDE_ENABLED, GEODE_ALLOW_LOCAL_KMS
kms:
provider: vault
endpoint: https://vault.example.com
Query with tenant context:
-- Tenant ID determines which DEK to use for decryption
SET SESSION tenant_id = 'tenant-abc-123';
MATCH (d:Document) RETURN d.content;
Secure Cloud Deployments
Protect data from cloud provider access:
# Deploy to cloud with customer-managed keys
$ geode deploy \
--cloud aws \
--kms-provider aws-kms \
--customer-managed-key arn:aws:kms:us-east-1:MY_ACCOUNT:key/MY_KEY
Even cloud administrators cannot decrypt your data without your KMS key.
Data Lifecycle Management
Securely retire old data:
# Crypto-shredding: Destroy encryption key to make data unrecoverable
$ geode retire-data \
--tablespace archived_2023 \
--method crypto-shred # Delete DEK, data becomes permanently unreadable
Faster and more secure than deleting millions of records.
Best Practices
Key Management
Use external KMS: Never store MEK with encrypted data
# Good: MEK in AWS KMS kms: provider: aws-kms key_id: arn:aws:kms:... # Bad: MEK in config file # NEVER DO THIS encryption: master_key: "base64-encoded-key-here" # Insecure!Rotate MEK annually: Regular rotation limits exposure
$ geode rotate-mek \ --old-key-id arn:aws:kms:.../old-key \ --new-key-id arn:aws:kms:.../new-keyRotate DEKs quarterly: Defense-in-depth
dek_rotation: enabled: true interval_days: 90Backup keys separately: Store key backups in different location than data backups
Performance Optimization
Enable hardware acceleration: Use AES-NI when available
# Verify AES-NI support $ grep -o aes /proc/cpuinfo | wc -l # If > 0, AES-NI is availableCache DEKs: Reduce KMS roundtrips
encryption: cache_deks: true cache_size_mb: 256 # Larger cache for more tablespacesUse AES-GCM: Faster than AES-CBC (parallel encryption)
encryption: algorithm: aes-256-gcm # RecommendedBenchmark impact: Measure before deploying
$ geode benchmark --with-tde --without-tde # Expect < 5% overhead with AES-NI
Operational Security
Principle of least privilege: Limit KMS key access
{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": {"AWS": "arn:aws:iam::123:role/geode-prod"}, "Action": ["kms:Decrypt", "kms:DescribeKey"], "Resource": "*" }] }Enable audit logging: Track all key usage
audit: log_key_access: true log_to: /var/log/geode/tde-audit.logTest disaster recovery: Practice key recovery procedures
# Test MEK recovery from backup $ geode recover-mek \ --backup-location s3://backup-bucket/mek-backup.enc \ --recovery-key $RECOVERY_PASSPHRASE
Performance Characteristics
Throughput Impact
Typical overhead with AES-NI:
- Read throughput: 2-5% slower
- Write throughput: 3-7% slower
- CPU usage: +10-15%
- Memory usage: Minimal (DEK cache: 128-256 MB)
Without AES-NI (software AES):
- Read throughput: 15-25% slower
- Write throughput: 20-30% slower
- CPU usage: +50-100%
Latency Impact
Typical latency overhead:
- Query latency: +0.5-2ms per query
- Write latency: +1-3ms per transaction
- Startup time: +5-30 seconds (DEK loading)
Monitoring and Troubleshooting
Monitoring
Track TDE health:
-- Check encryption status
CALL tde.get_encryption_status()
YIELD enabled, encrypted_tables, encryption_algorithm
RETURN enabled, encrypted_tables, encryption_algorithm;
-- Where key rotation stands
CALL tde.get_rotation_state()
YIELD current_generation, last_rotation_time, rotation_in_progress, scheduled_rotation
RETURN current_generation, last_rotation_time, rotation_in_progress, scheduled_rotation;
-- Encryption overhead against an unencrypted baseline
CALL tde.measure_overhead()
YIELD baseline_ops_per_sec, encrypted_ops_per_sec, overhead_percentage, passes_threshold
RETURN baseline_ops_per_sec, encrypted_ops_per_sec, overhead_percentage, passes_threshold;
Key-access events go to the audit trail rather than a dedicated encryption-audit
procedure — there is no dbms.security.encryption.* or dbms.monitor.*
namespace:
CALL audit.get_recent_events(100)
YIELD event_id, timestamp, category, action, outcome
RETURN timestamp, category, action, outcome
ORDER BY timestamp DESC;
Common Issues
KMS unavailable:
- Symptom: Cannot start database, “Failed to retrieve MEK”
- Cause: KMS service unreachable
- Solution: Verify network connectivity, check KMS service status, use cached DEKs (if enabled)
Performance degradation:
- Symptom: Slow queries after enabling TDE
- Cause: Missing AES-NI support or software encryption
- Solution: Verify AES-NI availability, consider hardware upgrade
Key rotation failures:
- Symptom: DEK rotation fails
- Cause: Insufficient KMS permissions
- Solution: Grant required KMS permissions (GenerateDataKey, Decrypt)
TDE Implementation Patterns
Multi-Tenant Key Isolation
Isolate tenant data with separate encryption keys:
# geode.yaml
# NOTE: `security:` is not a configuration-file section — it is ignored.
# KMS and encryption-at-rest are configured with environment variables:
# GEODE_KMS_URL, GEODE_KMS_ENDPOINT, GEODE_KMS_API_KEY
# GEODE_MASTER_KEY, GEODE_TDE_ENABLED, GEODE_ALLOW_LOCAL_KMS
Query with tenant context:
-- Set tenant context for session
SET SESSION tenant_id = 'tenant-123';
-- Geode automatically uses tenant-123's DEK for decryption
MATCH (d:Document) WHERE d.category = 'financial'
RETURN d.title, d.content;
Each tenant’s data is encrypted with their unique key, preventing cross-tenant data access even if database is compromised.
Tablespace-Level Encryption
Encrypt different tablespaces with different keys:
-- Create encrypted tablespace for sensitive data
CREATE TABLESPACE sensitive_data
LOCATION '/var/lib/geode/tablespaces/sensitive'
WITH (encryption = 'aes-256-gcm', kms_key_id = 'high-security-key');
-- Create encrypted tablespace for regular data
CREATE TABLESPACE regular_data
LOCATION '/var/lib/geode/tablespaces/regular'
WITH (encryption = 'aes-256-gcm', kms_key_id = 'standard-security-key');
-- Assign graphs to tablespaces
CREATE GRAPH financial_data TABLESPACE sensitive_data;
CREATE GRAPH analytics_data TABLESPACE regular_data;
Benefits: Different security levels, independent key rotation, compliance segmentation.
Key Rotation Without Downtime
Rotate encryption keys while database remains online:
Rotation is driven by the tde.* procedures, not a geode query "SHOW CLUSTER STATUS" (there is noadmin` subcommand):
-- Rotate now
CALL tde.rotate_keys()
YIELD success, keys_rotated, new_master_key_id
RETURN success, keys_rotated, new_master_key_id;
-- Or install a schedule
CALL tde.configure_rotation('scheduled', 8760)
YIELD status, next_rotation_time
RETURN status, next_rotation_time;
-- Watch progress
CALL tde.get_rotation_state()
YIELD current_generation, last_rotation_time, rotation_in_progress, scheduled_rotation
RETURN current_generation, last_rotation_time, rotation_in_progress, scheduled_rotation;
Online rotation process:
- New DEKs created with new MEK
- Background process re-encrypts old DEKs with new MEK
- Newly written data uses new DEKs
- Old data gradually re-encrypted during maintenance windows
- Rollback possible until 100% complete
Hardware Security Module (HSM) Integration
Use hardware-backed key storage for maximum security:
# geode.yaml with PKCS#11 HSM
# NOTE: `security:` is not a configuration-file section — it is ignored.
# KMS and encryption-at-rest are configured with environment variables:
# GEODE_KMS_URL, GEODE_KMS_ENDPOINT, GEODE_KMS_API_KEY
# GEODE_MASTER_KEY, GEODE_TDE_ENABLED, GEODE_ALLOW_LOCAL_KMS
kms:
provider: pkcs11
library_path: /usr/lib/softhsm/libsofthsm2.so
slot_id: 0
pin_file: /secure/hsm_pin
key_label: geode-master-encryption-key
# HSM-specific settings
use_hsm_crypto: true # Use HSM for encrypt/decrypt operations
cache_deks_in_hsm: true # Store DEKs in HSM memory
Initialize HSM key:
# Initialize HSM slot
softhsm2-util --init-token --slot 0 --label "geode-hsm"
# Generate master key in HSM
pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so \
--login --keypairgen --key-type AES:32 \
--label geode-master-encryption-key
Encryption Performance Optimization
Optimize TDE for your hardware:
# geode.yaml performance tuning
# NOTE: `security:` is not a configuration-file section — it is ignored.
# KMS and encryption-at-rest are configured with environment variables:
# GEODE_KMS_URL, GEODE_KMS_ENDPOINT, GEODE_KMS_API_KEY
# GEODE_MASTER_KEY, GEODE_TDE_ENABLED, GEODE_ALLOW_LOCAL_KMS
# Performance optimizations
use_aes_ni: true # Use hardware AES acceleration
cache_deks: true
dek_cache_size_mb: 512 # Large cache for many tablespaces
dek_cache_ttl_seconds: 3600
# Parallelization
encrypt_threads: 8 # Parallel encryption for writes
decrypt_threads: 16 # Parallel decryption for reads
# Batching
encryption_batch_size: 128 # Pages to encrypt in batch
Benchmark configuration:
# Test read performance with TDE
geode benchmark read \
--queries=1000000 \
--threads=32 \
--with-tde \
--output=tde-read-results.json
# Test write performance
geode benchmark write \
--inserts=1000000 \
--threads=32 \
--with-tde \
--output=tde-write-results.json
# Compare with non-encrypted baseline
geode benchmark read --queries=1000000 --threads=32 --without-tde
Typical results with AES-NI:
- Read overhead: 2-4%
- Write overhead: 4-8%
- CPU increase: 10-15%
Compliance Audit Trail
Generate TDE compliance reports:
-- Confirm encryption is on and which algorithm is in use
CALL tde.get_encryption_status()
YIELD enabled, encrypted_tables, encryption_algorithm
RETURN enabled, encrypted_tables, encryption_algorithm;
-- Prove no page still holds plaintext
CALL tde.verify_no_plaintext()
YIELD verified, pages_scanned, violations
RETURN verified, pages_scanned, violations;
-- Prove no key material is stored in the clear
CALL tde.audit_plaintext_keys()
YIELD plaintext_keys_found, encrypted_keys_count, security_violation
RETURN plaintext_keys_found, encrypted_keys_count, security_violation;
-- Write a signed manifest of the key hierarchy for the auditor
CALL tde.generate_key_manifest()
YIELD success, manifest_path, keys_included
RETURN success, manifest_path, keys_included;
-- Key access events come from the audit trail
CALL audit.get_recent_events(500)
YIELD event_id, timestamp, category, action, outcome
RETURN timestamp, category, action, outcome
ORDER BY timestamp DESC;
There is no per-tablespace encryption report and no key listing procedure: Geode encrypts the whole store rather than individual tablespaces, and key material is never enumerated to clients.
Export for compliance reporting:
def generate_tde_compliance_report():
"""Generate quarterly TDE compliance report"""
report = {
'period': f"Q{datetime.now().quarter} {datetime.now().year}",
'encryption_status': {},
'key_management': {},
'access_audit': {}
}
# Verify encryption is enabled and no plaintext remains
result = db.execute("""
CALL tde.verify_no_plaintext()
YIELD verified, pages_scanned, violations
RETURN verified, pages_scanned, violations
""")
row = result.rows[0]
report['encryption_status'] = {
'verified': row['verified'],
'pages_scanned': row['pages_scanned'],
'violations': row['violations'],
}
# Verify key rotation compliance
result = db.execute("""
CALL tde.get_rotation_state()
YIELD current_generation, last_rotation_time, rotation_in_progress
RETURN current_generation, last_rotation_time, rotation_in_progress
""")
row = result.rows[0]
last_rotation = datetime.fromisoformat(row['last_rotation_time'])
days_since_rotation = (datetime.now() - last_rotation).days
report['key_management'] = {
'generation': row['current_generation'],
'age_days': days_since_rotation,
'compliant': days_since_rotation < 365, # Annual rotation required
}
return report
Crypto-Shredding for Data Deletion
Implement cryptographic erasure for secure data deletion:
Crypto-shredding in Geode is whole-store, not per-tablespace: there is no
dbms.security.cryptoShred procedure and no per-tablespace DEK to destroy. The
key-destruction surface is the TDE key hierarchy itself:
-- Wipe live key material from memory
CALL tde.zeroize_keys()
YIELD success, keys_cleared, memory_wiped
RETURN success, keys_cleared, memory_wiped;
-- Tear down the derived key hierarchy
CALL tde.cleanup_key_hierarchy()
YIELD keys_zeroized, hierarchy_cleared
RETURN keys_zeroized, hierarchy_cleared;
For per-record erasure (“right to be forgotten”) use
field-level encryption
, where each
field is encrypted under a key you can retire independently, or delete the
records outright with DETACH DELETE. Destroying the TDE master key renders
the entire store unrecoverable, which is a disposal operation, not a
selective one.
TDE Disaster Recovery
Backup encryption keys securely:
-- Write a key manifest alongside the backup (references, not key material)
CALL tde.generate_key_manifest()
YIELD success, manifest_path, keys_included
RETURN success, manifest_path, keys_included;
The manifest records key identifiers and hierarchy metadata. The key material itself stays in the KMS: disaster recovery restores access to the keys, not the keys themselves.
Recover a TDE-encrypted database:
# Step 1: Start the server with TDE enabled
geode serve --data-dir /var/lib/geode --tde-provider aws-kms
# Step 2: Restore the backup into it
geode restore /backups/geode-full-20260124.backup --yes
-- Step 3: Point the server at the KMS and confirm it can wrap/unwrap
CALL tde.configure_external_kms('https://kms.us-east-1.amazonaws.com', 'us-east-1')
YIELD status, endpoint, connection_verified
RETURN status, endpoint, connection_verified;
CALL tde.test_kms_wrap_unwrap()
YIELD wrap_success, unwrap_success, roundtrip_verified, latency_ms
RETURN wrap_success, unwrap_success, roundtrip_verified, latency_ms;
-- Step 4: Confirm the restored store decrypts
CALL tde.get_encryption_status()
YIELD enabled, encrypted_tables, encryption_algorithm
RETURN enabled, encrypted_tables, encryption_algorithm;
TDE Monitoring and Alerting
Set up monitoring for encryption health:
The server exposes no geode_tde_* Prometheus metrics — the registered set is
the ten process-level metrics documented in the
statistics reference
. Monitor TDE by polling the
procedures on a schedule and alerting on their output:
#!/bin/bash
# /usr/local/bin/geode-tde-check.sh — run from cron, alert on non-zero exit
set -euo pipefail
geode query "CALL tde.get_encryption_status() YIELD enabled RETURN enabled" \
| grep -q true || { echo "TDE not enabled"; exit 1; }
geode query "CALL tde.test_kms_wrap_unwrap() YIELD roundtrip_verified RETURN roundtrip_verified" \
| grep -q true || { echo "KMS wrap/unwrap failed"; exit 1; }
geode query "CALL tde.audit_plaintext_keys() YIELD security_violation RETURN security_violation" \
| grep -q false || { echo "Plaintext key material detected"; exit 1; }
Rotation age comes from tde.get_rotation_state()’s last_rotation_time;
compare it against your policy window in the same script.
Related Topics
- Field-Level Encryption (FLE) : Encrypt specific sensitive fields
- Security : Overall security features
- Encryption : Encryption capabilities
- Compliance : Regulatory compliance
- Authentication : Access control
- Audit Logging : Security audit trails
- Backup : Encrypted backup strategies
Further Reading
- Security Guide : Complete security documentation
- KMS Integration : Key management service integration
- Performance Tuning : TDE performance optimization
- Disaster Recovery : TDE-encrypted backup recovery
Geode’s Transparent Data Encryption provides enterprise-grade protection for data at rest with minimal performance overhead and zero application changes—essential for regulated industries and security-conscious deployments.