<!-- Canonical URL: https://ask.atlascloud.ai/migrate-together-ai-batch-job-without-losing-request-ids -->

# How Do You Migrate a Together AI Batch Job Without Losing Request IDs?

> Keep each application-owned custom_id unchanged while mapping Together file and batch IDs to separate target-provider fields. Validate the full ID set before submission, join success and error outputs by ID, and retry through an attempt ledger without changing the business key.

Migrate a Together AI batch job by treating every source `custom_id` as immutable application data. Copy it unchanged into the target batch request, keep the target provider's batch and response IDs in separate fields, and reconcile results by `custom_id` rather than file order.

The important distinction is between the identifier your application owns and identifiers issued by either provider. A migration should preserve the former and map the latter.

## Inventory every identifier

Together batch input is JSONL. Each line carries a unique `custom_id` and a request body. The batch itself, uploaded input file, output file, and individual generated response may all have separate provider IDs.

| Identifier | Owner | Migration rule |
|---|---|---|
| `custom_id` | Your application | Preserve exactly |
| Source batch ID | Together | Store as source metadata |
| Target batch ID | Target provider | Store separately |
| Input and output file IDs | Each provider | Never use as business keys |
| Response ID | Model API | Keep for support and billing |

Never replace `custom_id` with a line number unless the line number was already your durable key. Output order may differ from input order, and failed requests may be written to a separate error file.

## Build a migration ledger

Before submitting anything to the target API, create one ledger row per logical request:

```json
{
  "custom_id": "invoice-2026-00421",
  "source_batch_id": "batch_source",
  "target_batch_id": null,
  "payload_sha256": "...",
  "state": "prepared"
}
```

Make `custom_id` unique within the migration set and add a hash of the normalized request body. The hash detects accidental edits without storing another copy of sensitive prompt data in the ledger.

## Convert the envelope, not the identity

Providers can use different batch envelopes. Together examples place `custom_id` beside `body`; another OpenAI-compatible batch API may also require `method` and `url`.

```json
{"custom_id":"invoice-2026-00421","method":"POST","url":"/v1/chat/completions","body":{"model":"target-model","messages":[{"role":"user","content":"Classify this record"}]}}
```

Change the endpoint, model ID, and unsupported parameters through a converter. Pass the source `custom_id` through as an opaque string. Do not trim, lowercase, translate, or regenerate it.

## Validate before submission

Run four checks on the generated JSONL:

* every line parses independently;
* every `custom_id` is present and unique;
* the set of IDs equals the source manifest;
* every body passes the target endpoint's schema.

Record the final file hash and line count. Upload exactly that artifact, then attach the returned target file and batch IDs to the migration ledger.

## Reconcile outputs and errors together

When the target batch finishes, download both its output and error artifacts. Index every row by `custom_id`, then compare the union with the submitted set.

Classify each ID as succeeded, failed, missing, or duplicated. A completed batch is not necessarily a fully reconciled batch. Do not mark the migration complete until every submitted ID has exactly one terminal disposition.

## Retry without changing identity

Create a new retry batch containing only failed or missing requests. Keep the same `custom_id` so downstream joins still work, and add an `attempt` field to your ledger rather than changing the business key.

If the target forbids reuse across batches, keep the original value in a dedicated application field and generate a transport ID with a reversible mapping. Never discard the original identifier.

## Cut over safely

Start with a small representative batch. Compare success rate, latency, token usage, model outputs, error categories, and cost. Keep source and target result tables side by side until reconciliation is deterministic.

Once the process works, automate three assertions: no unknown IDs, no duplicate terminal results, and no missing IDs. Those checks are more important than matching output order.

## The bottom line

Preserve the application-owned `custom_id`, translate only the provider envelope, and maintain a ledger that maps source and target batch artifacts. Reconcile successful and failed result files by ID, retry with an attempt record, and cut over only when every submitted request has a terminal outcome.

## FAQ

### Which ID must remain stable during a Together batch migration?

Preserve the custom_id assigned by your application. Together and target-provider batch, file, and response IDs should be stored as separate metadata rather than used as the business key.

### Can I reconcile batch results by line number?

No. Batch output order can differ from input order, and failed requests may appear in a separate file. Reconcile the union of output and error rows by custom_id.

### What should the migration ledger contain?

Store custom_id, a normalized payload hash, source and target batch and file IDs, attempt number, timestamps, and one terminal disposition for each submitted request.

### Should a retry receive a new custom_id?

Normally no. Keep the business identifier stable and increment an attempt field. If transport IDs must be unique across batches, keep a reversible mapping to the original custom_id.

### How do I detect lost requests?

Compare the set of submitted IDs with the union of success and error IDs. Flag any missing, unknown, or duplicated ID before declaring reconciliation complete.

### Can I reuse a Together input file unchanged?

Only if the target accepts the same envelope, endpoint, model ID, and parameters. Most migrations need an envelope converter, but that converter should pass custom_id through unchanged.
