Skip to content

Outbound Campaign event-based with percentage table.

0

I want to be able to run amazon connect outbound campaign event-based with a percentage table. I don't want all my calls to be trigger at the same time instead from my total I want to be able to send the call in batch during the day based on percentage.

What is the based approach? Because I don't see how regular configuration can handle this. I was thinking doing something like this:

Ingest --- the list arrives

1. Client writes CSV batches to the input bucket.

Files land between early morning, it could be several per day. Destination is the S3 input bucket.

2. Each file arriving fires an S3 event notification, which invokes the Load Lambda. No polling, no schedule --- arrival is the trigger.

3. The Load Lambda writes every row into the DynamoDB tracking store with status = pending, and increments the day's running total.

That running total is the reason the throttle works: the day's size isn't known when the first file lands, so it grows as batches arrive.

Release --- calls go out a slice at a time

4. EventBridge Scheduler fires the Release Lambda hourly, on cron job. 

5. The Release Lambda reads the percentage schedule from the DynamoDB config table.

6. It claims that hour's subset from the tracking store and the cumulative percentage of the running total, capped at 1.5x the hour's nominal share so a late batch can't spike the queues.

7. It submits them via PutOutboundRequestBatch, in chunks of 25, to the Connect outbound campaign. The campaign is agentless, created with no source, AMD enabled.

8. Connect places the call, and the contact flow runs: AMD, no profile lookup (assuming that PutOutboundRequestBatch can send the attributes to Connect), trigger flow configuration from Lambda, language branch, Set Voice, Get Prompts, then either play a prompt or hand off to the menu.

9. The customer receives the call.

Return --- results go back

10. Connect writes contact records to the Kinesis stream as calls complete.

11. A Lambda consumes them, maps each outcome to a numeric code, and writes result, time and attempt back onto the tracking record.

12. Client collects the data, then the tables are purged.

2 Answers
1

Your proposed architecture is a solid approach for distributing outbound campaign calls throughout the day based on percentage allocations. Since Amazon Connect Outbound Campaigns now supports hourly segment refresh (reduced from the previous 24-hour minimum), you can leverage this native capability as part of your solution, though your custom orchestration layer still provides valuable control for percentage-based throttling.

Here's how to optimize your approach:

Leverage Native Hourly Refresh: Configure your campaign to refresh segments hourly. This allows the campaign to pick up newly eligible customers throughout the day rather than in a single batch. However, this alone won't give you percentage-based distribution control.

Your Custom Throttling Layer: Your proposed architecture using DynamoDB tracking, EventBridge Scheduler, and a Release Lambda is the right approach for percentage-based distribution. The key elements work well:

  • Using S3 event notifications to trigger ingestion eliminates polling overhead
  • Tracking records in DynamoDB with a running total gives you the denominator for percentage calculations
  • The hourly EventBridge Scheduler firing your Release Lambda provides the cadence for batch releases
  • Capping each hour at 1.5x nominal share is a smart safeguard against late-arriving batches causing spikes
  • Using PutOutboundRequestBatch in chunks of 25 is the correct API approach for submitting contacts programmatically

Important Considerations:

  1. Campaign Quotas: Be aware of two critical limits - concurrent active calls and calls per second (CPS). Your percentage-based throttling helps, but monitor CloudWatch metrics like ThrottledCalls, CallsBreachingConcurrencyQuota, and ConcurrentCallsPercentage to ensure you're not hitting quota ceilings during peak hours.

  2. Contact Priority: If certain contacts are more important, you can configure priority ordering based on up to 10 profile attributes. Initial dial attempts always take precedence over reattempts, maintaining your priority throughout execution.

  3. Agentless Campaign Setup: Creating the campaign with no source and using PutOutboundRequestBatch is correct for your event-driven model. You can pass attributes directly with each batch submission.

  4. Monitoring: Beyond Kinesis for outcomes, also monitor campaign-level CloudWatch metrics to detect throttling patterns early. If you see concentrated throttle events in specific hours, you may need to adjust your percentage distribution.

Your architecture provides the granular control needed for percentage-based distribution that native campaign scheduling doesn't offer directly. The combination of hourly segment refresh capability with your custom throttling layer gives you both flexibility and control over call pacing throughout the day.
Sources
Amazon Connect outbound campaigns now supports hourly segment refresh - AWS
Amazon Connect Outbound Campaigns now supports contact priority ordering - AWS
Amazon Connect Outbound Campaigns V2 - Amazon Connect Customer
How to Diagnose Amazon Connect Outbound Campaign Throttling Using CloudWatch and CloudTrail | AWS re:Post

answered 4 days ago

1
  • PutOutboundRequestBatch is a standard API for Campaigns V2, and your understanding of the 25-item-per-batch limit is correct. Injecting records via API into a campaign that wasn't created with a source file is an intended use case.
  • For agentless campaigns, the dialingCapacity parameter (ranging from 0.01 to 1) allows you to control the allocation of dialing capacity across campaigns. However, since this controls the rate per second rather than a percentage allocation based on time of day, your decision to implement external logic to manage this is sound.
  • Please use UpdateCampaignCommunicationTime in conjunction with this. Currently, EventBridge cron is the only mechanism for time-based control, leaving a risk of calls being placed late at night due to a Lambda bug; you should implement a safety mechanism on the service side as well.

The system fails in scenarios where, for example, you start with 1,000 records in the morning and add 9,000 more at midday. If you allocate 10% (100 records) based on a total of 1,000 records at 9:00 AM, that initial allocation effectively becomes 1% once the total reaches 10,000. The "1.5x cap" only limits sudden spikes; it does not solve this underlying issue.

You need to choose one of the following approaches:

  • Option A: Fixed denominator — Agree with the client that "all files must arrive by X AM" and finalize the count after the deadline. This makes behavior predictable.
  • Option B: Remaining-count based — Redefine the logic to "allocate remaining records based on remaining time." Added files are automatically redistributed to subsequent time slots, eliminating the need for a cumulative counter.

Throttling handling (Critical)

RequestThrottled signals that you should stop sending and wait due to insufficient capacity. You need logic to examine the failedRequests and successfulRequests in the response, return failed requests to a "pending" state, and implement backoff when throttling occurs.

expirationTime

It is recommended to set this for a time a few minutes in the future. Since submitting a full hour's worth of records at once could result in most of them expiring, the design needs to break the batch down into smaller slices.

Idempotency

Generate the clientToken deterministically based on the record ID. Random generation leads to duplicate calls during Lambda retries.

API Rate Limits

Quotas apply at the account/region level and are shared across instances. Calculate the time required to send a full hour's worth of requests and verify that it fits within the 15-minute Lambda execution limit.

DynamoDB

  • A Global Secondary Index (GSI) is essential for retrieving "pending" records. Using status alone as a key creates a hot partition; use a composite key like status#shard to distribute the load.
  • Updating a single item for a cumulative counter causes contention (adopting "Plan B" eliminates this issue).
  • Since there is no TRUNCATE operation, use TTL (Time to Live) to clear the table. Deletions can be delayed by up to 48 hours, so implement date filters on the query side as well.

Result Collection

We recommend using EventBridge contact events alongside CTRs. While dispositions (e.g., EXPIRED, TELECOM_PROBLEM) can be tracked via either contact records or contact events, CTRs are written only after the call completes, delaying the detection of cases where the call could not be placed.

Other Undefined Items

Retry design (attempt counts are recorded, but re-submission logic is missing), alignment with concurrent call quotas, DNC/opt-out cross-referencing, and monitoring of RequestThrottled error rates.

answered 4 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.