Updated · 7 min read
Custom attributes: the data design that decides what your program can do
Every lifecycle program accumulates custom attributes — custom_plan, last_purchase_date, subscription_tier, preferred_category. Over time, dozens become hundreds. Some are used daily. Most are stale remnants of campaigns that shipped once and never again. That accumulated mess is the single most common reason 'can we segment on X?' turns into a multi-week engineering project instead of the 15 minutes it should be. This is how you stop the sprawl before it starts.
By Justin Williames
Founder, Orbit · 10+ years in lifecycle marketing
Three principles that keep the data clean
Custom attributes are infrastructure. Badly named or badly maintained attributes produce unreliable segmentation, personalisation that fires on the wrong users, and engineering queues full of "can we fix this attribute" tickets.
Three principles that do the work of a hundred style-guide rules:
Attributes are derived data, not raw data. Don't create an attribute for every column in your data warehouse. Create attributes for the specific segmentation and personalisation decisions the lifecycle program actually needs to make. "user_is_premium_tier" is useful. "user_plan_internal_id" is clutter. The warehouse is the source of truth; the ESP holds the derived view the program actually uses. Reverse-ETL copying every column is how you end up with 300 attributes and no one who knows which ones are live.
Every attribute has a defined update path. How does this attribute get set? How does it get updated? Who owns it? Attributes without a maintenance plan go stale silently, and silent staleness is the worst kind — the data looks fine right up until it produces a wrong send.
Retire aggressively. An attribute with no active campaigns using it is clutter. Audit quarterly. Remove anything unused. The cost of keeping them isn't zero — they confuse future teammates, bloat the data model, and slowly turn "let me check" into a 40-minute forensic exercise.
A naming convention that scales
Without a convention, attribute names become a free-text mess. Two people name the same concept three different ways and six months later nobody knows which one updates. The convention that works for most programs:
[domain]_[entity]_[property]_[aggregation]
Examples:
• subscription_plan_tier — user's current subscription tier
• commerce_order_count_lifetime — total orders ever
• commerce_order_count_90d — orders in the last 90 days
• engagement_email_open_count_30d — email opens in the last 30 days
• preference_category_primary — user's top category
The domain prefix groups related attributes in ESP dropdowns. The aggregation suffix ("_lifetime", "_90d", "_count") makes the data shape obvious at a glance. Pick snake_case and stick to it — camelCase and snake_case mixed in the same instance is a recipe for bugs when authors misremember which format applies to which attribute. See the Braze naming conventions guide for the broader naming framework this fits into.
Tier your attributes so you know what to protect
Not every attribute is equally important. Sort them into tiers with different maintenance standards:
Tier 1 — Core attributes. Used across many campaigns. Updated frequently. Central to segmentation. subscription_tier, lifetime_order_count, last_engagement_date. These get reliable update pipelines and continuous monitoring. If one of these breaks, it's a fire — multiple programs are now lying.
Tier 2 — Program-specific attributes. Used by one or two specific programs. birthday_month for birthday emails. preferred_frequency for frequency management. Owned by the specific program. Retired when the program retires.
Tier 3 — Computed or temporary attributes. Derived at send time or for a one-off campaign. Usually better handled via Liquid or segment logic at send time rather than persisted as an attribute.
,
Data freshness is a design choice, not a detail
Every attribute needs a defined update mechanism, and the right mechanism depends on what the attribute drives:
Real-time (event-driven). Updated the moment a user action occurs. Fast but requires event pipelines. Best for attributes that drive immediate triggers — "user_is_in_cart" has to be right within seconds or the cart-abandon flow fires on the wrong population.
Batch (nightly or hourly). Computed in the warehouse and pushed to the ESP on a schedule. Acceptable lag for most segmentation — lifetime_order_count, preferred_category — because nobody notices if the number is 12 hours old. Requires reverse-ETL or similar pipeline.
Send-time (computed via Liquid or similar). Computed when the email sends. Nothing stored. Most flexible; requires catalogue or data availability at send time, and a set of decisions about what happens when the catalogue is missing.
Document which mechanism each attribute uses. When something appears wrong, the first question is "when was this last updated, by which pipeline?" Programs without that documentation spend hours on debug sessions that should have taken three minutes. Over-refreshing wastes pipeline resources; under-refreshing causes wrong sends — neither is free.
The failure modes that show up in every audit
Stale attributes. An attribute that was useful in 2024 no longer updates. Campaigns still filter on it. Results are wrong. Fix: quarterly audit, confirm update pipelines are still running, retire anything no longer maintained.
Multiple sources of truth. Two attributes tracking the same thing — "subscription_status" and "is_subscriber" — updated by different pipelines, disagreeing in subtle ways. Fix: designate one as source of truth. Remove or compute the other from it.
Attribute sprawl. 300+ attributes, most unused, nobody knows which ones matter. Fix: audit and retire. Establish a creation-approval process for new attributes so new sprawl doesn't immediately replace the old sprawl.
Privacy-sensitive data over-stored. Detailed personal data (full birthdate, address, income) stored when only a derived attribute (age_bracket, city, plan_tier) is needed. Fix: store the minimum needed for lifecycle. Keep raw data in the warehouse where privacy controls are stronger and access is audited.
Retire safely. The three-step version: audit all campaigns and segments referencing the attribute, remove or redirect those references, wait 30 days of no usage, then delete. Removing the attribute before cleaning up references breaks campaigns in production; don't skip step one. How many attributes should a program have at all? As few as enable the decisions you need to make. Most programs operate comfortably with 30–80 active attributes. Above 200 is usually sprawl territory — the number matters less than the attribute-to-usage ratio. Every attribute should have at least one active campaign or segment referencing it, or it shouldn't exist.
treats attribute hygiene as part of the quarterly program audit. Most programs discover 20–40% of their attributes are stale or duplicated the first time they actually run it.
Frequently asked questions
- What is a custom attribute in Braze?
- A custom attribute is a user-level data field beyond the built-in properties (email, first name, etc.). Common custom attributes: subscription_tier, last_purchase_date, nps_score, product_interests, churn_risk_band. Custom attributes are the backbone of segmentation and personalisation — segments filter on them, Liquid renders them, triggers fire when they change. They differ from events: attributes describe current state, events describe historical action.
- How should I name custom attributes?
- snake_case, typed prefixes, and domain-consistent vocabulary. Examples: dt_last_purchase (dt_ for dates), is_paying (is_ for booleans), n_sessions_30d (n_ for counts), amt_ltv (amt_ for amounts), tier_subscription (tier_ for categorical). The prefixes make filtering in the Braze UI faster (typing "is_" shows all boolean attributes) and help non-technical team members read segments without memorising every field's type.
- How many custom attributes should I maintain?
- Fewer than most workspaces have — and audited quarterly. Every Braze instance I've seen eventually accumulates 200+ attributes where 100+ haven't been written to or read in a year. Dead attributes clutter segment-builder dropdowns, slow down the UI, and confuse new team members. Best practice: review all attributes quarterly, identify any with zero writes in the past 90 days, and archive them. Keep the active set under 100 wherever possible.
- Events vs custom attributes — which to use?
- Events for actions (purchased, viewed, clicked, signed_up), attributes for state (current_tier, is_active, total_lifetime_value). Events are appended to a log and queryable historically; attributes are single-value per user and represent current state. Use events to trigger programs; use attributes to segment and personalise. Common failure: storing event data as attributes (current_last_purchase instead of a purchased event log) loses history and wastes attribute slots.
- Should I store computed values as custom attributes?
- Yes for values expensive to compute live, no for values the ESP can derive from events. Good examples of stored-computed attributes: churn_risk_band (from a ML model computed daily), lifetime_value (aggregated from purchase events), tier_mapping (from subscription data). Avoid storing what can be derived cheaply from event streams — it creates consistency risk (the stored value drifts from the truth) and wastes slots.
Read to the end
Scroll to the bottom of the guide — we'll tick it on your reading path automatically.
This guide is backed by an Orbit skill
Related guides
Browse allProgressive profiling: asking users for data without scaring them off
Progressive profiling means collecting user data over time in small, contextual prompts instead of one giant signup form. Done well, it transforms personalisation data quality. Done badly, it's irritating surveillance with extra steps.
Personalisation that doesn't feel creepy
There's a line between personalisation that earns trust and personalisation that breaks it. It's not where most people think it is — it's about how you signal what you know, not what you know. Here's the line, how programs cross it without noticing, and the patterns that keep you on the right side.
CRM vs CDP: which tool do you actually need?
Vendors sell CRM, CDP, marketing automation, and ESP as if they're four shapes of the same box. They aren't. Here's what each one actually does, where it falls over, and the decision rule for picking one first.
Email dark mode: the four render modes and how to not break any of them
Dark mode in email isn't one feature — it's four different render behaviours across major clients, each with its own logic. Design without knowing which mode you're hitting and roughly half your audience sees something you never approved. Here's what each client does and the defensive rules that survive all of them.
Mobile email design: 65% of opens are on a phone — design for that
Two-thirds of email is opened on mobile. Most designs still start with desktop and hope it collapses. Here are the mobile-first rules that reliably produce emails that read, click, and convert on a phone.
Transactional email anatomy: the five sections every transactional needs
Transactional emails open at 3–5x the rate of marketing and carry more brand signal per send than anything else in the program. Most teams treat them as ops artefacts and miss the leverage entirely. Here's the five-section anatomy that works across every transactional type.
Found this useful? Share it with your team.
Use this in Claude
Run this methodology inside your Claude sessions.
Orbit turns every guide on this site into an executable Claude skill — 62 lifecycle methodologies, 84MCP tools, native Braze integration. Pay what it's worth.