Use a Local channel only when the call needs dialplan re-entry
A Local channel calls back into Asterisk's own dialplan. It is useful when a queue member, callfile or other application needs dialplan logic before the eventual destination, or when individual destinations need different handling. That flexibility adds an internal channel layer and a performance cost; it is not a required wrapper for an ordinary endpoint call.
Start with the reason for the layer and the exact dial string, such as Local/201@desk-routing. Preserve the originating application, context, extension, variables that must survive, intended final channel and rollback. A route that can be expressed and observed correctly without an extra Local pair is usually easier to diagnose without one.
Map both halves before counting or changing channels
Asterisk creates Local channels in pairs. The two channel names end in ;1 and ;2, and media entering one half passes out through the other. One requested Local destination therefore produces two internal channels with separate unique identifiers; it does not prove two customer calls or two external sessions.
Correlate the original channel, both Local halves and the eventual destination by timestamp, channel name, uniqueid, linkedid, dial events and bridge identifiers. Keep the application-facing half separate from the half that executes the requested dialplan. Channel inventory, concurrent-call accounting and failure diagnosis can all be wrong when the pair is collapsed into one row or counted as two independent conversations.
Expect optimization unless retained behavior is required
By default, a Local channel tries to optimize itself out after the destination answers and the call path can be joined directly. That removes the Local pair from the active media path. It can also remove channel variables, dialplan state and Dial() options that were attached to the Local channel rather than to a surviving outside channel. Disappearance after answer can therefore be normal optimization, not a crash or missing call.
Append /n only when the Local pair must stay in the call path because a required channel-specific behavior lives there. Asterisk documents this as the no-release modifier. It preserves the internal layer and its cost, so do not make it a blanket fix for every queue member, callfile or originate path. First name the exact variable, option, feature or observation that optimization would otherwise discard.
Select modifiers by the behavior they change
The documented modifiers are not interchangeable. /j enables the generic jitter buffer on the Local channel and must be combined with /n so optimization does not remove it. /m forwards music-on-hold start and stop requests instead of handling them on the Local channel. /b returns the actual channel behind the Local channel when queried, which changes transfer handling.
Use a modifier only after reproducing the behavior it owns. A jitter-buffer need is not evidence that transfers require /b; music-on-hold signaling is not evidence that every variable must remain on a retained pair. Record the complete dial string, loaded dialplan and application help from the running build before and after the change.
Place data on the channel that must keep it
Optimization is a data-ownership boundary. Asterisk's CDR specification warns that CDR properties set on an optimizing Local channel are not propagated to the surviving channels. It directs administrators toward pre-dial handlers when data must be set on the appropriate channel at creation. The same discipline applies to any channel-scoped feature: identify which channel owns it and whether that channel survives.
Do not add /n merely to preserve reporting data that belongs on the final channel. Instead, map the creation point, inheritance requirements, pre-dial handler and expected post-optimization owner. Then verify the value on the intended channel. A variable visible before answer is not proof that it survived optimization or reached a backend record.
When the symptom is specifically a variable, option or CDR value that disappears after answer, follow the focused Local-channel diagnosis. It separates optimization, inheritance, channel creation, pre-dial placement and justified retention before changing the dial string.
Read bridge and record changes as a lifecycle
AMI represents optimization with LocalOptimizationBegin and LocalOptimizationEnd. Depending on bridge membership, a remaining channel can move between bridges or bridges can merge, producing bridge-leave, bridge-enter or bridge-merge events. The specification does not define which channel moves first or which bridge wins, so an observer must correlate identifiers rather than depend on one incidental event order.
CDR records attached to the optimized Local channels are finalized, and the merged bridge relationships can generate new records. Use linkedid, uniqueid, sequence and channel names together; do not assume one CDR row equals one business call. Use CEL or AMI event evidence when the question is chronological, while keeping record dispatch, backend storage and report consumption as later stages.
Pilot answer and failure paths before production use
For an authorized pilot, capture the original channel, both Local halves, destination channel, answer, bridge membership, optimization events, variables or options that must persist, hangup and resulting CDR or CEL evidence. Test answer, no answer, busy, cancellation, transfer, hold and release only where those paths are in scope. For /n, compare the retained pair and cleanup against the documented need; without /n, confirm the expected surviving channels and data owners.
Correct only the demonstrated owner: an unnecessary Local layer, wrong context or extension, misplaced channel data, missing modifier, unjustified retained pair, observer correlation or downstream report logic. Roll back if channel cleanup, transfer, media, feature behavior or reporting regresses. No PBX, Local channel, queue, callfile, channel variable, bridge, event, record, endpoint, media path or live call was inspected or tested for this guide.
Do not leave a required header on an optimizing intermediary
A value on a Local channel does not prove that the outbound PJSIP channel owns the corresponding header. The outbound-header guide shows the callee pre-dial and version-supported inheritance paths; the existing Local-channel diagnostic remains the place to prove which channel survives.
Keep the spool attempt separate from the Local-channel pair
A call file can originate Local/extension@context, after which the Local channel creates its two halves and may optimize. The call-file guide keeps queue status, first-leg answer and later Local-channel or Dial outcome separate; use the spool diagnostic before changing channel optimization.
Correlate both Local halves after an AMI originate
When AMI originates a Local channel, record the action ID and both channel identifiers, then follow optimization and downstream Dial evidence. The AMI Originate diagnostic prevents a successful first Local leg from being mistaken for a completed second-party call.
Name both Local halves created through ARI
ARI channel operations accept a client channelId and an otherChannelId for the second Local-channel half. The ARI origination guide retains both identifiers so optimization, bridge membership and final records stay attached to the correct channel.
Do not confuse a Gosub frame with a Local-channel pair
A regular Gosub reuses dialplan on the current channel; it does not create the two halves of a Local channel. The Gosub guide identifies the current frame and handler channel before any Local optimization is considered.
Map post-bridge continuation across both Local halves
When a Local channel is involved, the after-bridge diagnostic proves which half entered the bridge, which survived optimization and which channel actually owned the destination.
Keep Local halves visible in channel counts
A Local channel normally adds two legs and may optimize out. The channel-groups guide maps membership to the intended owner rather than treating a linked call as one automatic count.
Assign log groups to the intended Local-channel half
The LOG_GROUP diagnostic treats each Local-channel half and any outbound leg as a distinct channel owner rather than assuming one group covers the entire call.
Trace the intended Local-channel half
The frame-trace guide treats each Local-channel half and later outbound leg as a separate owner; a linked ID correlates them without proving identical frame flow.
Do not transfer lock ownership between Local halves
The dialplan-lock guide treats each Local-channel half as a separate mutex owner even when linked IDs correlate the call.
Track variables across both Local-channel halves
The missing-variable diagnostic places writes relative to creation of both Local halves and keeps inheritance distinct from optimization and /n retention.
A Dial result does not erase Local-channel ownership
The Dial application guide keeps the calling channel, Local pair, final outbound leg, bridge and continuation channel distinct.
Track a Local originated channel before any second leg
The Originate diagnostic preserves the Local pair, destination handoff, optimization and later Dial channels as distinct stages.
Resolve the live Local half before bridging
The Bridge diagnostic treats optimization, replacement and channel lifetime as target-identity evidence.
Preserve the live target across BridgeAdd lookup
The BridgeAdd diagnostic proves target identity and existing bridge membership at invocation time.
Re-resolve channel identity before an AMI bridge action
The wrong-membership diagnostic accounts for rename, optimization, hangup and replacement.
Re-resolve transfer channels before mutation
The AMI transfer diagnostic accounts for optimization, rename, hangup and replacement.
Do not cancel against a stale transferer name
The CancelAtxfer diagnostic preserves stable IDs across replacement and callback legs.
Add explicit optimization control and outcome evidence
The AMI Local optimization guide relates /n, /j, /b and /m to action, event and bridge evidence.
Expect channel inventory to change after optimization
The channel lifetime diagnostic distinguishes an optimized-away Local pair from a failed surviving call leg.
Do not infer the activation leg after optimization
The dynamic-feature diagnostic uses live channel and bridge identity before interpreting self or peer.
Expect AMI variable targets to change across optimization
The AMI variable diagnostic re-resolves the live channel rather than reusing a Local-channel label.
Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- Asterisk Local Channel overview ↗
- Asterisk Local Channel modifiers ↗
- Asterisk Local Channel optimization ↗
- Asterisk callfile and Local Channel example ↗
- Asterisk ARI channels and Local Channel pairs ↗
- Asterisk AMI v2 Local Channel optimization events ↗
- Asterisk CDR specification and Local Channel optimization ↗
- Asterisk channel-variable inheritance ↗
- Asterisk pre-dial handlers ↗
- Asterisk PJSIP_HEADER dialplan function ↗
- Asterisk PJSIP_INHERITABLE_HEADER dialplan function ↗
- Asterisk PJSIP_HEADERS dialplan function ↗
- Asterisk PJSIP_HEADER_PARAM dialplan function ↗
- Asterisk PJSIP_RESPONSE_HEADER dialplan function ↗
- Asterisk call-file documentation ↗
- Official Asterisk sample.call ↗
- Asterisk outgoing spool source ↗
- Asterisk module-loading troubleshooting ↗
- Asterisk main configuration reference ↗
- Asterisk 23 AMI Originate action ↗
- Asterisk 23 OriginateResponse event ↗
- Asterisk Manager TCP/IP API ↗
- Asterisk network security guidance ↗
- Asterisk API boundary overview ↗
- Asterisk 23 ARI Channels REST API ↗
- Asterisk configuration for ARI ↗
- Asterisk ARI channel-state operations ↗
- Asterisk ARI bridge operations ↗
- Asterisk ARI basic mixing bridges ↗
- Asterisk dialplan subroutines overview ↗
- Asterisk Gosub guide ↗
- Asterisk 22 Gosub application reference ↗
- Asterisk 22 Return application reference ↗
- Asterisk STACK_PEEK function reference ↗
- Asterisk pre-bridge handlers ↗
- Asterisk 22 Dial application reference ↗
- Asterisk 22 CHANNEL function reference ↗
- Asterisk 22 Bridge application reference ↗
- Asterisk 22 Goto application reference ↗
- Asterisk 22 BridgeEnter AMI event ↗
- Asterisk 22 BridgeLeave AMI event ↗
- Asterisk 22 Hangup AMI event ↗
- Asterisk GROUP function ↗
- Asterisk GROUP_COUNT function ↗
- Asterisk GROUP_LIST function ↗
- Asterisk GROUP_MATCH_COUNT function ↗
- Asterisk channels key concepts ↗
- Asterisk LOG_GROUP dialplan function ↗
- Asterisk 22 LOG_GROUP dialplan function ↗
- Asterisk logging overview ↗
- Asterisk basic logging commands ↗
- Asterisk call identifier logging ↗
- Asterisk collecting debug information ↗
- Asterisk FRAME_TRACE dialplan function ↗
- Asterisk FRAME_DROP dialplan function ↗
- Asterisk CHANNEL dialplan function ↗
- Asterisk LOCK dialplan function ↗
- Asterisk TRYLOCK dialplan function ↗
- Asterisk UNLOCK dialplan function ↗
- Asterisk 22 SHARED dialplan function ↗
- Asterisk global variables basics ↗
- Asterisk 22 Set application ↗
- Asterisk 22 MASTER_CHANNEL function ↗
- Asterisk 22 LOCAL function ↗
- Asterisk 22 LOCAL_PEEK function ↗
- Asterisk 22 VARIABLE_EXISTS function ↗
- Asterisk 22 IMPORT function ↗
- Asterisk 23 Dial application ↗
- Asterisk hangup-cause overview ↗
- Asterisk HANGUPCAUSE_KEYS function ↗
- Asterisk 23 Originate application ↗
- Asterisk 22 Originate application ↗
- Asterisk 23 Bridge application ↗
- Asterisk Bridge application overview ↗
- Asterisk 23 CHANNELS function ↗
- Asterisk ARI bridge overview ↗
- Asterisk 23 BridgeWait application ↗
- Asterisk 22 BridgeWait application ↗
- Asterisk 23 BridgeAdd application ↗
- Asterisk 22 BridgeAdd application ↗
- Asterisk 23 AMI Bridge action ↗
- Asterisk 22 AMI Bridge action ↗
- Asterisk 23 AMI BridgeList action ↗
- Asterisk 23 AMI BridgeInfo action ↗
- Asterisk 23 AMI BridgeKick action ↗
- Asterisk 22 AMI BridgeKick action ↗
- Asterisk 23 AMI BridgeCreate event ↗
- Asterisk 23 AMI BridgeEnter event ↗
- Asterisk 23 AMI BridgeLeave event ↗
- Asterisk 23 AMI BridgeInfoChannel event ↗
- Asterisk 23 AMI BridgeInfoComplete event ↗
- Asterisk 23 AMI Redirect action ↗
- Asterisk 22 AMI Redirect action ↗
- Asterisk 23 AMI BlindTransfer action ↗
- Asterisk 22 AMI BlindTransfer action ↗
- Asterisk 23 AMI Atxfer action ↗
- Asterisk 22 AMI Atxfer action ↗
- Asterisk 23 AMI BlindTransfer event ↗
- Asterisk 23 AMI AttendedTransfer event ↗
- Asterisk 23 AMI CancelAtxfer action ↗
- Asterisk 22 AMI CancelAtxfer action ↗
- Asterisk 23 attended-transfer feature configuration ↗
- Asterisk 22 attended-transfer feature configuration ↗
- Asterisk feature-code call transfers ↗
- Asterisk 23 AMI LocalOptimizeAway action ↗
- Asterisk 22 AMI LocalOptimizeAway action ↗
- Asterisk 23 AMI LocalOptimizationBegin event ↗
- Asterisk 23 AMI LocalOptimizationEnd event ↗
- Asterisk 23 AMI LocalBridge event ↗
- Asterisk CHANNEL_EXISTS dialplan function ↗
- Asterisk CLI channel creation and manipulation ↗
- Asterisk AMI CoreShowChannels action ↗
- Asterisk AMI CoreShowChannel event ↗
- Asterisk func_channel implementation ↗
- Asterisk custom dynamic features ↗
- Asterisk built-in dynamic features ↗
- Asterisk features overview ↗
- Asterisk upstream features.conf sample ↗
- Asterisk upstream features configuration implementation ↗
- Asterisk 23 AMI Getvar action ↗
- Asterisk 23 AMI Setvar action ↗
- Asterisk 23 AMI VarSet event ↗
- Asterisk channel-variable setting and substitution ↗
- Asterisk 23 SHARED dialplan function ↗
- Asterisk external-protocol dialplan-function safeguards ↗
- Asterisk AMI event filtering ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.