---
title: "Compact Receiver"
description: "Per-pattern compaction decision via a declarative cap-file. Decides\
  \ whether each event is emitted via encode() (compact templateHash+vars form, volume\
  \ reduction where the destination supports it) or as fullText. GitOps-controlled,\
  \ the MCP writes per-pattern entries via PR, engine hot-reloads the cap-file without\
  \ restart."
source: "https://github.com/log-10x/modules/tree/main/pipelines/run/modules/receive/compact/module.yaml"
icon: "material/tune-variant"

---
Compact specific patterns' events into a template+values tuple, without redeploying the engine.

The compact receiver makes a per-event decision whether to emit via `encode()` (the pattern's template hash plus extracted variable values, smaller where the destination supports it) or preserve `fullText`. The decision is keyed by pattern identity (the same symbolMessage the Reporter attributes cost to), so an operator targets compaction at the same patterns surfaced in cost analysis.

Entries live in a CSV cap-file, typically committed to a git repo and edited by PR. The file is hot-reloaded on in-place writes; a merged PR takes effect within ~10 seconds, no pod restart.

## :material-clipboard-list-outline: Per-pattern caps

A cap-file declares, for each pattern, whether its events are compacted or preserved. Patterns not listed fall back to `compactReceiverDefault`.

**File format**, CSV with a header row, keyed by the fields named in `compactReceiverFieldNames` joined with `_` (default: `[symbolMessage]`):

```csv
fieldSet,value
<fieldSet>,<true|false>[:<untilEpochSec>][:<reason>]
```

- `fieldSet`, the event fields named by `compactReceiverFieldNames` joined with `_`. With the default `[symbolMessage]` this is the symbolMessage value for the pattern.
- `value`, `true` compacts via `encode()`; `false` explicitly preserves `fullText` for this pattern (beats the default).
- `untilEpochSec`, optional Unix-epoch (seconds) expiry. Past it the entry self-heals and the pattern falls back to `compactReceiverDefault`.
- `reason`, optional free-text for audit. Must not contain commas (would break CSV parsing).

**Example** (with `compactReceiverDefault: false`):

```csv
fieldSet,value
payment_retry_gateway_timeout,true:1745856000:OPS-5123 spike
auth_audit_trail,false:1745856000:compliance keep verbose
```

The engine hot-reloads on in-place file writes (the gitops pattern); Kubernetes `ConfigMap` mounts don't reload because the CM swap is a symlink rename, not an in-place write.

## :material-swap-horizontal: Default policy

`compactReceiverDefault` sets the fallback decision when no cap-file entry matches:

- **`false`** (default), preserve `fullText`. Cap-file entries opt specific patterns *into* compaction. Right when most traffic is already high-signal.
- **`true`**, compact via `encode()`. Cap-file entries opt specific patterns *out* of compaction (e.g. audit/compliance patterns that must stay verbose). Right when most traffic is low-signal machinery and only a few patterns need full-text fidelity.

Flipping the default is a policy decision that affects every event and requires a pod rollout. Cap-file edits handle per-pattern exceptions without restart.

## :material-cog-box: Wiring

```yaml
compactReceiver:
  fieldNames: [symbolMessage]        # fields joined to form the lookup key
  default: false                     # fallback when no entry matches
  lookup:
    file: $=path("data/caps") + "/compact-cap.csv"
    retain: $=parseDuration("10m")
```

- Setting `lookup.file` enables the per-pattern compaction path; leaving it unset preserves the pre-compact behavior (receive-only emits `fullText`; `receiverOptimize=true` compacts every event).

Tune these values in this config block, not via container environment variables. Any `compactReceiver:` key set here resolves to a launch argument at engine init and shadows a same-named env var, so env-only overrides are silently ignored. Edit the config (via a gitops PR) to change a value at runtime.

## :material-wrench-outline: Config Files

To configure the compact receiver module, [:material-cog: Edit](https://doc.log10x.com/config/app/#module-config "Learn how to edit app and module configurations") these files.  

Below is the default configuration from: [compact/config.yaml](https://github.dev/log-10x/config/blob/main/pipelines/run/receive/compact/config.yaml "compact/config.yaml"){target="\_blank"}.  
  
<div class="edit-options">
    <a class="md-button tenx-edit-online-button" data-tooltip="Edit online on github.dev" href="https://github.dev/log-10x/config/blob/main/pipelines/run/receive/compact/config.yaml" target="_blank" rel="noopener noreferrer">
        <span class="twemoji" style="margin-right: 0.3rem;">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                <path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path>
            </svg>
        </span> Edit Online
    </a>
    <button class="md-button tenx-config.yaml0-edit-button" data-tooltip="Edit configuration file" data-dialog-id="config-yaml0-dialog">
        <span style="margin-right: 0.3rem;">
            <span class="twemoji">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                    <path d="M20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18,2.9 17.35,2.9 16.96,3.29L15.12,5.12L18.87,8.87M3,17.25V21H6.75L17.81,9.93L14.06,6.18L3,17.25Z"></path>
                </svg>
            </span>
        </span>Edit Locally
    </button>
</div>

<dialog id="config-yaml0-dialog" class="md-dialog md-dialog--editor">
    <div class="editor-dialog-wrapper">
        <div class="editor-dialog-header">
            <span class="editor-dialog-title">Edit config.yaml Locally</span>
            <div class="editor-header-actions">
                <button class="editor-toolbar-btn yaml-editor-locations" data-tooltip="Save">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M5 20h14v-2H5v2m14-9h-4V3H9v8H5l7 7 7-7Z"></path></svg>
                </button>
                <button class="editor-toolbar-btn yaml-editor-reset" data-tooltip="Reset to default">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M12.5 8c-2.65 0-5.05 1-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z"></path></svg>
                </button>
                <button class="editor-toolbar-btn yaml-editor-copy" data-tooltip="Copy to clipboard">
                    <svg class="icon-copy" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19 21H8V7h11m0-2H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m-3-4H4a2 2 0 0 0-2 2v14h2V3h12V1Z"></path></svg>
                    <svg class="icon-check" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="display:none;"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg>
                </button>
                <span class="header-divider"></span>
                <button class="editor-toolbar-btn yaml-editor-fullscreen" data-tooltip="Fullscreen">
                    <svg class="icon-maximize" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M5,5H10V7H7V10H5V5M14,5H19V10H17V7H14V5M17,14H19V19H14V17H17V14M10,17V19H5V14H7V17H10Z"></path></svg>
                    <svg class="icon-minimize" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" style="display:none;"><path fill="currentColor" d="M5,16H8V19H10V14H5V16M14,14V19H16V16H19V14H14M16,5V8H19V10H14V5H16M10,5V10H5V8H8V5H10Z"></path></svg>
                </button>
                <span class="header-divider"></span>
                <button class="editor-toolbar-btn editor-dialog-close" onclick="closeDialog('config-yaml0-dialog')" data-tooltip="Close">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"></path></svg>
                </button>
            </div>
        </div>
        <div class="editor-dialog-content">
            <div class="yaml-editor-container"></div>
        </div>
        <div class="yaml-editor-statusbar">
            <span class="yaml-editor-status"></span>
        </div>
    </div>
    <!-- Locations Popup -->
    <div class="locations-popup" style="display: none;">
        <div class="locations-popup-content">
            <div class="locations-popup-header">
                <span class="locations-header-label">Download and save to:</span>
                <button class="locations-popup-close" aria-label="Close">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
                        <path fill="currentColor" d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"></path>
                    </svg>
                </button>
            </div>
            <ul class="locations-list">
                <li>
                    <span class="location-label">Linux / Docker / macOS
                        <span class="help-icon" data-tooltip="Default system location. The engine automatically reads configs from here at startup. Best for production deployments.">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M11 18h2v-2h-2v2m1-16A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8m0-14a4 4 0 0 0-4 4h2a2 2 0 0 1 2-2 2 2 0 0 1 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5a4 4 0 0 0-4-4Z"/></svg>
                        </span>
                    </span>
                    <div class="location-path-row">
                        <code class="default-path location-path" data-tooltip=""
                            data-copy-osx="/etc/log10x/config/run/receive/compact/config.yaml"
                            data-copy-nix="/etc/log10x/config/run/receive/compact/config.yaml"
                            data-copy-win="C:\log10x\configs/run/receive/compact/config.yaml"></code>
                        <button class="copy-btn" data-tooltip="Copy path">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14">
                                <path fill="currentColor" d="M19 21H8V7h11m0-2H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m-3-4H4a2 2 0 0 0-2 2v14h2V3h12V1Z"></path>
                            </svg>
                        </button>
                    </div>
                </li>
                <li>
                    <span class="location-label">Custom directory
                        <span class="help-icon" data-tooltip="Set TENX_CONFIG environment variable to point to a custom config directory. Useful when you want configs in a non-standard location.">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M11 18h2v-2h-2v2m1-16A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8m0-14a4 4 0 0 0-4 4h2a2 2 0 0 1 2-2 2 2 0 0 1 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5a4 4 0 0 0-4-4Z"/></svg>
                        </span>
                    </span>
                    <div class="location-path-row">
                        <code class="location-path" data-tooltip="$TENX_CONFIG/run/receive/compact/config.yaml">$TENX_CONFIG/run/receive/compact/config.yaml</code>
                        <button class="copy-btn" data-tooltip="Copy path">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14">
                                <path fill="currentColor" d="M19 21H8V7h11m0-2H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m-3-4H4a2 2 0 0 0-2 2v14h2V3h12V1Z"></path>
                            </svg>
                        </button>
                    </div>
                </li>
                <li>
                    <span class="location-label">Within cloned repo
                        <span class="help-icon" data-tooltip="First run: git clone github.com/log-10x/config. Then save the file to this path within the cloned folder. Use for version control.">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="12" height="12"><path fill="currentColor" d="M11 18h2v-2h-2v2m1-16A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8m0-14a4 4 0 0 0-4 4h2a2 2 0 0 1 2-2 2 2 0 0 1 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5a4 4 0 0 0-4-4Z"/></svg>
                        </span>
                    </span>
                    <div class="location-path-row">
                        <code class="location-path" data-tooltip="./pipelines/run/receive/compact/config.yaml">./pipelines/run/receive/compact/config.yaml</code>
                        <button class="copy-btn" data-tooltip="Copy path">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14">
                                <path fill="currentColor" d="M19 21H8V7h11m0-2H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2m-3-4H4a2 2 0 0 0-2 2v14h2V3h12V1Z"></path>
                            </svg>
                        </button>
                    </div>
                </li>
            </ul>
            <div class="locations-popup-footer">
                <button class="locations-download-btn" title="Download config file">
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="14" height="14">
                        <path fill="currentColor" d="M5 20h14v-2H5v2m14-9h-4V3H9v8H5l7 7 7-7Z"></path>
                    </svg>
                    <span>Download</span>
                </button>
            </div>
        </div>
    </div>
</dialog>

<template class="tenx-config-schema" data-encoding="base64">ewogICJ0eXBlIiA6ICJvYmplY3QiLAogICJwcm9wZXJ0aWVzIiA6IHsKICAgICJpbmNsdWRlIiA6IHsKICAgICAgInR5cGUiIDogInN0cmluZyIKICAgIH0sCiAgICAidGVueCIgOiB7CiAgICAgICJ0eXBlIiA6ICJzdHJpbmciCiAgICB9LAogICAgImNvbXBhY3RSZWNlaXZlciIgOiB7CiAgICAgICJ0eXBlIiA6ICJvYmplY3QiLAogICAgICAiYWRkaXRpb25hbFByb3BlcnRpZXMiIDogZmFsc2UsCiAgICAgICJwcm9wZXJ0aWVzIiA6IHsKICAgICAgICAibG9va3VwIiA6IHsKICAgICAgICAgICJ0eXBlIiA6ICJvYmplY3QiLAogICAgICAgICAgImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiA6IGZhbHNlLAogICAgICAgICAgInByb3BlcnRpZXMiIDogewogICAgICAgICAgICAiZmlsZSIgOiB7CiAgICAgICAgICAgICAgInR5cGUiIDogWwogICAgICAgICAgICAgICAgInN0cmluZyIsCiAgICAgICAgICAgICAgICAibnVsbCIKICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICJtYXJrZG93bkRlc2NyaXB0aW9uIiA6ICJQYXRoIG9yIFVSTCB0byBhIHBlci1wYXR0ZXJuIGNvbXBhY3QgZGVjaXNpb25zIGNhcC1maWxlXG5cblBvaW50cyB0aGUgZW5naW5lIGF0IGEgY2FwLWZpbGUgd2hvc2UgZW50cmllcyBkZWNpZGUgd2hldGhlciBlYWNoIHBhdHRlcm4ncyBldmVudHMgYXJlIGNvbXBhY3RlZCB2aWEgYGVuY29kZSgpYCBvciBwcmVzZXJ2ZWQgYXMgYGZ1bGxUZXh0YC4gUGF0dGVybnMgbm90IGxpc3RlZCBmYWxsIGJhY2sgdG8gYGNvbXBhY3RSZWNlaXZlckRlZmF1bHRgLiAgVGhlIGxvb2t1cCBrZXkgaXMgdGhlIGV2ZW50IGZpZWxkcyBuYW1lZCBieSBgY29tcGFjdFJlY2VpdmVyRmllbGROYW1lc2Agam9pbmVkIHdpdGggYF9gIChkZWZhdWx0cyB0byBgW3N5bWJvbE1lc3NhZ2VdYCksIG1hdGNoaW5nIHRoZSBzYW1lIHBhdHRlcm4gaWRlbnRpdHkgdGhlIFJlcG9ydGVyIGF0dHJpYnV0ZXMgY29zdCB0by4gICoqRmlsZSBmb3JtYXQqKiAoQ1NWOyBoZWFkZXIgcm93ICsgb25lIGNvbW1hLXNlcGFyYXRlZCBlbnRyeSBwZXIgcm93KTogIGBgYCBmaWVsZFNldCx2YWx1ZSA8ZmllbGRTZXQ+LDx0cnVlfGZhbHNlPls6PHVudGlsRXBvY2hTZWM+XVs6PHJlYXNvbj5dIGBgYCAgLSBgZmllbGRTZXRgLCB0aGUgZXZlbnQgZmllbGRzIG5hbWVkIGJ5IGBjb21wYWN0UmVjZWl2ZXJGaWVsZE5hbWVzYCAgIGpvaW5lZCB3aXRoIGBfYC4gV2l0aCB0aGUgZGVmYXVsdCBgW3N5bWJvbE1lc3NhZ2VdYCB0aGlzIGlzIHRoZSAgIHN5bWJvbE1lc3NhZ2UgdmFsdWUgZm9yIHRoZSBwYXR0ZXJuLiAtIGB2YWx1ZWAsIGB0cnVlYCAoY29tcGFjdCB2aWEgYGVuY29kZSgpYCkgb3IgYGZhbHNlYCAoZXhwbGljaXRseSAgIHByZXNlcnZlIGBmdWxsVGV4dGAgZm9yIHRoaXMgcGF0dGVybiwgYmVhdGluZyB0aGUgZGVmYXVsdCkuIC0gYHVudGlsRXBvY2hTZWNgLCBvcHRpb25hbCBVbml4LWVwb2NoIChzZWNvbmRzKSBleHBpcnkuIFBhc3QgaXQgdGhlICAgZW50cnkgYmVjb21lcyBhIG5vLW9wIGFuZCB0aGUgcGF0dGVybiBmYWxscyBiYWNrIHRvICAgYGNvbXBhY3RSZWNlaXZlckRlZmF1bHRgLiAtIGByZWFzb25gLCBvcHRpb25hbCBmcmVlLXRleHQgZm9yIGF1ZGl0LiBNdXN0IG5vdCBjb250YWluIGNvbW1hcyAgICh3b3VsZCBicmVhayBDU1YgcGFyc2luZykuICAqKkV4YW1wbGUqKjogIGBgYCBmaWVsZFNldCx2YWx1ZSBwYXltZW50X3JldHJ5X2dhdGV3YXlfdGltZW91dCx0cnVlOjE3NDU4NTYwMDA6T1BTLTUxMjMgc3Bpa2UgYXV0aF9hdWRpdF90cmFpbCxmYWxzZToxNzQ1ODU2MDAwOmNvbXBsaWFuY2Uga2VlcCB2ZXJib3NlIGBgYCAgVGhlIGZpbGUgaXMgaG90LXJlbG9hZGVkIG9uIGluLXBsYWNlIHdyaXRlcyAodGhlIGdpdG9wcyBwYXR0ZXJuKTsgYSBLdWJlcm5ldGVzIGBDb25maWdNYXBgIG1vdW50IHdvbid0IHJlbG9hZCBiZWNhdXNlIHRoZSBDTSBzd2FwIGlzIGEgc3ltbGluayByZW5hbWUsIG5vdCBhbiBpbi1wbGFjZSB3cml0ZS4iCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgICJyZXRhaW4iIDogewogICAgICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgICAgICJudW1iZXIiLAogICAgICAgICAgICAgICAgInN0cmluZyIsCiAgICAgICAgICAgICAgICAibnVsbCIKICAgICAgICAgICAgICBdLAogICAgICAgICAgICAgICJtYXJrZG93bkRlc2NyaXB0aW9uIiA6ICJSZXRlbnRpb24gcGVyaW9kIGZvciB0aGUgcGVyLXBhdHRlcm4gY2FwLWZpbGUgYmVmb3JlIGl0IGlzIGNvbnNpZGVyZWQgc3RhbGVcblxuRGVmaW5lcyB0aGUgcmV0ZW50aW9uIHBlcmlvZCAoaW4gbWlsbGlzZWNvbmRzKSBmb3IgdGhlIGNhcC1maWxlIChgY29tcGFjdFJlY2VpdmVyTG9va3VwRmlsZWApLiBJZiB0aGUgZmlsZSdzIGxhc3QgbW9kaWZpZWQgdGltZSBpcyBvbGRlciB0aGFuIHRoaXMgcGVyaW9kLCBhIHdhcm5pbmcgaXMgbG9nZ2VkLiBUaGUgY2FwIGVudHJpZXMgY29udGludWUgdG8gYXBwbHk7IHRoZSBzdGFsZW5lc3MgY2hlY2sgaXMgYWR2aXNvcnkgc28gb3BlcmF0b3JzIG5vdGljZSB3aGVuIGFuIGF1dG9tYXRlZCB0b29saW5nIHBpcGVsaW5lIGhhcyBzdG9wcGVkIHVwZGF0aW5nIHRoZSBmaWxlLiAgKipWYWxpZGF0aW9uKio6IG11c3QgYmUgZ3JlYXRlciB0aGFuIDYwMDAwbXMgKDEgbWludXRlKS4gKEFjY2VwdHMgbnVtYmVyIG9yIHN0cmluZyB3aXRoICQ9IHByZWZpeCBmb3IgcnVudGltZSBldmFsdWF0aW9uKSAoRGVmYXVsdDogMzAwMDAwKSIsCiAgICAgICAgICAgICAgImRlZmF1bHQiIDogMzAwMDAwCiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgICJmaWVsZE5hbWVzIiA6IHsKICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgImFycmF5IiwKICAgICAgICAgICAgInN0cmluZyIsCiAgICAgICAgICAgICJudWxsIgogICAgICAgICAgXSwKICAgICAgICAgICJtYXJrZG93bkRlc2NyaXB0aW9uIiA6ICJFdmVudCBmaWVsZHMgam9pbmVkIHRvIGZvcm0gZWFjaCBldmVudCdzIGNhcC1maWxlIGxvb2t1cCBrZXlcblxuRGVmaW5lcyB0aGUgbGlzdCBvZiBUZW5YT2JqZWN0IGZpZWxkIG5hbWVzIGpvaW5lZCB3aXRoIGBfYCB0byBmb3JtIGVhY2ggZXZlbnQncyBsb29rdXAga2V5IGludG8gdGhlIGNhcC1maWxlLiBNYXRjaGVzIHRoZSByYXRlIHJlY2VpdmVyJ3MgYHJhdGVSZWNlaXZlckZpZWxkTmFtZXNgLCBzbyBhIGNhcC1maWxlIGVudHJ5IHRhcmdldHMgdGhlIHNhbWUgcGF0dGVybiBpZGVudGl0eSB0aGUgUmVwb3J0ZXIgYXR0cmlidXRlcyBjb3N0IHRvLiAgKipEZWZhdWx0Kio6IGBbc3ltYm9sTWVzc2FnZV1gLCB0aGUgc3ltYm9sTWVzc2FnZSBmaWVsZCwgd2hpY2ggaXMgdGhlIHN0YWJsZSBwYXR0ZXJuIGlkZW50aXR5IHByb2R1Y2VkIGJ5IHRoZSBlbmdpbmUncyBjbGFzc2lmaWVyLiAgTXVsdGktZGltZW5zaW9uYWwgY29tcGFjdGlvbiAoZS5nLiwgY29tcGFjdCBhIHBhdHRlcm4gb25seSBmb3IgYSBzcGVjaWZpYyB0ZW5hbnQpOiAgYGBgeWFtbCBjb21wYWN0UmVjZWl2ZXJGaWVsZE5hbWVzOiAgIC0gc3ltYm9sTWVzc2FnZSAgIC0gdGVuYW50SWQgYGBgICBDaGFuZ2luZyB0aGlzIGZpZWxkIHNldCByZXF1aXJlcyBhbiBlbmdpbmUgcmVzdGFydC4gKERlZmF1bHQ6IFtcInN5bWJvbE1lc3NhZ2VcIl0pIiwKICAgICAgICAgICJpdGVtcyIgOiB7CiAgICAgICAgICAgICJ0eXBlIiA6ICJzdHJpbmciCiAgICAgICAgICB9LAogICAgICAgICAgImRlZmF1bHQiIDogWwogICAgICAgICAgICAic3ltYm9sTWVzc2FnZSIKICAgICAgICAgIF0KICAgICAgICB9LAogICAgICAgICJkZWZhdWx0IiA6IHsKICAgICAgICAgICJ0eXBlIiA6IFsKICAgICAgICAgICAgImJvb2xlYW4iLAogICAgICAgICAgICAic3RyaW5nIiwKICAgICAgICAgICAgIm51bGwiCiAgICAgICAgICBdLAogICAgICAgICAgIm1hcmtkb3duRGVzY3JpcHRpb24iIDogIkZhbGxiYWNrIGNvbXBhY3Rpb24gZGVjaXNpb24gd2hlbiBubyBjYXAtZmlsZSBlbnRyeSBhcHBsaWVzXG5cbkNvbnRyb2xzIHRoZSBmYWxsYmFjayBkZWNpc2lvbiB3aGVuIG5vIGNhcC1maWxlIGlzIGxvYWRlZCwgbm8gZW50cnkgbWF0Y2hlcyBhbiBldmVudCdzIHBhdHRlcm4sIG9yIGEgbWF0Y2hpbmcgZW50cnkgaGFzIGV4cGlyZWQuICAtIGBmYWxzZWAgKGRlZmF1bHQpLCBwcmVzZXJ2ZSBgZnVsbFRleHRgLiBDYXAtZmlsZSBlbnRyaWVzIG9wdCAgIHNwZWNpZmljIHBhdHRlcm5zIElOVE8gY29tcGFjdGlvbi4gLSBgdHJ1ZWAsIGNvbXBhY3QgdmlhIGBlbmNvZGUoKWAuIENhcC1maWxlIGVudHJpZXMgb3B0IHNwZWNpZmljICAgcGF0dGVybnMgT1VUIChlLmcuLCBhdWRpdC9jb21wbGlhbmNlIHBhdHRlcm5zIHRoYXQgbXVzdCBzdGF5ICAgdmVyYm9zZSkuICBGbGlwcGluZyB0aGlzIHZhbHVlIGlzIGEgcG9saWN5LWxldmVsIGRlY2lzaW9uIChhZmZlY3RzIGV2ZXJ5IGV2ZW50KSwgbm90IGEgY2FwLWZpbGUgZWRpdC4gQ2hhbmdpbmcgaXQgcmVxdWlyZXMgYSBwb2Qgcm9sbG91dC4gVGhlIGNhcC1maWxlIGhhbmRsZXMgcGVyLXBhdHRlcm4gb3ZlcnJpZGVzIHdpdGhvdXQgcmVzdGFydC4gKEFjY2VwdHMgYm9vbGVhbiBvciBzdHJpbmcgd2l0aCAkPSBwcmVmaXggZm9yIHJ1bnRpbWUgZXZhbHVhdGlvbikiCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfSwKICAiYWRkaXRpb25hbFByb3BlcnRpZXMiIDogdHJ1ZQp9</template>

```yaml
# 🔟❎ 'run' compact receiver configuration

# Per-pattern compaction decision via a declarative cap-file.
# The forwarder output stream emits encode() for listed patterns and
# fullText for everyone else (or vice versa via per-pattern opt-out).
# To learn more see https://doc.log10x.com/run/receive/compact/

# Set the 10x pipeline to 'run'
tenx: run

# =============================== Dependencies ================================

include: run/modules/receive/compact

# ============================ Compact Options ================================

compactReceiver:

  # 'fieldNames' defines the TenXObject fields joined with underscores to form
  # each event's lookup key. Defaults to [symbolMessage], matching the rate
  # receiver's rateReceiverFieldNames so MCP-authored entries address the same
  # pattern_hash the Reporter attributes cost to.
  fieldNames:
    - symbolMessage

  # 'default' is the fallback when no cap-file entry matches the event's
  # pattern. `false` (default) preserves fullText; `true` compacts via
  # encode(). The cap-file's per-pattern decision overrides this per event.
  default: false

  lookup:

    # 'file' specifies the per-pattern cap-file path. Hot-reloaded on in-place
    #  writes (the gitops pattern); Kubernetes ConfigMap mounts won't reload.
    #  Comment out to disable the cap-file (every event follows 'default' above).
    # file: $=path("data/sample/compact") + "/compact-cap.csv"

    # 'retain' specifies the period before the file is marked as stale.
    retain: $=parseDuration("10m")
```

## :material-menu: Options

Specify the options below to [configure](/config "configure") the compact receiver:

|Name|Description|
|---|---|
|[compactReceiverLookupFile](#compactreceiverlookupfile "path or URL to a per-pattern compact decisions cap-file")|Path or URL to a per-pattern compact decisions cap-file|
|[compactReceiverLookupRetain](#compactreceiverlookupretain "retention period for the per-pattern cap-file before it is considered stale")|Retention period for the per-pattern cap-file before it is considered stale|
|[compactReceiverFieldNames](#compactreceiverfieldnames "event fields joined to form each event's cap-file lookup key")|Event fields joined to form each event's cap-file lookup key|
|[compactReceiverDefault](#compactreceiverdefault "fallback compaction decision when no cap-file entry applies")|Fallback compaction decision when no cap-file entry applies|

### :material-menu-right-outline:**`compactReceiverLookupFile`**

Path or URL to a per-pattern compact decisions cap-file.

|Type|Default|
|---|---|
|String|""|

Points the engine at a cap-file whose entries decide whether each
pattern's events are compacted via `encode()` or preserved as
`fullText`. Patterns not listed fall back to `compactReceiverDefault`.

The lookup key is the event fields named by `compactReceiverFieldNames`
joined with `_` (defaults to `[symbolMessage]`), matching the same
pattern identity the Reporter attributes cost to.

**File format** (CSV; header row + one comma-separated entry per row):

```
fieldSet,value
<fieldSet>,<true|false>[:<untilEpochSec>][:<reason>]
```

- `fieldSet`, the event fields named by `compactReceiverFieldNames`
  joined with `_`. With the default `[symbolMessage]` this is the
  symbolMessage value for the pattern.
- `value`, `true` (compact via `encode()`) or `false` (explicitly
  preserve `fullText` for this pattern, beating the default).
- `untilEpochSec`, optional Unix-epoch (seconds) expiry. Past it the
  entry becomes a no-op and the pattern falls back to
  `compactReceiverDefault`.
- `reason`, optional free-text for audit. Must not contain commas
  (would break CSV parsing).

**Example**:

```
fieldSet,value
payment_retry_gateway_timeout,true:1745856000:OPS-5123 spike
auth_audit_trail,false:1745856000:compliance keep verbose
```

The file is hot-reloaded on in-place writes (the gitops pattern); a
Kubernetes `ConfigMap` mount won't reload because the CM swap is a
symlink rename, not an in-place write.


### :material-menu-right-outline:**`compactReceiverLookupRetain`**

Retention period for the per-pattern cap-file before it is considered stale.

|Type|Default|
|---|---|
|Number|300000|

Defines the retention period (in milliseconds) for the cap-file
(`compactReceiverLookupFile`). If the file's last modified time is
older than this period, a warning is logged. The cap entries continue
to apply; the staleness check is advisory so operators notice when an
automated tooling pipeline has stopped updating the file.

**Validation**: must be greater than 60000ms (1 minute).


### :material-menu-right-outline:**`compactReceiverFieldNames`**

Event fields joined to form each event's cap-file lookup key.

|Type|Default|
|---|---|
|List|\[symbolMessage\]|

Defines the list of TenXObject field names joined with `_` to form
each event's lookup key into the cap-file. Matches the rate receiver's
`rateReceiverFieldNames`, so a cap-file entry targets the same pattern
identity the Reporter attributes cost to.

**Default**: `[symbolMessage]`, the symbolMessage field, which is the
stable pattern identity produced by the engine's classifier.

Multi-dimensional compaction (e.g., compact a pattern only for a
specific tenant):

```yaml
compactReceiverFieldNames:
  - symbolMessage
  - tenantId
```

Changing this field set requires an engine restart.


### :material-menu-right-outline:**`compactReceiverDefault`**

Fallback compaction decision when no cap-file entry applies.

|Type|Default|
|---|---|
|Boolean|false|

Controls the fallback decision when no cap-file is loaded, no entry
matches an event's pattern, or a matching entry has expired.

- `false` (default), preserve `fullText`. Cap-file entries opt
  specific patterns INTO compaction.
- `true`, compact via `encode()`. Cap-file entries opt specific
  patterns OUT (e.g., audit/compliance patterns that must stay
  verbose).

Flipping this value is a policy-level decision (affects every event),
not a cap-file edit. Changing it requires a pod rollout. The cap-file
handles per-pattern overrides without restart.


<br/>:material-github: This module is defined in [compact/module.yaml](https://github.com/log-10x/modules/tree/main/pipelines/run/modules/receive/compact/module.yaml "compact/module.yaml"){target="\_blank"}.

