If you manage a mid-to-large Adobe Campaign Classic instance, there is a good chance your database is quietly growing because of a single checkbox that developers routinely enable during testing and forget to turn off before going to production. That checkbox is “Keep the results of interim populations between two executions” and the underlying field is @keepResult.
This post covers what it is, why it matters, the architectural quirk that makes it hard to query, and a production-ready JavaScript script to audit and bulk-disable it across your entire instance.
What is keepResult?
In Adobe Campaign Classic, every workflow activity that processes data passes its output to the next activity through a temporary work table. Once the workflow completes, those work tables are normally purged.
When you enable “Keep the results of interim populations between two executions” found in the workflow’s Properties > Execution tab ACC retains all those intermediate work tables between runs. This means every transition in the workflow holds its population data in the database indefinitely, not just until the next execution.
According to the Adobe Campaign Classic Data Life Cycle documentation:
“The target data is purged as the workflow is executed. Only the last work table is accessible. You can configure the workflow so that all work tables remain accessible: check the Keep the result of interim populations between two executions option in the workflow properties.”
Adobe is explicit about when this should be used. The official analysis use cases documentation states:
“The Keep the result of interim populations between two executions option must only be used in development phases, but never for an environment in production.”
That last sentence is the important one. This is a development and debugging tool, not a production setting.
Why it Causes Problems in Production
The immediate consequence is database bloat. Every workflow with @keepResult = true is accumulating work tables that are never purged. On a high-volume instance running hundreds or thousands of workflows, this can translate to gigabytes of unnecessary data building up over time.
Beyond disk usage, it has secondary effects on performance the Database Cleanup technical workflow has more to process, query times on system tables can increase, and backup sizes grow.
The problem compounds because developers habitually enable it while building or debugging a workflow, then forget to uncheck it before deploying. On a large team with many workflows being created simultaneously, this happens constantly and largely invisibly.
The Schema Quirk That Makes It Hard to Query
Here is where it gets interesting from a technical standpoint. You might expect to be able to query xtk:workflow with a <where> condition filtering on @keepResult = 1 and get a clean list. You cannot.
The reason is that @keepResult is defined with xml="true" on the xtk:workflow schema. As the Adobe Experience League community has documented:
“xml (boolean): if this option is activated, the values of the field don’t have a linked SQL field. Adobe Campaign creates a Text type mData field for record storage. This means there is no filtering or sorting on these fields.”
In other words, @keepResult is stored inside the serialised mData XML memo column rather than a dedicated SQL column. There is no index, so ACC cannot execute a WHERE keepResult = 1 query at the database level. Any attempt to add a <condition expr="@keepResult = 1"/> to a queryDef <where> clause will either return zero results or be silently ignored.
The only workaround is to retrieve all workflows via paginated queries and evaluate @keepResult in JavaScript after the fact which is exactly what the script below does.
Tip: You can also spot workflows with
keepResult=truemanually via the ACC console using the Advanced Filter on the workflow list, set the filter to XML memo data contains keepResult=”true”. But for bulk operations this doesn’t scale.
The Script: Audit and Bulk Disable
The script below runs in two passes. Pass 1 pages through all workflows in batches of 5,000, evaluates @keepResult in JavaScript, and collects the IDs of any workflows where it is true. Pass 2 then writes keepResult='0' to each of those workflows using xtk.session.Write.
The two-pass approach is deliberate, it ensures that the pagination in pass 1 is never affected by concurrent writes, and it gives you a clean audit log before any changes are made.
var startLine = 0;
var pageSize = 5000;
var hasMore = true;
var idsToUpdate = [];
// PASS 1 — collect IDs where keepResult = true
while (hasMore) {
var query = xtk.queryDef.create(
<queryDef schema="xtk:workflow" operation="select"
lineCount={pageSize} startLine={startLine}>
<select>
<node expr="@id"/>
<node expr="@label"/>
<node expr="@keepResult"/>
</select>
</queryDef>
).ExecuteQuery();
var batch = 0;
for each (var wf in query.workflow) {
batch++;
if (wf.@keepResult == true) {
logInfo("[keepResult=true] " + wf.@label + " (id=" + wf.@id + ")");
idsToUpdate.push(wf.@id);
}
}
if (batch < pageSize) {
hasMore = false;
} else {
startLine += pageSize;
}
}
logInfo("--- Found " + idsToUpdate.length + " workflows to update ---");
// PASS 2 — disable keepResult on collected IDs
for (var i = 0; i < idsToUpdate.length; i++) {
xtk.session.Write(
<workflow xtkschema="xtk:workflow" _operation="update"
id={idsToUpdate[i]} keepResult='0' _key="@id"/>
);
}
logInfo("--- Done: " + idsToUpdate.length + " workflows updated ---");Notes on the script
SpiderMonkey compatibility — ACC Classic runs on the SpiderMonkey ECMA5 engine. The script uses for each (var wf in query.workflow) for the XML collection iteration (correct for SpiderMonkey) and a standard indexed for loop for the plain JavaScript array in pass 2. Do not use for...of or Array.forEach — they are not supported.
Why wf.@keepResult == true works — The XML attribute comes back as a string. SpiderMonkey’s loose equality coerces "true" correctly in this comparison. It is the established community-verified pattern for this check.
Why keepResult='0' in the Write call — Boolean fields stored via xml="true" on the schema respond correctly to '0' as the falsy value in xtk.session.Write. Using false or {false} can behave inconsistently depending on the ACC build.
Pagination — The lineCount/startLine approach pages through all workflows without hitting the platform’s default 10,000-row ExecuteQuery cap. The batch < pageSize exit condition is the standard ACC pagination terminator — when a page returns fewer rows than requested, you have reached the end.
Running workflows — If a workflow currently has keepResult=true and is actively executing at the time the script runs, the write itself is safe. The change will take effect from the next execution.
Recommended: Dry Run First
Before running this on production, comment out pass 2 and replace it with a dry-run log line to verify the count looks right:
// PASS 2 — DRY RUN (comment out to audit without making changes)
logInfo("--- DRY RUN: would update " + idsToUpdate.length + " workflows ---");Once you are satisfied with the audit output, restore pass 2 and run for real.
Going Further: Schedule It as a Technical Workflow
Because developers will continue to enable this setting during development, a one-time cleanup is not enough. The sustainable approach is to wrap this script in a JavaScript activity inside a dedicated technical workflow, scheduled to run weekly or nightly. This keeps @keepResult continuously suppressed across the instance without requiring manual intervention.
A scheduled technical workflow for this purpose is referenced in the Adobe Experience League community as a best practice for instance hygiene management.
Summary
| Topic | Detail |
|---|---|
| Field | @keepResult on xtk:workflow schema |
| UI label | Keep the results of interim populations between two executions |
| Location | Workflow Properties > Execution tab |
| Effect when true | All intermediate work tables retained between executions |
| Production recommendation | Always false — development only |
| Why you can’t filter on it | xml="true" on schema — stored in mData memo, no SQL column |
| Fix | Paginated JS query + xtk.session.Write with keepResult='0' |
References: Adobe Campaign Classic — Data Life Cycle · Adobe Campaign Classic — Analysis Use Cases · Adobe Experience League Community — keepResult monitoring workflow · Adobe Experience League — Filter workflows by keepResult condition

