Building Queues
What is a Queue?
A queue is where callers wait before being connected to an available agent. Think of it like a virtual waiting room - callers enter the queue, wait their turn, and get connected to the next available agent.
Real-World Examples
- Sales Queue: Callers waiting to talk to sales representatives
- Support Queue: Customers waiting for technical support
- VIP Queue: Priority queue for your most important customers
- Billing Queue: Dedicated queue for billing inquiries
How Queues Work in Contact Centers
- Caller enters queue → Via contact flow transfer
- Queue music/announcements play → Keeps caller informed while waiting
- Agent becomes available → System finds next caller in queue
- Call connects → Agent and caller are connected
When You Need Queues
Create queues whenever you want to:
- Organize calls by department (Sales, Support, Billing)
- Route calls to specialized agents (Technical, VIP, Spanish-speaking)
- Manage call volumes and wait times
- Track queue metrics (average wait time, calls answered, etc.)
- Set capacity limits to prevent overwhelming agents
Creating Your First Queue
Let's build a simple queue step-by-step.
Step 1: Use QueueBuilder
The easiest way to create a queue is with QueueBuilder:
var queue = new QueueBuilder()
.SetName("CustomerSupport")
.Build();That's it! This creates a basic queue with default settings.
Step 2: Add to Stack
Add the queue to your CDK stack:
var app = new App();
var stack = new SwitchboardStack(app, "MyContactCenter", "my-center");
var queue = new QueueBuilder()
.SetName("CustomerSupport")
.Build();
stack.AddQueue(queue);
app.Synth();Step 3: Deploy
Deploy your stack:
cdk deployCongratulations! You've created your first queue. Now callers can be transferred to the "CustomerSupport" queue from contact flows.
Queue Configuration
Let's explore the different settings you can configure for queues.
Setting Queue Name (Required)
Every queue must have a unique name:
var queue = new QueueBuilder()
.SetName("Sales")
.Build();Naming Tips:
- Use descriptive names (Sales, Support, Billing)
- Be consistent (avoid "sales", "Sales_Queue", "SALES")
- No special characters (use letters, numbers, and hyphens)
- Keep it short but meaningful
Setting Description (Optional)
Add a description to document the queue's purpose:
var queue = new QueueBuilder()
.SetName("VIPSupport")
.SetDescription("Priority queue for VIP customers with premium support contracts")
.Build();When to use:
- Documenting queue purpose for your team
- Explaining special routing rules
- Noting capacity limits or business hours
Setting Capacity - Max Contacts (Optional)
Limit how many callers can wait in the queue at once:
var queue = new QueueBuilder()
.SetName("Support")
.SetMaxContacts(100)
.Build();What happens when the queue is full?
- New callers hear a "queue full" message
- Contact flow can route to overflow queue
- Or play a callback offer message
When to set capacity:
- Prevent extremely long wait times
- Match queue size to staffing levels
- Force overflow routing when overloaded
- Improve customer experience with callbacks
Default: No limit (queue can grow indefinitely)
Example with overflow:
// Main queue with capacity limit
var mainQueue = new QueueBuilder()
.SetName("Support")
.SetMaxContacts(50)
.Build();
// Overflow queue
var overflowQueue = new QueueBuilder()
.SetName("SupportOverflow")
.SetMaxContacts(25)
.Build();
// Flow checks queue status
var flow = new FlowBuilder()
.SetName("SupportRouting")
.CheckQueueStatus("Support")
.Branch(branch =>
{
branch.When("$.Queue.IsFull == false", "transfer-main");
branch.Otherwise("transfer-overflow");
})
.Build();Setting Outbound Caller ID (Optional)
Configure the phone number and name shown when agents call from this queue:
var queue = new QueueBuilder()
.SetName("Sales")
.SetOutboundCallerId("Acme Sales Team", "+18005551234")
.Build();When to use:
- Different departments use different numbers
- Branding (show company name to customers)
- Tracking (know which queue called back)
- Compliance (display correct business phone number)
Parameters:
- Name: What displays to the called party (e.g., "Acme Sales")
- Number: The phone number displayed (must be claimed in Amazon Connect)
Important: The phone number must be:
- Claimed in your Amazon Connect instance
- Enabled for outbound calls
Adding Tags (Optional)
Tags help organize and track queues for cost allocation and reporting:
var queue = new QueueBuilder()
.SetName("Support")
.AddTag("Department", "CustomerService")
.AddTag("CostCenter", "CC-1234")
.AddTag("Environment", "Production")
.Build();Common tag uses:
- Department: Track which team owns the queue
- Environment: Separate dev/staging/production queues
- CostCenter: Allocate AWS costs to business units
- Region: Track queues by geographic region
Associating with Hours of Operation
Queues can be linked to business hours schedules. This determines when the queue is "open" for receiving calls.
Why Hours Matter
When you associate hours with a queue:
- Contact flows can check if the queue is open
- Route callers differently during/after hours
- Display accurate status to agents
How to Link Hours to Queues
Option 1: When adding to stack (Recommended)
// Create hours of operation
var hours = new HoursOfOperation
{
Name = "BusinessHours",
TimeZone = "America/New_York"
};
hours.AddDayConfig(new HoursOfOperationConfig
{
Day = DayOfWeek.Monday,
StartTime = new TimeRange { Hours = 9, Minutes = 0 },
EndTime = new TimeRange { Hours = 17, Minutes = 0 }
});
stack.AddHoursOfOperation(hours);
// Create queue
var queue = new QueueBuilder()
.SetName("Support")
.Build();
// Associate queue with hours when adding to stack
stack.AddQueue(queue, "BusinessHours");Option 2: Using SetHoursOfOperation (Advanced)
var queue = new QueueBuilder()
.SetName("Support")
.SetHoursOfOperation("arn:aws:connect:us-east-1:123456789012:instance/abc/hours/xyz")
.Build();Recommendation: Use Option 1 - it's cleaner and handles ARN resolution automatically.
Complete Queue Examples
Basic Support Queue
Simple queue for general customer support:
var supportQueue = new QueueBuilder()
.SetName("CustomerSupport")
.SetDescription("General customer support queue")
.SetMaxContacts(100)
.Build();
stack.AddQueue(supportQueue, "BusinessHours");VIP Queue
Priority queue for VIP customers:
var vipQueue = new QueueBuilder()
.SetName("VIPSupport")
.SetDescription("Priority queue for VIP customers")
.SetMaxContacts(50)
.SetOutboundCallerId("VIP Support Team", "+18005559999")
.AddTag("Priority", "High")
.AddTag("SLA", "5-minutes")
.Build();
stack.AddQueue(vipQueue, "24x7Hours");After-Hours Queue
Queue with different hours and callback option:
var afterHoursQueue = new QueueBuilder()
.SetName("AfterHoursSupport")
.SetDescription("Limited support queue for after-hours calls")
.SetMaxContacts(10)
.AddTag("Shift", "AfterHours")
.Build();
// Different hours schedule
var afterHours = new HoursOfOperation
{
Name = "AfterHours",
TimeZone = "America/New_York"
};
afterHours.AddDayConfig(new HoursOfOperationConfig
{
Day = DayOfWeek.Monday,
StartTime = new TimeRange { Hours = 17, Minutes = 0 },
EndTime = new TimeRange { Hours = 21, Minutes = 0 }
});
stack.AddHoursOfOperation(afterHours);
stack.AddQueue(afterHoursQueue, "AfterHours");Department-Specific Queues
Multiple queues for different departments:
var salesQueue = new QueueBuilder()
.SetName("Sales")
.SetDescription("Sales inquiries and new customers")
.SetMaxContacts(75)
.SetOutboundCallerId("Acme Sales", "+18005551000")
.AddTag("Department", "Sales")
.Build();
var supportQueue = new QueueBuilder()
.SetName("TechnicalSupport")
.SetDescription("Technical support for existing customers")
.SetMaxContacts(150)
.SetOutboundCallerId("Acme Support", "+18005552000")
.AddTag("Department", "Support")
.Build();
var billingQueue = new QueueBuilder()
.SetName("Billing")
.SetDescription("Billing and account inquiries")
.SetMaxContacts(50)
.SetOutboundCallerId("Acme Billing", "+18005553000")
.AddTag("Department", "Billing")
.Build();
// Add all to stack
stack.AddQueue(salesQueue, "BusinessHours");
stack.AddQueue(supportQueue, "ExtendedHours");
stack.AddQueue(billingQueue, "BusinessHours");Using Queues in Contact Flows
Once you've created queues, reference them in contact flows:
Simple Transfer
var flow = new FlowBuilder()
.SetName("TransferToSupport")
.PlayPrompt("Transferring you to customer support")
.TransferToQueue("CustomerSupport")
.Build();IVR Menu with Multiple Queues
var flow = new FlowBuilder()
.SetName("DepartmentMenu")
.GetCustomerInput("Press 1 for sales, 2 for support, or 3 for billing")
.Branch(branch =>
{
branch.Case("1", "sales-transfer");
branch.Case("2", "support-transfer");
branch.Case("3", "billing-transfer");
branch.Otherwise("default-queue");
})
.PlayPrompt("Transferring to sales", "sales-transfer")
.TransferToQueue("Sales")
.Build();
// Add queues before flow
stack.AddQueue(salesQueue);
stack.AddQueue(supportQueue);
stack.AddQueue(billingQueue);
stack.AddFlow(flow); // Now flow can reference queuesQueue Priority Routing
Route VIP customers to priority queue:
var flow = new FlowBuilder()
.SetName("VIPRouter")
.InvokeLambda("CustomerLookup")
.Branch(branch =>
{
branch.When("$.External.CustomerType == \"VIP\"", "vip-queue");
branch.Otherwise("standard-queue");
})
.PlayPrompt("Transferring to our VIP support team", "vip-queue")
.TransferToQueue("VIPSupport")
.PlayPrompt("Transferring to customer support", "standard-queue")
.TransferToQueue("CustomerSupport")
.Build();Queue Best Practices
1. Set Realistic Capacity Limits
Match queue capacity to your staffing:
// If you have 10 agents, don't allow 500 callers in queue
var queue = new QueueBuilder()
.SetName("Support")
.SetMaxContacts(50) // 5x your agent count
.Build();Rule of thumb: 3-5x your average agent count
2. Use Descriptive Names
Queue names show up in reports and agent dashboards:
// Good - Clear and descriptive
.SetName("TechnicalSupportTier2")
.SetName("SpanishBillingSupport")
// Bad - Vague or cryptic
.SetName("Queue1")
.SetName("Q_TS_2")3. Tag Consistently
Apply consistent tags across all queues:
var standardTags = new Dictionary<string, string>
{
["Environment"] = "Production",
["ManagedBy"] = "CDK"
};
var queue = new QueueBuilder()
.SetName("Sales")
.AddTag("Department", "Sales")
.AddTag("Environment", standardTags["Environment"])
.AddTag("ManagedBy", standardTags["ManagedBy"])
.Build();4. Always Associate Hours
Link queues to hours of operation schedules:
// Create hours first
var hours = CreateBusinessHours();
stack.AddHoursOfOperation(hours);
// Then associate with queue
stack.AddQueue(queue, "BusinessHours");This enables flows to check queue availability.
5. Plan for Overflow
Create overflow queues for high-volume scenarios:
var mainQueue = new QueueBuilder()
.SetName("Support")
.SetMaxContacts(100)
.Build();
var overflowQueue = new QueueBuilder()
.SetName("SupportOverflow")
.SetMaxContacts(50)
.Build();
stack.AddQueue(mainQueue);
stack.AddQueue(overflowQueue);6. Use Outbound Caller ID Strategically
Set meaningful caller IDs for callback scenarios:
var queue = new QueueBuilder()
.SetName("Sales")
.SetOutboundCallerId(
"Acme Sales - Return Call", // Shows to customer
"+18005551234" // Must be claimed in Connect
)
.Build();Common Queue Configurations
24/7 Support Queue
var hours24x7 = new HoursOfOperation
{
Name = "24x7",
TimeZone = "UTC"
};
for (var day = DayOfWeek.Sunday; day <= DayOfWeek.Saturday; day++)
{
hours24x7.AddDayConfig(new HoursOfOperationConfig
{
Day = day,
StartTime = new TimeRange { Hours = 0, Minutes = 0 },
EndTime = new TimeRange { Hours = 23, Minutes = 59 }
});
}
stack.AddHoursOfOperation(hours24x7);
var supportQueue = new QueueBuilder()
.SetName("24x7Support")
.SetMaxContacts(200)
.Build();
stack.AddQueue(supportQueue, "24x7");Business Hours Only Queue
var businessHours = new HoursOfOperation
{
Name = "BusinessHours",
TimeZone = "America/New_York"
};
// Monday-Friday 9am-5pm
for (var day = DayOfWeek.Monday; day <= DayOfWeek.Friday; day++)
{
businessHours.AddDayConfig(new HoursOfOperationConfig
{
Day = day,
StartTime = new TimeRange { Hours = 9, Minutes = 0 },
EndTime = new TimeRange { Hours = 17, Minutes = 0 }
});
}
stack.AddHoursOfOperation(businessHours);
var salesQueue = new QueueBuilder()
.SetName("Sales")
.SetMaxContacts(50)
.Build();
stack.AddQueue(salesQueue, "BusinessHours");Multi-Language Queues
var englishQueue = new QueueBuilder()
.SetName("EnglishSupport")
.SetDescription("English-speaking support agents")
.AddTag("Language", "English")
.Build();
var spanishQueue = new QueueBuilder()
.SetName("SpanishSupport")
.SetDescription("Spanish-speaking support agents")
.AddTag("Language", "Spanish")
.Build();
var frenchQueue = new QueueBuilder()
.SetName("FrenchSupport")
.SetDescription("French-speaking support agents")
.AddTag("Language", "French")
.Build();
stack.AddQueue(englishQueue, "BusinessHours");
stack.AddQueue(spanishQueue, "BusinessHours");
stack.AddQueue(frenchQueue, "BusinessHours");Troubleshooting Queues
Issue: Queue Not Found in Flow
Problem:
var flow = new FlowBuilder()
.SetName("TransferFlow")
.TransferToQueue("NonExistentQueue")
.Build();
stack.AddFlow(flow); // Deployment fails!Solution: Create and add the queue before the flow:
var queue = new QueueBuilder()
.SetName("NonExistentQueue")
.Build();
stack.AddQueue(queue); // Add queue first
stack.AddFlow(flow); // Then add flowIssue: Invalid Max Contacts
Problem:
var queue = new QueueBuilder()
.SetName("BadQueue")
.SetMaxContacts(0) // Invalid!
.Build();Error: ArgumentException: MaxContacts must be greater than 0
Solution: Set a positive number:
var queue = new QueueBuilder()
.SetName("GoodQueue")
.SetMaxContacts(50) // Valid
.Build();Issue: Hours of Operation Not Found
Problem:
stack.AddQueue(queue, "NonExistentHours"); // Hours not created!Error: InvalidOperationException: Hours of operation 'NonExistentHours' not found
Solution: Create hours before referencing:
var hours = new HoursOfOperation
{
Name = "NonExistentHours",
TimeZone = "UTC"
};
hours.AddDayConfig(/* ... */);
stack.AddHoursOfOperation(hours); // Add hours first
stack.AddQueue(queue, "NonExistentHours"); // Then referenceNext Steps
Now that you understand queues, explore these related topics:
- Building Routing Profiles - Assign queues to agents
- Business Hours - Configure queue schedules
- Building Flows - Route calls to queues
- Complete Example - Build a full contact center
Quick Reference
Basic Queue Template
var queue = new QueueBuilder()
.SetName("QueueName")
.SetDescription("Optional description")
.SetMaxContacts(100)
.SetOutboundCallerId("Display Name", "+18005551234")
.AddTag("Department", "Sales")
.Build();
stack.AddQueue(queue, "BusinessHours");Queue Configuration Checklist
- [ ] Unique, descriptive name
- [ ] Appropriate max contacts limit
- [ ] Associated with hours of operation
- [ ] Outbound caller ID configured (if needed)
- [ ] Tags applied for organization
- [ ] Referenced in contact flows
- [ ] Added to routing profiles
Common Queue Patterns
// Simple queue
var simple = new QueueBuilder()
.SetName("Support")
.Build();
// Full-featured queue
var advanced = new QueueBuilder()
.SetName("VIPSupport")
.SetDescription("Priority VIP queue")
.SetMaxContacts(50)
.SetOutboundCallerId("VIP Team", "+18005559999")
.AddTag("Priority", "High")
.Build();
// Multiple department queues
var sales = new QueueBuilder().SetName("Sales").Build();
var support = new QueueBuilder().SetName("Support").Build();
var billing = new QueueBuilder().SetName("Billing").Build();
// Add to stack
stack.AddQueue(sales, "BusinessHours");
stack.AddQueue(support, "ExtendedHours");
stack.AddQueue(billing, "BusinessHours");Getting Help
If you run into issues:
- Check the Stack API Reference for queue methods
- Review Complete Example for working queue setup
- Explore the Examples for common patterns
- File an issue on GitHub