Column Mapping

The problem

Two systems export the same data with different column names. A bank statement calls a field counterparty. The ERP calls it entity_name. A legacy CRM uses customer_id. The new platform uses cust_id.

Without column mapping, Reconlify sees these as unrelated columns. It cannot match counterparty to entity_name or compare their values. Rows that are actually identical appear as entirely different.

Example datasets

You are reconciling a payment processor export against your internal ledger. The data is the same, but every column has a different name.

payments.csv (source)

pay_id,merchant,pay_amount,pay_currency,pay_date,method
P-3001,Acme Corp,4500.00,USD,2026-02-15,wire
P-3002,Globex Inc,1200.50,EUR,2026-02-16,ach
P-3003,Initech Ltd,8900.00,GBP,2026-02-16,wire
P-3004,Wayne Ent,320.75,USD,2026-02-17,card

ledger.csv (target)

transaction_id,vendor_name,amount,currency,txn_date,payment_method
P-3001,Acme Corp,4500.00,USD,2026-02-15,wire
P-3002,Globex Inc,1200.50,EUR,2026-02-16,ach
P-3003,Initech Ltd,8900.00,GBP,2026-02-16,wire
P-3004,Wayne Ent,320.75,USD,2026-02-17,card

The records are identical. But a raw diff would flag every row because the column headers do not match.

The column mapping config

type: tabular
source: payments.csv
target: ledger.csv
 
keys:
  - pay_id
 
column_mapping:
  pay_id: transaction_id
  merchant: vendor_name
  pay_amount: amount
  pay_currency: currency
  pay_date: txn_date
  method: payment_method

Each entry in column_mapping is a pair: the left side is the source column name, the right side is the target column name it corresponds to.

With this mapping, Reconlify knows that pay_id in the source corresponds to transaction_id in the target, merchant corresponds to vendor_name, and so on. It pairs the values and compares them correctly.

Logical column names

Column mapping introduces a concept that affects how you write the rest of your config: the logical name.

The logical name is the source-side column name. Once you define a mapping, you use the logical name everywhere else in the config — keys, tolerance, string rules, filters, include/exclude columns. You never reference target column names outside of column_mapping.

Here is how the three names relate for each column in this example:

Source column Target column Logical name
pay_id transaction_id pay_id
merchant vendor_name merchant
pay_amount amount pay_amount
pay_currency currency pay_currency
pay_date txn_date pay_date
method payment_method method

The logical name is always the source column name. The mapping tells Reconlify how to find the corresponding column in the target file.

This means the rest of the config reads naturally in source terms:

keys:
  - pay_id            # not "transaction_id"
 
tolerance:
  pay_amount: 0.05    # not "amount"
 
string_rules:
  merchant:           # not "vendor_name"
    - trim
    - case_insensitive

If a column has the same name in both files, you do not need to map it. Unmapped columns are looked up by their source name in the target file automatically.

Result interpretation

With the mapping above, Reconlify matches all four rows by pay_id and compares every mapped column pair. The report summary:

{
  "source_rows": 4,
  "target_rows": 4,
  "missing_in_target": 0,
  "missing_in_source": 0,
  "rows_with_mismatches": 0,
  "mismatched_cells": 0
}

Zero mismatches. The data is identical despite completely different column names.

If the target had a different value — say vendor_name was "ACME CORP" instead of "Acme Corp" for P-3001 — the report sample would show:

{
  "key": { "pay_id": "P-3001" },
  "columns": {
    "merchant": {
      "source": "Acme Corp",
      "target": "ACME CORP"
    }
  }
}

The report uses the logical name (merchant) in the output. The key also uses the logical name (pay_id). You can trace every difference back to the source schema without needing to remember target column names.

To handle that casing difference, add a string rule — using the logical name:

string_rules:
  merchant:
    - case_insensitive

Mapping with generated columns

Column mapping works with source-side normalization to bridge structural differences, not just naming differences.

The source stores names in two columns. The target has a single combined field with a different name:

column_mapping:
  full_name: customer_full_name
 
normalization:
  full_name:
    - op: concat
      args: [first_name, " ", last_name]
    - op: trim
 
ignore_columns:
  - first_name
  - last_name

Normalization generates full_name on the source side. Column mapping tells Reconlify that full_name corresponds to customer_full_name in the target. The generated value is compared against the target column.

The logical name for the generated column is full_name — the name you chose in the normalization section. It works like any other logical name in keys, tolerance, or string rules.

How mapping interacts with other config sections

Every config section uses logical names. Column mapping only affects how Reconlify looks up the target column.

Config section Uses logical names? Example
keys Yes keys: [pay_id] matches against transaction_id in target
compare.include_columns Yes include_columns: [pay_amount] includes the mapped target column
compare.exclude_columns Yes exclude_columns: [pay_date] excludes the mapped target column
ignore_columns Yes ignore_columns: [pay_date] ignores the mapped target column
tolerance Yes tolerance: { pay_amount: 0.05 } applies to the mapped pair
string_rules Yes string_rules: { merchant: [trim] } normalizes both sides
normalization Yes Generated column names are logical names

If a column is not listed in column_mapping, Reconlify assumes the target uses the same name as the source. You only need to map columns that differ.

Limitations

  • No many-to-one mapping. Each logical column maps to exactly one target column. You cannot map two source columns to the same target column.
  • No one-to-many mapping. Each target column can only be mapped from one logical column.
  • Rename only. Column mapping is a pure rename on the target side, not a transform. To transform values, use source-side normalization.
  • Runtime validation. Reconlify checks that mapped target columns exist when the file is loaded. If a mapped column is missing from the target file, the error appears at runtime.