An idempotency key, and where the response is stored

A client that times out and retries has sent the same request twice, and the server cannot tell whether the first one succeeded.

$key = $request->header('Idempotency-Key');

try {
    $record = IdempotentRequest::create(['key' => $key, 'route' => 'orders.store']);
} catch (QueryException $e) {
    $prior = IdempotentRequest::where('key', $key)->firstOrFail();

    return response($prior->response_body, $prior->response_status);
}

// do the work, then store the response on $record — same transaction

Storing the response rather than only the key is what makes the retry return the same answer instead of a conflict, which is what a retrying client needs. Writing the record in the same transaction as the work is what stops a crash between them leaving a key claimed and nothing done. Expiring keys after a day keeps the table small and is safe, because no reasonable client retries later than that.