Mistake 4: Ignoring Data Retention Requirements
Mistake 4: Ignoring Data Retention Requirements
Developers often implement features to collect and store data but forget to implement automated deletion. This leads to indefinite data retention, violating privacy principles and regulations. The mistake is compounded when backups retain data that was "deleted" from primary systems, or when derived data persists after source data deletion.
Manual deletion processes don't scale and are prone to human error. Developers might implement user-requested deletion but forget about automatic retention limits. They might delete from the application database but leave data in analytics systems, log files, or caches. Cloud services often retain "deleted" data for recovery purposes, requiring explicit purge operations.
// ❌ Bad: No retention management
async function saveUserActivity(activity) {
await db.activities.insert(activity);
// Data lives forever
}
// ✅ Good: Automated retention management
class RetentionManager {
async saveUserActivity(activity) {
const record = await db.activities.insert({
...activity,
createdAt: new Date(),
expiresAt: this.calculateExpiry(activity.type),
retentionPolicy: this.getPolicy(activity.type)
});
// Schedule deletion
await this.scheduleExpiry(record);
return record;
}
calculateExpiry(activityType) {
const policies = {
'security_log': 180, // 6 months for security
'user_content': null, // Until user deletion
'analytics': 730, // 2 years
'performance': 30, // 30 days
'debug': 7 // 1 week
};
const days = policies[activityType];
if (days === null) return null;
const expiry = new Date();
expiry.setDate(expiry.getDate() + days);
return expiry;
}
async runRetentionCleanup() {
// Primary data
const expired = await db.activities.where('expiresAt', '<=', new Date());
await this.deleteRecords(expired);
// Derived data
await this.cleanupDerivedData(expired);
// Backups
await this.scheduleBackupPurge(expired);
// Caches and logs
await this.purgeFromAuxiliarySystems(expired);
}
async deleteRecords(records) {
for (const record of records) {
// Log deletion for compliance
await this.logDeletion(record);
// Delete from primary storage
await db.activities.delete(record.id);
// Delete from full-text search
await searchIndex.delete(record.id);
// Clear from cache
await cache.delete(`activity:${record.id}`);
}
}
}
// Automated cleanup job
cron.schedule('0 2 * * *', async () => {
const manager = new RetentionManager();
await manager.runRetentionCleanup();
});
Implement retention policies from the start, not as an afterthought. Design data models with expiration in mind. Use database features like TTL indexes where available. Create comprehensive deletion procedures that handle all data locations. Test retention automation regularly, as silent failures can lead to compliance violations. Document retention policies in code and make them easily auditable.