Skip to content

Recorded output

River jobs can record a JSON object as their “output” for use by other jobs or elsewhere in the application. Any JSON-encodable value can be recorded.


How to record job output

River provides a river.RecordOutput function that can be called within a worker's Work function to record output for the job:

type MyWorkerOutput struct {
    CreatedResourceID string `json:"created_resource_id"`
}

// ...

func (w *MyWorker) Work(ctx context.Context, job *river.Job[MyJobArgs]) error {
    // ... other job execution logic ...
    // Now that the job has finished, record its output as a final step:
    output := MyWorkerOutput{CreatedResourceID: "123"}
    if err := river.RecordOutput(ctx, job, output); err != nil {
        return err
    }
    return nil
}

The output is stored in the job's metadata under the "output" key (rivertype.MetadataKeyOutput). This does not involve an additional database query, as the metadata is updated as part of the asynchronous job completion process.

JSON marshalling happens inline and RecordOutput will return an error if JSON serialization fails.

Only one output can be stored per job. If this function is called more than once, the output will be overwritten with the latest value. Once recorded, the output is stored regardless of the outcome of the execution attempt (success, error, panic, etc.).

Using with JobCompleteTx

This feature is also compatible with transactional job completion using JobCompleteTx, however there is an important caveat. While a job's output can be recorded at any time during execution, it must be recorded before calling JobCompleteTx in order for the output to be recorded as part of the same transaction.

Calling RecordOutput after JobCompleteTx has been called will still work, but there will be a window of time where the output is not yet recorded in the database on the completed job before it is later added asynchronously.

How to read job output

Once saved on the job row, the output can be read from a loaded river.JobRow using the Output method. The output is a []byte of the JSON-encoded output value provided to RecordOutput, so it must be unmarshalled to the appropriate type before use:

output := job.Output()
if output == nil {
    // handle error
}

var myOutput MyWorkerOutput
if err := json.Unmarshal(output, &myOutput); err != nil {
    // handle error
}

Performance and size considerations

The output is stored as part of the job row's metadata column, which is a jsonb type in Postgres. Take care to ensure that the encoded output payload size is not too large; the hard size limit is 32 MB, though it's recommended to keep it much smaller.