skip to content

What does Acct-Delay-Time (41) on a retried RADIUS Accounting-Request correct for, and what must change alongside it?

level: seniorimportance: nice to knowfreq 26%

answer

  1. the record may arrive long after the event
  2. how long it has been trying
  3. arrival time minus the delay
  4. changing content means a new Identifier
  5. seconds queued, not retries counted

basics

~20 s

Acct-Delay-Time (41) reports how many seconds the access device has been trying to deliver this record, so the server can subtract it from arrival time to recover the approximate event time. Updating it changes the packet's content, so the Identifier must change too.

solid answer

~50 s

Accounting is best-effort: an `Accounting-Request (Code 4)` is a datagram on UDP port 1813, and the device keeps retrying until an `Accounting-Response (Code 5)` acknowledges it or a local limit discards it. That means a record can arrive long after the thing it describes. `Acct-Delay-Time (41)` is the device's statement of how many seconds it has been trying to send this record, so the server recovers the approximate event time as arrival time minus the delay — approximate, because network transit is not counted. The device updates the value on each retry, and because that changes the packet's content, it must allocate a **new Identifier** for the retransmission; reusing the old one presents two different records under one identity. A queue of unacknowledged records is the failure that costs money: the buffer is finite and what overflows is unbilled.

code

pseudocode · 17 lines
pseudocode
function send_accounting_record(record):
    queued_for = 0
    loop:
        record.Acct-Delay-Time = queued_for
        identifier = next_identifier()   // content changed: new one
        transmit(record, identifier)     // Accounting-Request -> 1813

        if acknowledged_within(timeout):  // Accounting-Response (5)
            return delivered

        queued_for = queued_for + elapsed_seconds
        if queued_for > local_discard_limit:
            return dropped               // unbilled traffic

// server side
approximate_event_time = arrival_time - record.Acct-Delay-Time
// approximate: one-way transit time is not included

go deeper

for a junior

Know that RADIUS accounting records ride UDP and can be delayed or lost, so the time a record arrives is not the time the thing it describes happened.

for a middle

Explain the subtraction the server performs and why the attribute is a duration in seconds rather than a count of retransmissions.

for a senior

Show the operational half: the identifier rule on retry, the finite queue behind it, and why a rising delay across the fleet is the warning worth wiring to an alert.

for a principal

Decide what unbilled loss is acceptable and what it is worth spending to avoid it — buffer sizing, a second collector, or a transport whose failures are visible.

## Accounting is best-effort, and the record knows it The accounting half of RADIUS makes no delivery guarantee. Each record is an `Accounting-Request (Code 4)` datagram to UDP port 1813, and the only confirmation is an `Accounting-Response (Code 5)` coming back. The access device therefore retries a record until it is acknowledged or until a locally configured limit gives up on it. Two consequences shape everything else: - A record's **arrival time is not its event time**. A `Stop (2)` for a session that ended at 02:11 can land at 03:40 because the path was down in between. - The device is holding records in memory while it retries, and that memory is finite. `Acct-Delay-Time (41)` is the attribute that makes the first problem solvable and the second one visible. ## What the attribute says It carries the number of seconds the device has been trying to send *this record*. The server's reconstruction is a subtraction: ```pseudocode approximate_event_time = arrival_time - Acct-Delay-Time ``` The word **approximate** is load-bearing. Network transit time is not included in the delay value, so the result is off by the one-way latency of the path. For billing that is irrelevant; for correlating an accounting record against an event elsewhere it is exactly the error you must budget for. Note also what it is not: - It is **not** `Acct-Session-Time (46)`, which is the session's duration. A record can describe a two-week session and have an `Acct-Delay-Time (41)` of four seconds. - It is **not** a retry counter. It is a duration in seconds, and a device retrying quickly may send several attempts within one second. ## Why the Identifier must change with it The one-octet Identifier in the RADIUS header is what matches a reply to a request, and the rule that governs it is simple: the Identifier must change whenever the content of the packet changes. Updating `Acct-Delay-Time (41)` changes the content, so the retransmission is a **new** packet and needs a **new** Identifier. Keeping the old one is a real defect rather than an untidiness: 1. Two datagrams with different bodies now carry the same identity, so a response cannot be attributed to either with confidence. 2. A server's duplicate-detection cache keys on the identity, and the honest retransmission is either swallowed as a duplicate of something it is not, or accepted as a second distinct record. 3. A device that retries without updating the delay at all avoids the identifier problem and creates a worse one — the server then dates the event from arrival, and every queued record is timestamped late. | Behaviour on retry | Effect on the server | |---|---| | Update the delay, allocate a new Identifier | Correct: the event time is recoverable and each attempt is distinguishable | | Update the delay, keep the Identifier | Two different bodies under one identity; duplicate detection becomes unreliable | | Retransmit the original unchanged | Duplicate detection works, but the event time is lost and dated from arrival | ## The queue is the failure that costs money This is where the attribute earns its place in an operator's monitoring rather than only in a parser: - The retry buffer is finite. When the accounting path is broken for long enough, the oldest records are dropped, and a dropped record is traffic nobody can bill and an audit trail with a hole in it. - A **rising `Acct-Delay-Time (41)` across many sessions and many devices** is the protocol's own early warning: the records are being delivered, but they are queueing first. It is visible before the buffer overflows, which is the only useful time to see it. - An `Accounting-Response (Code 5)` is an acknowledgement of receipt. It says the server got the datagram. It does not say the record was stored, matched to a session or billed, and treating it as a storage guarantee means a server that accepts and discards looks perfectly healthy from the device. - Interim records interact with all of this: frequent updates mean a dropped record costs less, because the next one restates the cumulative totals anyway. A dropped `Stop (2)` is the expensive one, because nothing later restates it. ## The shape of a good answer Name the attribute, say it is a duration and not a counter, give the subtraction the server performs, state that the result is approximate because transit is excluded, and then give the operational half: the identifier rule on retry, and the fact that a queue of unacknowledged records is where best-effort accounting turns into lost revenue.

  • How exact is the event time a server reconstructs this way?
    Approximate. The device reports how long it has been trying, but the datagram's flight time is not in that figure, so the result is early by the one-way latency of the path. Good enough for billing, and a known error term for anything correlating records against other evidence.
  • Why is a rising Acct-Delay-Time (41) across a fleet worth alerting on?
    It means records are queueing before delivery. The retry buffer is finite, so the trend leads the overflow, and overflow is traffic that can never be billed. It is the one signal the protocol itself gives you before the loss becomes permanent.
  • What exactly does an Accounting-Response (Code 5) promise?
    That the datagram arrived. It is the device's cue to stop retrying and free the record from its queue. It carries no statement that the record was stored, correlated to a session or billed, so a server that accepts and then loses records looks entirely healthy from the device's side.

saying these in an interview costs you the question

  • Thinks Acct-Delay-Time (41) counts the session's duration
  • Keeps the same Identifier after updating Acct-Delay-Time (41)
  • Says an Accounting-Response (5) confirms the record was billed
  • Assumes a lost accounting record is retried forever
  • Timestamps the event at arrival, ignoring the delay attribute