The sum() function in Attio: rollups without the rollup feature
Total pipeline per company. Lifetime closed-won value per account. Combined contract value across an account's renewals. Every CRM computes these somewhere — usually in a report you open twice a quarter. sum() puts them on the record itself, recalculated live, sortable in every view. It's a rollup without a rollup feature.
This is part of our function-by-function series on Attio formula attributes — previously: if(), timeSpentIn(), dateDiff(), the ?? operator, count(), hasBeenIn(), valueSetAt(), and contains(). This one covers sum(): the syntax, the relationship rollup, and the formulas worth copying.
Table of contents
- What the sum() function does
- The rollup trick
- sum() vs. count()
- Turning totals into tiers
- Blank-proofing your totals
- The rest of the array family
- CRM use cases that earn their keep
- Copy-paste formulas
- Final thoughts
What the sum() function does
sum() takes an array and adds it up:
sum(values)So 13px] bg-[color:var(--color-bg-muted)] border border-[color:var(--color-border)] px-1.5 py-0.5 rounded">sum([10, 25, 3]) returns 38. Like [count(), the literal-array form is the least interesting thing about it — you'll almost never hand-type numbers into a formula. The function matters because of what Attio lets you feed it.
The rollup trick
Attio's data model is built on relationships, and formulas inherit that graph: a formula on a Company can reach into its related records. Type { in the editor and the attributes exposed through your relationships appear alongside the Company's own — including the numeric ones on linked deals. Point sum() at the deal-value attribute your relationship exposes:
sum({Deal value})Total pipeline per company, live on every record. No report, no export, no rollup configuration — and because it's a real attribute, it sorts, filters, and feeds automations like any other column. The same pattern works for any numeric attribute across any relationship: contract values across an account's agreements, fees across a client's placements, whatever your objects link to.
This is the same trick that makes count({Team}) work, applied one step further: count tallies the edges of your data graph, sum aggregates a number *across* them.
sum() vs. count()
The two questions views eventually want side by side:
count()answers *volume* — how many deals, how many contacts. It counts the linked records themselves and needs no numeric attribute on the other side.sum()answers *value* — how much those deals are worth. It needs a numeric attribute to add up.
An account with 6 linked deals worth $12K total and an account with 1 deal worth $300K are different customers. Two one-line formulas next to each other tell you which is which at a glance.
Turning totals into tiers
A total is a metric. Wrapped in if(), it becomes a segment:
if((sum({Deal value}) ?? 0) > 100000, "Key account", "Standard")Every company self-classifies by pipeline weight, and "Key account" stops being a judgment call that lives in someone's head. Stack the thresholds with nested if() for tiers — the same pattern the count() article used for buying-committee sizes, pointed at money instead of people.
Blank-proofing your totals
The trap by now familiar from the whole series: an empty input evaluates to 13px] bg-[color:var(--color-bg-muted)] border border-[color:var(--color-border)] px-1.5 py-0.5 rounded">null, and null can blank the surrounding expression. A company with no linked deals is exactly the record a pipeline rollup should report as zero — not silently skip. Guard with [??:
sum({Deal value}) ?? 0Now dealless companies sort to the bottom of a pipeline-ranked view instead of vanishing from it, and threshold comparisons like the tier formula above can't drop them out of both buckets. Set the output type explicitly — Number or Currency to match what you're summing — rather than leaving it on Auto.
The rest of the array family
13px] bg-[color:var(--color-bg-muted)] border border-[color:var(--color-border)] px-1.5 py-0.5 rounded">sum() is one of seven array functions that all pair with relationship and multi-value attributes the same way: [count() for how many, 13px] bg-[color:var(--color-bg-muted)] border border-[color:var(--color-border)] px-1.5 py-0.5 rounded">avg() and median() for what's typical, min() and max() for the extremes — earliest renewal, largest deal — and unique() for distinct values. Same rollup trick, different aggregation; the full rundown lives in the [pillar guide's math section. sum() and count() are the two to ship first because volume and value are the two questions every account view asks.
CRM use cases that earn their keep
- Total pipeline per company —
sum({Deal value})across linked deals — important because "how much is in play at this account?" is the first question in every pipeline review, and it shouldn't require opening a report. - Lifetime value per account — sum over closed-won deal values — important because expansion targeting, tiering, and CS prioritization all key off LTV, and most teams recompute it in a spreadsheet monthly.
- Key-account tiers —
if((sum({Deal value}) ?? 0) > 100000, "Key account", "Standard")— important because account tiers decided by formula are consistent; tiers decided by vibe drift with whoever edited them last. - Combined contract value — sum across an account's linked contracts or subscriptions — important because renewals get negotiated per-contract while the relationship's real weight is the total, and the rep should see the total.
- Fees per client — sum of placement or project fees through the relationship — important for services businesses where revenue lives on child records and the client-level answer is otherwise a report away.
- Multi-value totals —
sum()on any multi-value number attribute — important because "what do these add up to?" is otherwise unanswerable in a view without exporting.
Copy-paste formulas
Swap in your attribute names and these work as-is:
Total pipeline per company (Currency output):
sum({Deal value})Blank-safe rollup for sorting and math (Currency output):
sum({Deal value}) ?? 0Key-account flag (Text output):
if((sum({Deal value}) ?? 0) > 100000, "Key account", "Standard")Three-tier account weight (Text output):
if((sum({Deal value}) ?? 0) > 250000, "Strategic", if((sum({Deal value}) ?? 0) > 100000, "Key account", "Standard"))Clean board-deck total (Currency output):
round(sum({Deal value}) ?? 0, 0)Final thoughts
13px] bg-[color:var(--color-bg-muted)] border border-[color:var(--color-border)] px-1.5 py-0.5 rounded">sum() is the value half of Attio's rollup story: [count() tells you how many records a relationship holds, sum() tells you what they're worth, and together they replace the two reports every account view secretly depends on. Ship sum({Deal value}) ?? 0 on your companies first — pipeline-per-account as a sortable column changes how the Monday review runs.
For the rest of the library — every math, logic, date, text, and history function with CRM use cases — see the complete guide to Attio formula attributes.
And if you'd rather have LTV rollups, account tiers, and pipeline metrics designed and shipped for you, that's literally what we do. Get a free workspace audit or see the AI-native Attio sprint.
Need help with your Attio setup?
We migrate teams, build data models, wire automations, and train Claude agents inside your workspace. Discovery call is free.
Book a free discovery callReady when you are.
Two ways in. Pick the friction that fits.