Skip to content

We need to define the SyntheticID (Server Side Cookie) Schema #308

@jevansnyc

Description

@jevansnyc

We haven't taken a stab in writing at this yet but with the SynthID work going on I took a stab at requirements. We'll get feedback from stakeholders such as publishers, SSPs, DSPs, Rowena, Tony, Hill, Shailley and some others on this first, but here's a start. Note the usage of the "Metadata" Fastly feature which is actually quite cool and useful here:

`Metadata is arguably the most underutilized feature of Fastly's KV Store. You can attach up to 2048 bytes of UTF-8 string data to any entry—no schema required. This could be JSON, timestamps, flags, or even assembly code (if that's your thing).

Why is this powerful? Because metadata is accessible without streaming the body. You can make decisions based on metadata alone, saving bandwidth and processing time.`

MD file below:

SyntheticID KV Store Schema

Overview

This schema defines the structure for storing user identity and behavioral data in Fastly KV Store, using the SyntheticID as the key.

Storage Architecture

  • Key: SyntheticID (format: {64-hex-hmac}.{6-alphanumeric-suffix})
  • Value: JSON payload (up to 25MB, see schema below)
  • Metadata: Fast-access fields (up to 2048 bytes, see metadata schema)

Metadata Schema (2048 bytes max)

Optimized for fast access without streaming the full value:

{
  "schema_version": "1.0",
  "last_updated": "2026-02-15T10:30:00Z",
  "consent_status": "granted",
  "jurisdiction": "EU",
  "sync_status": "active",
  "ttl_days": 90
}

Metadata Fields

Field Type Description
schema_version string Schema version for backward compatibility
last_updated ISO 8601 Last modification timestamp
consent_status enum One of: granted, denied, pending, expired
jurisdiction string Geographic region (e.g., EU, US-CA, US-NY)
sync_status enum One of: active, stale, error, disabled
ttl_days number Days until expiration

Value Schema (JSON Payload)

{
  "version": "1.0",
  "created_at": "2026-01-15T08:22:00Z",
  "updated_at": "2026-02-15T10:30:00Z",

  "identifiers": {
    "synthetic_id": "a1b2c3...xyz.Ab12c3",
    "universal_ids": {
      "uid2": {
        "token": "AgAAAAVW...",
        "expires_at": "2026-02-20T10:30:00Z",
        "status": "active"
      },
      "id5": {
        "id": "ID5*xxx...",
        "link_type": "deterministic",
        "expires_at": "2026-03-15T10:30:00Z"
      },
      "liveramp": {
        "ats": "ramp:xxx...",
        "envelope": "envelope-v3:xxx..."
      },
      "criteo": {
        "onetag_id": "criteo-xxx..."
      },
      "sharedid": {
        "id": "shared-xxx...",
        "third_party_cookie": "xxx..."
      }
    },
    "first_party": {
      "email_sha256": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
      "phone_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
      "crm_id": "CRM-12345",
      "loyalty_id": "LOYAL-67890",
      "authenticated_user_id": "user-abc-123"
    },
    "cross_device": {
      "device_graph_id": "device-cluster-xxx",
      "linked_devices": ["device-1", "device-2"],
      "confidence_score": 0.92
    }
  },

  "partner_identifiers": {
    "dsp_buyers": {
      "thetradedesk": {
        "buyer_id": "TTD-buyer-xxx",
        "cookie_value": "xxx...",
        "last_synced": "2026-02-15T09:00:00Z"
      },
      "google_dv360": {
        "buyer_id": "DV360-xxx",
        "cookie_value": "xxx...",
        "last_synced": "2026-02-15T09:00:00Z"
      },
      "amazon_advertising": {
        "buyer_id": "amzn-xxx",
        "cookie_value": "xxx...",
        "last_synced": "2026-02-15T09:00:00Z"
      }
    },
    "ssp_identifiers": {
      "pubmatic": {
        "user_id": "PM-xxx",
        "cookie_value": "xxx...",
        "last_synced": "2026-02-15T09:00:00Z"
      },
      "magnite": {
        "user_id": "MAG-xxx",
        "cookie_value": "xxx...",
        "last_synced": "2026-02-15T09:00:00Z"
      },
      "openx": {
        "user_id": "OX-xxx",
        "cookie_value": "xxx...",
        "last_synced": "2026-02-15T09:00:00Z"
      }
    },
    "data_partners": {
      "permutive": {
        "user_id": "perm-xxx",
        "segment_ids": ["seg-123", "seg-456", "seg-789"],
        "last_synced": "2026-02-15T09:00:00Z"
      },
      "liveramp": {
        "abilitec_id": "lr-xxx",
        "last_synced": "2026-02-15T09:00:00Z"
      },
      "lotame": {
        "panorama_id": "lotame-xxx",
        "last_synced": "2026-02-15T09:00:00Z"
      }
    }
  },

  "consent": {
    "tcf": {
      "version": "2.2",
      "consent_string": "CPXxRfAPXxRfAAfKABENATEIAACAAAAAAAAAAAAAAAAA.YAAAAAAAAAA",
      "purpose_consents": {
        "1": true,
        "2": true,
        "3": false,
        "4": true,
        "5": false,
        "6": true,
        "7": true,
        "8": true,
        "9": false,
        "10": true
      },
      "vendor_consents": {
        "755": true,
        "10": true
      },
      "timestamp": "2026-02-15T10:30:00Z",
      "cmp_id": 123,
      "cmp_version": 1
    },
    "gpp": {
      "string": "DBABMA~CPXxRfAPXxRfAAfKABENATEIAACAAAAAAAAAAAAAAAAA.YAAAAAAAAAA",
      "sections": ["tcfeuv2", "uspv1"],
      "timestamp": "2026-02-15T10:30:00Z"
    },
    "ccpa": {
      "us_privacy_string": "1YNN",
      "opt_out": false,
      "timestamp": "2026-02-15T10:30:00Z"
    },
    "custom": {
      "analytics_consent": true,
      "personalization_consent": true,
      "advertising_consent": true,
      "timestamp": "2026-02-15T10:30:00Z"
    },
    "coppa": {
      "is_child": false,
      "age_gate_passed": true,
      "age": null
    }
  },

  "segments": {
    "behavioral": {
      "categories": [
        {
          "id": "IAB1",
          "name": "Arts & Entertainment",
          "confidence": 0.85,
          "last_observed": "2026-02-15T10:30:00Z"
        },
        {
          "id": "IAB3",
          "name": "Business",
          "confidence": 0.72,
          "last_observed": "2026-02-14T15:20:00Z"
        }
      ],
      "intent_signals": {
        "purchase_intent": {
          "category": "automotive",
          "score": 0.78,
          "recency_days": 3
        },
        "research_intent": {
          "category": "travel",
          "score": 0.65,
          "recency_days": 1
        }
      }
    },
    "contextual": {
      "recent_content": [
        {
          "url_path": "/tech/ai-news",
          "categories": ["technology", "ai"],
          "timestamp": "2026-02-15T10:25:00Z"
        },
        {
          "url_path": "/sports/football",
          "categories": ["sports", "football"],
          "timestamp": "2026-02-15T09:15:00Z"
        }
      ]
    },
    "private": {
      "permutive_segments": [
        "seg-high-value-user",
        "seg-frequent-visitor",
        "seg-newsletter-subscriber"
      ],
      "custom_segments": [
        "vip-member",
        "early-adopter"
      ]
    },
    "lookalike": {
      "models": [
        {
          "model_id": "lal-premium-buyers",
          "score": 0.88,
          "updated_at": "2026-02-15T00:00:00Z"
        }
      ]
    }
  },

  "attributes": {
    "keywords": [
      "tech-enthusiast",
      "sports-fan",
      "early-adopter",
      "newsletter-subscriber"
    ],
    "lifecycle": {
      "stage": "engaged",
      "first_seen": "2025-11-20T14:30:00Z",
      "last_seen": "2026-02-15T10:30:00Z",
      "session_count": 47,
      "page_view_count": 283,
      "days_active": 87,
      "avg_session_duration_seconds": 420
    },
    "engagement": {
      "recency_days": 0,
      "frequency_30d": 18,
      "monetary_value": null,
      "engagement_score": 0.82,
      "content_affinity": {
        "technology": 0.75,
        "sports": 0.60,
        "business": 0.45
      }
    },
    "propensity": {
      "subscription_likelihood": 0.68,
      "churn_risk": 0.15,
      "conversion_likelihood": 0.54
    }
  },

  "technical": {
    "fingerprint": {
      "user_agent_hash": "sha256:xxx...",
      "ip_geolocation": {
        "country": "US",
        "region": "CA",
        "city": "San Francisco",
        "dma": 807,
        "postal_code": "94105"
      },
      "platform": {
        "device_type": "desktop",
        "os": "macOS",
        "os_version": "14.2",
        "browser": "Chrome",
        "browser_version": "120.0"
      }
    },
    "environment": {
      "app_version": null,
      "sdk_version": null,
      "is_mobile_app": false,
      "is_web": true
    }
  },

  "quality": {
    "data_completeness_score": 0.87,
    "last_validated": "2026-02-15T10:30:00Z",
    "error_flags": [],
    "data_sources": [
      "first_party_direct",
      "uid2_sync",
      "permutive_enrichment"
    ],
    "confidence_level": "high"
  },

  "sync_metadata": {
    "collective_sync": {
      "participant_publishers": ["pub-123", "pub-456"],
      "last_broadcast": "2026-02-15T09:00:00Z",
      "last_received": "2026-02-15T08:45:00Z",
      "shared_segments": ["seg-premium-audience"],
      "opt_in": true
    },
    "partner_sync_status": {
      "uid2": {
        "last_sync": "2026-02-15T09:00:00Z",
        "next_sync": "2026-02-16T09:00:00Z",
        "status": "success"
      },
      "id5": {
        "last_sync": "2026-02-15T09:00:00Z",
        "next_sync": "2026-02-16T09:00:00Z",
        "status": "success"
      }
    }
  }
}

Schema Design Principles

1. Versioning

  • Top-level version field for schema evolution
  • Metadata schema_version for quick compatibility checks
  • Allows backward-compatible changes

2. Timestamps

  • ISO 8601 format for all timestamps
  • Track creation, updates, sync times
  • Enable time-based queries and cleanup

3. Consent-First

  • Comprehensive consent tracking (TCF, GPP, CCPA, custom)
  • Purpose-level granularity
  • COPPA compliance flags

4. Partner Integration

  • Structured namespacing for DSPs, SSPs, data partners
  • Sync status tracking
  • Easy to add new partners

5. Privacy & Quality

  • No raw PII (only hashed identifiers)
  • Quality scoring and validation tracking
  • Data source attribution

Usage Patterns

Fast Metadata Access

// Check consent without reading full payload
let metadata = kv_store.get_metadata(synthetic_id)?;
if metadata.consent_status != "granted" {
    return Err("No consent");
}

Full Profile Read

let value = kv_store.get(synthetic_id)?;
let profile: SyntheticIdProfile = serde_json::from_str(&value)?;

Atomic Updates with Generation Markers

// Read with generation
let (value, generation) = kv_store.get_with_generation(synthetic_id)?;
let mut profile: SyntheticIdProfile = serde_json::from_str(&value)?;

// Update specific fields
profile.partner_identifiers.dsp_buyers.insert("new_dsp", buyer_data);
profile.updated_at = Utc::now();

// Write with generation check (fails if modified)
kv_store.put_with_generation(
    synthetic_id,
    &serde_json::to_string(&profile)?,
    generation
)?;

TTL-Based Expiration

// Set 90-day TTL for GDPR compliance
kv_store.put_with_ttl(
    synthetic_id,
    &serde_json::to_string(&profile)?,
    90 * 24 * 60 * 60  // 90 days in seconds
)?;

Size Considerations

  • Typical size: 5-15 KB per profile
  • Heavy user: 20-50 KB (many segments, partners)
  • Maximum: 25 MB (KV Store limit)
  • Metadata: ~200-400 bytes (well under 2048 limit)

Future Enhancements

  1. Compression: Use gzip for values >10KB
  2. Sharding: Split very large profiles across multiple keys
  3. Caching: Use metadata timestamps for cache invalidation
  4. Archival: Move stale profiles to cheaper storage
  5. Analytics: Aggregate statistics without PII

Related Documentation

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions